{"owner":"zama-ai","repo":"fhevm","hasSkills":true,"totalSkillsCount":14,"totalTokensCount":12024,"categories":["subagent-persona","anthropic-skill","claude-rule"],"hasMcp":false,"mcpConfig":null,"found":["sdk/cli-js-sdk/docs/agents/CLI.md","coprocessor/docs/references/fhevm_api.md","coprocessor/docs/references/gateway_api.md","sdk/cli-js-sdk/docs/agents/ARCHITECTURE.md","relayer-http/CLAUDE.md","gateway-contracts/docs/references/selectors.md","sdk/cli-js-sdk/docs/agents/TESTING.md","sdk/cli-js-sdk/packages/cli/package.json","sdk/cli-js-sdk/docs/agents/ENGINE.md","sdk/cli-js-sdk/packages/load-test/tsconfig.json","sdk/cli-js-sdk/packages/toolkit/package.json","sdk/cli-js-sdk/packages/toolkit/tsconfig.json","sdk/cli-js-sdk/packages/load-test/docs/OPERATIONS.md","sdk/cli-js-sdk/packages/load-test/docs/design/dual-relayer-dispatch.md"],"skills":{"sdk/cli-js-sdk/docs/agents/CLI.md":"# CLI\n\nUse these tools for CLI work:\n\n- `commander` for CLI interface\n- `@commander-js/extra-typings` for TypeScript types\n- `consola` for Elegant Console Wrapper\n- `@pnpm/tabtab` for shell tab completion\n\nBehavioral guidance:\n\n- Keep progress and status logs on stderr.\n- Keep the final machine-readable response on stdout as JSON.\n- Update `README.md` examples and this guidance when changing command behavior, options, outputs, defaults, or supported flows.\n- Global options may be passed before or after subcommands; use `optsWithGlobals()` from the command action context.\n- The CLI ships as the `fhevm-sdk` binary (`packages/cli/bin/fhevm-sdk.mjs`, exposed via `pnpm link` run from `packages/cli`) and runs compiled `packages/cli/dist/index.mjs`; run `pnpm run build` before linking or using `pnpm run cli`.\n- Use `pnpm run cli:dev` for source-mode CLI checks without rebuilding.\n- The workspace-root `.env` is loaded by `packages/cli/src/env.ts` relative to the repository, not the working directory; shell variables take precedence.\n- `completion-server` is invoked by tabtab's shell templates; the binary routes it to `packages/cli/bin/completion-server.mjs` before loading `tsx` or runtime flow modules. Keep its stdout limited to completion items.\n- Keep completion metadata in `packages/cli/bin/completion-server.mjs` aligned with command help whenever changing commands, options, choices, or descriptions.\n- Keep CLI command modules free of top-level flow imports. Runtime flow modules should be loaded with dynamic imports inside `.action()` handlers so help and completion startup stay fast.\n- FHETest is the only contract target, except `token transfer`/`token balance`, which target ERC-7984 confidential tokens and require `--contract` since there is no per-network token default.\n- Networks may target different host chains; do not assume Ethereum Sepolia for every network.\n- Keep decrypt-family naming consistent: the `direct` subcommand does direct handle decryption, while `fresh` and `stored` are FHETest demo subcommands.\n- The decrypt family roots (`user-decrypt`, `public-decrypt`, `delegated-user-decrypt`) are pure dispatchers with no options of their own; their `direct` subcommands decrypt existing `--handle` values from any contract, where `--contract` is the ACL pairing contract and defaults to FHETest. A bare root command with no subcommand prints help.\n- `fresh` creates or stores a new FHETest handle before decrypting.\n- `stored` reads an existing FHETest handle from the wallet/account/delegator type slots (defaulting to the bool slot); it has no `--handle`.\n- Public decrypt `fresh` stores with `makePublic=true`.\n- User decrypt and delegated user decrypt `fresh` store with `makePublic=false`.\n- Delegated flows use `PRIVATE_KEY`/`MNEMONIC` for the delegate and `DELEGATOR_PRIVATE_KEY`/`DELEGATOR_MNEMONIC` for the encrypted data owner.\n- `fhe-test inspect` is read-only. Keep raw `--handle` inspection mutually exclusive with account/type inspection.\n- `fhe-test inspect --type <type>` defaults `--account` to the wallet address loaded from `PRIVATE_KEY`/`MNEMONIC` when no account is provided.\n- `fhe-test init --bulk` calls the contract-level all-types initializer and is mutually exclusive with `--type`.\n- `fhe-test init --type <type>` may be repeated to initialize selected types without bulk mode.\n- `fhe-test init` returns `transactionHashes` as an array because non-bulk initialization may send one transaction per initialized type.\n- `fhe-test op` exposes FHETest operator demos as explicit subcommands, not as a generic `--type` flag. Keep operation names aligned with the underlying behavior, such as `add-uint64` and `xor-uint256`.\n- `token transfer` uses `confidentialTransferFrom` when `--from` is set, spending an existing operator allowance instead of the loaded wallet's own balance.\n- `token transfer` returns `transferredHandle` because ERC-7984 does not revert on insufficient balance; the token ACL lets the recipient (not the sender) decrypt it with `user-decrypt direct --handle <transferredHandle> --contract <token address>`.\n- `token transfer --verify` decrypts the sender balance before/after and reports `deltaMatches` (`balanceBefore - balanceAfter === <requested amount>`); it is rejected together with `--from` because the operator wallet cannot decrypt the `--from` account's balance.\n- `token balance --account` defaults to the wallet address loaded from `PRIVATE_KEY`/`MNEMONIC` when omitted.\n","coprocessor/docs/references/fhevm_api.md":"# FHEVM API specifications\n","coprocessor/docs/references/gateway_api.md":"# Gateway API Specifications\n\n## Endpoints\n\n<details>\n  <summary>GET /keyurl ---- Retrieve links for retrieving the public keys and CRS' in the system.</summary>\n\n#### Description\n\nThis endpoint returns a JSON object containing URLs from an S3 bucket, allowing the client to download key files such as the blockchain public key, CRS files for input proof generation, the bootstrap key, and the address and public verification keys for each of the MPC servers running the TKMS.\n\nFor each file (with the exception of the verification key and address), a list of cryptographic signatures is provided to ensure the integrity and authenticity of the downloaded content. These signatures should be considered as a multi-sig. This means that instead of needing all the signatures to validate the content, only a subset, specifically >1/3 of the total signatures (if n nodes are signing), is required to verify that the content is legitimate. \n\nNo query parameters are required, as the gateway is already preconfigured for a specific blockchain.\n\n\n#### Query Parameters\n\nNo parameters.\n\n#### Headers\n\nNone.\n\n#### Response\n\n**Success (200 OK)**\n\nThe request is successful, and the response will include a JSON object with a `status` and a `response`. The response again consists of the following elements: \n- `crs`: A map of containing information on the different CRS'. The key of the map is the max amount of bits the CRS can support proofs for. The value is an object of the following elements for the given CRS:\n    * `data_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the CRS.\n    * `param_choice`: An integer representing the choice of parameters for the public key to be used with the CRS. \n    * `signatures`: A list of signatures (one from each MPC party constituting the TKMS backend). Each signature is a hex (lower-case) encoded EIP712 signature on the `safe_serialization` of `PublicParam<Bls12_446>`.\n    * `urls`: A list of URLs where the data can be fetched. The data at the end-point is a `safe_serialization` of `PublicParam<Bls12_446>`.\n- `fhe_key_info`: A list of objects, each representing information on a key-set in the system. More specifically each element consists of the following:\n    * `fhe_public_key`: An element which contains information about the public encryption key of a FHE key set. More specifically it consists of the following elements:\n        * `data_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the key.\n        * `param_choice`: An integer representing the choice of parameters used to generate the key. \n        * `signatures`: A list of signatures (one from each MPC party constituting the TKMS backend). Each signature is a hex (lower-case) encoded EIP712 signature on the `safe_serialization` of `CompactPublicKey`.\n        * `urls`: A list of URLs where the data can be fetched. The data at the end-point is a `safe_serialization` of `CompactPublicKey`.\n    * `fhe_server_key`: An element which contains information about the server key (the key used to perform FHE operations on ciphertexts) of a FHE key set. More specifically it consists of the following elements:\n        * `data_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the key.\n        * `param_choice`: An integer representing the choice of parameters used to generate the key. \n        * `signatures`: A list of signatures (one from each MPC party constituting the TKMS backend). Each signature is a hex (lower-case) encoded EIP712 signature on the `safe_serialization` of `CompactPublicKey`.\n        * `urls`: A list of URLs where the data can be fetched. The data at the end-point is a `safe_serialization` of `ServerKey`.\n- `verf_public_key`: **Deprecated and will be removed in the future. Should instead be fetched directly from the config contract on the TKMS blockchain** A list containing of elements, where each element is the information about a TKMS MPC server's signing key. That is, the key which a server uses to sign requests. More specifically each element of the vector consists of the following:\n        * `key_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the key. Currently this value is static for signing keys. That is, it will always be `408d8cbaa51dece7f782fe04ba0b1c1d017b1088`.\n        * `server_id`: The integer ID of the server whose key is being described in the current element. This is an integer in the range [1; n], where n is the amount of MPC servers.\n        * `verf_public_key_url`: The URL end-point of the given server where a serialization of the signing key can be found. The signing key is a `safe_serialization` of `PublicSigKey`.\n        * `verf_public_key_address`: The URL end-point of the given server where a file containing the human-readable Ethereum address of the server's signing key.\n\nFor example the following:\n\n```json\n{\n    \"response\": {\n        \"crs\": {\n            \"256\": {\n                \"data_id\": \"d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\",\n                \"param_choice\": 1,\n                \"signatures\": [\n                    \"0d13...\",\n                    \"4250...\",\n                    \"a42c...\",\n                    \"fhb5...\"\n                ],\n                \"urls\": [\n                    \"https://s3.amazonaws.com/bucket-name-1/PUB-p1/CRS/d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\",\n                    \"https://s3.amazonaws.com/bucket-name-4/PUB-p4/CRS/d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\",\n                    \"https://s3.amazonaws.com/bucket-name-2/PUB-p2/CRS/d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\",\n                    \"https://s3.amazonaws.com/bucket-name-3/PUB-p3/CRS/d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\"\n                ]\n            }\n        },\n        \"fhe_key_info\": [\n            {\n                \"fhe_public_key\": {\n                    \"data_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                    \"param_choice\": 1,\n                    \"signatures\": [\n                        \"cdff...\",\n                        \"123c...\",\n                        \"00ff...\",\n                        \"a367...\"\n                    ],\n                    \"urls\": [\n                        \"https://s3.amazonaws.com/bucket-name-1/PUB-p1/PublicKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-4/PUB-p4/PublicKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-2/PUB-p2/PublicKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-3/PUB-p3/PublicKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n                    ]\n                },\n                \"fhe_server_key\": {\n                    \"data_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                    \"param_choice\": 1,\n                    \"signatures\": [\n                        \"839b...\",\n                        \"baef...\",\n                        \"55cc...\",\n                        \"81a4...\"\n                    ],\n                    \"urls\": [\n                        \"https://s3.amazonaws.com/bucket-name-1/PUB-p1/ServerKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-4/PUB-p4/ServerKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-2/PUB-p2/ServerKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-3/PUB-p3/ServerKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n                    ]\n                }\n            }\n        ],\n        \"verf_public_key\": [\n            {\n                \"key_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"server_id\": 1,\n                \"verf_public_key_address\": \"https://s3.amazonaws.com/bucket-name-1/PUB-p1/VerfAddress/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"verf_public_key_url\": \"https://s3.amazonaws.com/bucket-name-1/PUB-p1/VerfKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n            },\n            {\n                \"key_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"server_id\": 4,\n                \"verf_public_key_address\": \"https://s3.amazonaws.com/bucket-name-4/PUB-p4/VerfAddress/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"verf_public_key_url\": \"https://s3.amazonaws.com/bucket-name-4//PUB-p4/VerfKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n            },\n            {\n                \"key_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"server_id\": 2,\n                \"verf_public_key_address\": \"https://s3.amazonaws.com/bucket-name-2/PUB-p2/VerfAddress/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"verf_public_key_url\": \"https://s3.amazonaws.com/bucket-name-2/PUB-p2/VerfKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n            },\n            {\n                \"key_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"server_id\": 3,\n                \"verf_public_key_address\": \"https://s3.amazonaws.com/bucket-name-3/PUB-p3/VerfAddress/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"verf_public_key_url\": \"https://s3.amazonaws.com/bucket-name-3/PUB-p3/VerfKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n            }\n        ]\n    },\n    \"status\": \"success\"\n}\n```\n\n**Error Responses**\n\n| Status Code | Error Code   | Description                                      |\n| ----------- | ------------ | ------------------------------------------------ |\n| 400         | `BadRequest` | The request is invalid or missing required parameters. |\n| 404         | `NotFound`   | The requested resource was not found.            |\n| 500         | `ServerError` | An internal server error occurred.                   |\n\n#### Example Error Responses\n\n```json\n{\n  \"error\": \"BadRequest\",\n  \"message\": \"The request is invalid or missing required parameters.\"\n}\n```\n\n```json\n{\n  \"error\": \"NotFound\",\n  \"message\": \"The requested resource was not found.\"\n}\n```\n\n```json\n{\n  \"error\": \"ServerError\",\n  \"message\": \"An internal server error occurred. Please try again later.\"\n}\n```\n\n</details>\n\n<details>\n  <summary>POST /verify_proven_ct ---- Input a batch of proven ciphertexts to be validated by the TKMS.</summary>\n\n#### Description\n\nThis endpoint returns a JSON object containing all the signatures on the proven ciphertexts from the TKMS servers. Furthermore the response contains some meta-information distinguishing if the response is for the co-processor setting or FHEVM native setting. In case of the co-processor setting, then the ciphertext storage handles and a signature from the co-processor attesting correct storage is also included.\n\nThe signatures from the TKMS should be considered as a multi-sig. This means that instead of needing all the signatures to validate the content, only a subset, specifically >1/3 of the total signatures, is required to verify that the content is legitimate. \n\n#### Query Parameters\n\nMultiple parameters must be supplied in JSON format:\n- `contract_address`: An EIP-55 encoded address (that is, including the `0x` prefix) of the contract where the proven ciphertext is to be submitted.\n- `caller_address`: An EIP-55 encoded address (that is, including the `0x` prefix) of the user who is providing the encrypted input.\n- `crs_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the CRS used to construct the proof.\n- `key_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the public key used to encrypt the ciphertext with.\n- `ct_proof`: A hex encoding of the serialization of the proven ciphertext. More specifically the TFHE-RS object `ProvenCompactCiphertextList` serialized using `safe_serialization`.\n\n```json\n{\n    \"contract_address\": \"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed\",\n    \"caller_address\": \"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb\" ,\n    \"crs_id\": \"d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\",\n    \"key_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n    \"ct_proof\": \"cdff...\",\n}\n```\n\n#### Headers\n\nNone.\n\n#### Response\n\n**Success (200 OK)**\n\nThe request is successful, and the response will include a JSON object with a `status` and a `response` which  consists of the following:\n\n- `handles`: A vector of handles to each of the ciphertexts which have been proven knowledge of. A handle is a 32 byte (lower-case) hex encoded handle/ID identifying the ciphertext.\n- `kms_signatures`: A list of signatures (one for each of the TKMS servers that respond to the query). Each signature is a hex (lower-case) encoded EIP712 signature on the `safe_serialization` of `ProvenCompactCiphertextList`.\n- `listener_type`: An enum expressing whether the result is for an FHEVM native (`FHEVM_NATIVE`) or co-processor respectively (`COPROCESSOR`).\n- `proof_of_storage`: An optional signature from the co-processor. More specifically if FHEVM native is used it will be an empty string, otherwise it will be a hex (lower-case) encoded EIP712 signature on the request. \n\nFor example the following:\n```json\n{\n    \"response\": {\n        \"handles\": [\n            \"0748b542afe2353c86cb707e3d21044b0be1fd18efc7cbaa6a415af055bfb358\",\n            \"054ab4515b1541878723431005054f154e15e45e15800adb67879679df670456\"\n        ],\n        \"kms_signatures\":[\n            \"15a4f9a8eb61459cfba7d103d8f911fb04ce91ecf841b34c49c0d56a70b896d20cbc31986188f91efc3842b7df215cee8acb40178daedb8b63d0ba5d199bce121c\", \n            \"118165165165423465234414c4c468a4d9684d8e18186d6f786161b4b436c58787cc68418186d6f786161b4b98461166a6a6668e8e118542c154867aab238abd79\", \n            \"1c849848940128065242121b2b12121ed876986da251561650c654564d684654e51610879a9a9798b78b78e7f8787d87c8c8894a454547809586616161464cc8a8\", \n            \"10c864ac145423466798808098c098b09a8908d6432da4544f5e54566b76740454654a54c65454565d65d657e44651241561342441234128888063304854897893\", \n        ],\n        \"listener_type\": \"COPROCESSOR\",\n        \"proof_of_storage\": \"17acd15648740c00849f489498489e4600a60a06068d484b084894988333000cff798751651498d68768753567a4356787c45787e79i8f64d128218927897c8789\"\n    },\n    \"status\": \"success\"\n}\n```\n\n**Error Responses**\n\n| Status Code | Error Code   | Description                                      |\n| ----------- | ------------ | ------------------------------------------------ |\n| 400         | `BadRequest` | The request is invalid or missing required parameters. |\n| 404         | `NotFound`   | The requested resource was not found.            |\n| 500         | `ServerError` | An internal server error occurred.                   |\n\n#### Example Error Responses\n\n```json\n{\n  \"error\": \"BadRequest\",\n  \"message\": \"The request is invalid or missing required parameters.\"\n}\n```\n\n```json\n{\n  \"error\": \"NotFound\",\n  \"message\": \"The requested resource was not found.\"\n}\n```\n\n```json\n{\n  \"error\": \"ServerError\",\n  \"message\": \"An internal server error occurred. Please try again later.\"\n}\n```\n\n</details>\n\n<details>\n  <summary>POST /reencrypt ---- Decrypt a ciphertext under an ephemeral key s.t. a client can learn the decrypted value privately.</summary>\n\n#### Description\n\nThis end-point returns a JSON object containing a signcryption of the plaintext value of an FHE ciphertext that has been (obliviously) decrypted by the TKMS. \nMore specifically the TKMS servers carry out a partial decryption resulting in each of them knowing a secret share of the plaintext (meaning that multiple servers need to maliciously collude in order to learn the decrypted plaintext). They each then signcrypt their share of the plaintext. The response consists of each of these signcryptions along with meta information about the threshold setup and which server provides each signcrypted share of the result. \nSince the signcryption is based on secret sharing it means that only a subset, specifically >1/3 of the total responses, is required to recover the result (assuming all returned signcryptions are correct). \n\n#### Query Parameters\n\nMultiple parameters must be supplied in JSON format:\n- `signature`: A hex (lower-case) encoded EIP712 signature on the public encryption key, `enc_key`, under which the of the ciphertext in question will be reencrypted. \n- `client_address`: An EIP-55 encoded address (that is, including the `0x` prefix) of the end-user who is supposed to learn the reencrypted response.\n- `enc_key`: The hex (lower-case) encoded public encryption key (libsodium) which the reencryption should be signcrypted under.\n- `ciphertext_handle`: The 32 byte (lower-case) hex encoded handle/ID identifying the ciphertext and hence allowing the gateway to fetch it.\n- `eip712_verifying_contract`: An EIP-55 encoded address (that is, including the `0x` prefix) of the contract holding the ciphertext to reencrypt.\n```json\n{\n     \"signature\": \"15a4f9a8eb61459cfba7d103d8f911fb04ce91ecf841b34c49c0d56a70b896d20cbc31986188f91efc3842b7df215cee8acb40178daedb8b63d0ba5d199bce121c\",\n     \"client_address\": \"0x17853A630aAe15AED549B2B874de08B73C0F59c5\",\n     \"enc_key\": \"2000000000000000df2fcacb774f03187f3802a27259f45c06d33cefa68d9c53426b15ad531aa822\",\n     \"ciphertext_handle\": \"0748b542afe2353c86cb707e3d21044b0be1fd18efc7cbaa6a415af055bfb358\",\n     \"eip712_verifying_contract\": \"0x66f9664f97F2b50F62D13eA064982f936dE76657\"\n}\n```\n\n#### Headers\n\nNone.\n\n#### Response\n\n**Success (200 OK)**\n\nThe request is successful, and the response will include a JSON object with a `status` and a `response` which is a list of responses from each TKMS. More specifically each element in the list consists of the following:\n- `payload`: A bincode encoding of the signcryption from a single server along with meta information including the server ID, threshold parameter, type of value encrypted and the specific public key of the server supplying the specific response. \n- `signature`: An EIP712 signature which is hex (low-case) encoded.\n\nFor example the following:\n```json\n{\n    \"response\": [\n        {\n            \"payload\": \"161c5...\",\n            \"signature\": \"15a4f9a8eb61459cfba7d103d8f911fb04ce91ecf841b34c49c0d56a70b896d20cbc31986188f91efc3842b7df215cee8acb40178daedb8b63d0ba5d199bce121c\"\n        },\n        {\n            \"payload\": \"44546...\",\n            \"signature\": \"118165165165423465234414c4c468a4d9684d8e18186d6f786161b4b436c58787cc68418186d6f786161b4b98461166a6a6668e8e118542c154867aab238abd79\"\n        },\n        {\n            \"payload\": \"54cd5...\",\n            \"signature\": \"1c849848940128065242121b2b12121ed876986da251561650c654564d684654e51610879a9a9798b78b78e7f8787d87c8c8894a454547809586616161464cc8a8\"\n        },\n        {\n            \"payload\": \"a516b...\",\n            \"signature\": \"10c864ac145423466798808098c098b09a8908d6432da4544f5e54566b76740454654a54c65454565d65d657e44651241561342441234128888063304854897893\"\n        },\n    ],\n    \"status\": \"success\"\n}\n```\n\n**Error Responses**\n\n| Status Code | Error Code   | Description                                      |\n| ----------- | ------------ | ------------------------------------------------ |\n| 400         | `BadRequest` | The request is invalid or missing required parameters. |\n| 404         | `NotFound`   | The requested resource was not found.            |\n| 500         | `ServerError` | An internal server error occurred.                   |\n\n#### Example Error Responses\n\n```json\n{\n  \"error\": \"BadRequest\",\n  \"message\": \"The request is invalid or missing required parameters.\"\n}\n```\n\n```json\n{\n  \"error\": \"NotFound\",\n  \"message\": \"The requested resource was not found.\"\n}\n```\n\n```json\n{\n  \"error\": \"ServerError\",\n  \"message\": \"An internal server error occurred. Please try again later.\"\n}\n```\n\n</details>","sdk/cli-js-sdk/docs/agents/ARCHITECTURE.md":"# Architecture\n\nThe repository is a pnpm workspace. Use the existing boundaries when adding behavior.\n\n## Packages\n\n- `packages/toolkit` (`@cli-fhevm-sdk/toolkit`): the library layer. It wraps `@fhevm/sdk` and FHETest with importable flows and must not depend on CLI packages (`commander`, `consola`, `@pnpm/tabtab`).\n- `packages/cli` (`cli-fhevm-sdk`): commander command registration and the `fhevm-sdk` binary. It consumes the toolkit through `@cli-fhevm-sdk/toolkit` package imports (root export or deep subpaths such as `@cli-fhevm-sdk/toolkit/flows/input-proof`), never through relative paths.\n- `packages/load-test` (`@cli-fhevm-sdk/load-test`): a private operator application, not a publishable SDK library. It owns load models, durable pools, raw relayer wire validation, collectors, reports, baselines, and its Commander surface. It may use public `@fhevm/sdk` entry points directly for SDK-native workload journeys and proof workers, and uses the toolkit for shared network, account, contract, ACL, and value behavior. Load orchestration must not move into toolkit.\n\nThe toolkit's `exports` map points at TypeScript source; the CLI build (`tsdown`) bundles the toolkit into `packages/cli/dist/` via `deps.alwaysBundle` while keeping npm dependencies external. Because of that, the toolkit's runtime npm dependencies must also be declared in `packages/cli/package.json`.\n\n## Toolkit boundaries (`packages/toolkit/src`)\n\n- `flows`: orchestration only. Compose config, SDK, contract, ACL, transaction, and value helpers here. Group command families into subfolders such as `fhe-test`, `public-decrypt`, `user-decrypt`, `delegated-user-decrypt`, and `token`.\n- `fhevm`: `@fhevm/sdk` adapters and SDK response normalization.\n- `fhe-test`: FHETest ABI and contract reads/writes.\n- `token`: ERC-7984 confidential token ABI and contract reads/writes.\n- `acl`: ACL delegation reads/writes.\n- `config`: network registry, runtime config, account loading, and client contexts.\n- `values`: clear-value parsing, random values, and JSON serialization helpers.\n- `shared`: cross-cutting helpers like progress and transaction waiting.\n- `types.ts`: networks, FHE value types, and flow result types shared across packages.\n- `index.ts`: the public API barrel; keep new public functions exported from here. Deep subpath exports stay available for lazy loading.\n\nKeep SDK integration on entry points declared by `@fhevm/sdk`; do not resolve or\nimport files from its private `_esm`, `_cjs`, or internal source layout. Toolkit\npermit APIs use seconds, matching `@fhevm/sdk`. Human-facing CLI options may use\ndays, but must convert at the CLI boundary.\n\nCustom FHEVM chains must include the host-chain `protocolConfig` contract used\nby the SDK to resolve the protocol and compatible WASM versions.\n\n## CLI boundaries (`packages/cli`)\n\n- `src/cli`: command registration, argument parsing, stdout/stderr behavior.\n- `bin/completion-server.mjs`: static tab completion resolver. It must stay lightweight and must not import TypeScript runtime, SDK clients, config, or flows.\n\nWhen adding a command, prefer:\n\n1. CLI module in `packages/cli/src/cli/commands`.\n2. Flow module in the matching `packages/toolkit/src/flows/<command-family>` folder.\n3. Adapter changes only at the boundary being crossed.\n\nKeep raw SDK response casts and raw contract calls out of CLI and flow code when practical.\nKeep expensive flow and SDK imports inside command actions, not at CLI module top level.\n\n## Load-test boundaries (`packages/load-test/src`)\n\n- `scenario` and `suite`: validated workload data, exact flow allocation, pool planning, and sequential suite orchestration.\n- `runner` and `flows`: scheduler lifecycle plus one executor per relayer flow.\n- `relayer`: bounded, runtime-validated raw HTTP protocol adapters. Never trust wire data through TypeScript casts.\n- `pool`: durable pool schemas, writers, cursors, and on-chain/off-chain preparation.\n- `collectors` and `report`: optional observations, strict versioned report schema, rendering, comparison, and explicit baseline blessing.\n- `cli`: argument parsing and lazy action wiring only.\n\nReport and baseline reads must pass the versioned runtime schema. A missing\nbaseline may skip a comparison; a corrupt or incompatible baseline must fail.\nBaseline mutation belongs only to the explicit `baseline bless` command and is\nstaged only after every suite report validates.\n","relayer-http/CLAUDE.md":"# relayer-http — development guide\n\nThis file is living: add a rule or change a description here whenever a feature lands that affects them, in the same\nchange. It describes a minimal first version.\n\n## What this repo is\n\nThe Zama relayer over HTTP. It replaces the gateway-chain decryption path: request handlers receive the SDK's\ndecryption requests and the `kms_aggregator` module fans them out to the KMS connector endpoints and aggregates the\nt-of-n answers.\n\n**Minimal first version**: the handlers and the fan-out/aggregation only.\n- No ACL check and no ciphertext-commit (readiness) check in the relayer: the connector's worker performs them and their\n  failures come back as connector error codes. Both can come back later as optional modules in front of the aggregator.\n- No database, no queue, no cache, no response storage.\n\n## Layout\n\n```\nrelayer-http/\n├── Cargo.toml, Cargo.lock, rust-toolchain.toml   # workspace, exact dependency pins (=x.y.z), toolchain 1.97.1\n├── Dockerfile                                     # container image, built from the repository root (see Container image)\n├── .gitignore                                     # target/, config/*.local.yaml (local variants of the configuration)\n├── config/config.yaml                             # example configuration: name, log, http, kms_aggregator\n├── dev/                                           # local development tooling: Makefile, per-topology configs, proxy port-forwards, flow scripts; start with its README.md\n└── crates/relayer-http/src/\n    ├── main.rs                # load config → init logging → App → serve until SIGINT/SIGTERM → drain → exit\n    ├── lib.rs                 # App: the one shared state (both aggregators, http config, shutdown token)\n    ├── config.rs              # RelayerConfig, LogConfig, HttpConfig: YAML + APP_<SECTION>__<FIELD> overrides\n    ├── logging.rs             # tracing subscriber (json | pretty | compact, RUST_LOG) + Log: one request's identifiers on every line\n    ├── endpoint/              # the HTTP layer; start with its docs.md\n    │   ├── mod.rs             # router() and serve()\n    │   ├── error.rs           # ApiError: the one error body and its mapping\n    │   ├── validate.rs        # rules shared by the routes (handles, extraData)\n    │   ├── ops.rs             # GET /liveness, GET /healthz\n    │   └── flows/{mod,user_decrypt,public_decrypt}.rs   # one file per route: wire types, validation, handler (logs each step)\n    └── kms_aggregator/        # fan-out to the KMS connectors and t-of-n aggregation; start with its docs.md\n        ├── mod.rs, config.rs, client.rs, call.rs, aggregator.rs\n        ├── flows/{mod,user_decrypt,public_decrypt}.rs   # one file per flow: checks, counting, output\n        ├── mock.rs, scenarios.rs                       # test only: scripted connector, YAML scenario runner\n        └── scenarios/*.yaml                            # behaviour scenarios, run by cargo test\n```\n\nTwo modules, each with its `docs.md` next to the code: `endpoint/docs.md` (routes, payloads, responses, every\nerror code and its mapping) and `kms_aggregator/docs.md` (how an aggregation runs, one node call, checks,\nconfiguration → behaviour). The implementation plans live outside the repository (`relayer_specs_plans/`).\n\n## Configuration\n\nOne YAML file (`config/config.yaml` is the example), four sections: `name`, `log` (optional, defaults to JSON\nlines), `http` (bind address, body limit, body read timeout, supported chain ids) and `kms_aggregator` (deadline,\nretries, thresholds, optional checks, the KMS endpoints). Any field can be overridden with `APP_<SECTION>__<FIELD>` (durations carry a\nunit, e.g. `APP_KMS_AGGREGATOR__CALL__TIMEOUT=7s`). API keys are never in the file: each endpoint names the env var\nholding its key. Local variants go to `config/*.local.yaml`, ignored by git.\n\n## Commands\n\nFrom `relayer-http/`:\n\n```sh\ncargo fmt -- --check      # not --all: cargo-fmt would follow the kms-connector-api path dependency into generated bindings\ncargo clippy --workspace --all-targets -- -W clippy::perf -W clippy::suspicious -W clippy::style -D warnings\ncargo test --workspace\ncargo test -p relayer-http yaml_scenarios          # the aggregator scenarios only\ncargo run -p relayer-http -- config/config.yaml    # needs the KMS_<i>_API_KEY env vars named in the config\n```\n\nEvery change must pass the first three. Check exit codes strictly (a grep on the output hides a failing build).\n\nAgainst the local fhevm stack: `make -C dev up` (connector proxies and their host port-forwards), `make -C dev run`\n(the relayer with the config matching the running topology), `make -C dev public-decrypt` / `user-decrypt` (one flow\neach, from the e2e container), `make -C dev check` (the three commands above). See `dev/README.md`.\n\n## Container image\n\n`Dockerfile` follows the relayer's and the kms-connector's model: the golden `rust-glibc` builder pinned by\n`RUST_IMAGE_VERSION` (single source of truth: `rust-toolchain.toml`, read by the CI template), `cargo build --locked\n--release`, a `glibc-dynamic` runtime running as the `fhevm` user, no configuration baked in. The build context is the\n**repository root**: the crate depends on `kms-connector/crates/api` by path and that workspace references its\nsiblings, which the Dockerfile copies at the same relative places.\n\n```sh\n# from the repository root\ndocker build -f relayer-http/Dockerfile --build-arg RUST_IMAGE_VERSION=1.97.1 -t relayer-http .\ndocker run --rm -p 8080:8080 -v \"$PWD/relayer-http/config/config.yaml:/app/config/config.yaml:ro\" \\\n  -e KMS_00_API_KEY=... relayer-http            # the config is mounted at /app/config/config.yaml\n```\n\nCI publishes the image as `ghcr.io/zama-ai/fhevm/relayer-http` through `.github/workflows/relayer-http-docker-build.yml`\n(pushes to `main`/`release/*`, releases, manual runs, or a call from the e2e orchestrator). The two other workflows,\n`relayer-http-tests.yml` and `relayer-http-dependency-analysis.yml`, run on pull requests: the three commands above,\nthen `cargo update -w --locked`, `cargo-deny check license` against `deny.toml` (every allowed license must be used)\nand `cargo-audit audit` with `.cargo/audit.toml`. All three are gated on changes under `relayer-http/**`,\n`kms-connector/crates/api/**` and `kms-connector/Cargo.toml`.\n\n## Rules\n\n**No gateway interaction.** The relayer never talks to the gateway chain and carries no gateway-specific\nconfiguration, optional checks included. Every on-chain read goes to a host chain through host contracts, Ethereum\nbeing the reference.\n\n**No unexpected panic.** Both crate roots deny `clippy::unwrap_used`, `expect_used`, `indexing_slicing` and `panic`\n(allowed in tests). Every failure is a typed error returned to the caller. Configuration validation bounds every value\nthe runtime arithmetic relies on (`call.timeout <= 60s`, `backoff_max <= call.timeout`, semaphore size capped) so that no\narithmetic can overflow later. A panic inside a spawned task is counted as a failure, never propagated.\n\n**Fail fast.** Never wait for something that cannot change the outcome: when `counted + pending < threshold` the\nremaining calls are cancelled at once. One deadline per request, no queue, no ETA; the client retries.\n\n**HPA compatible.** No per-request state outside the request's own future: no shared map, no registry, no sticky\nsession. Every replica is identical; the call semaphore is per pod. If per-request state is ever needed, it goes behind\na trait so that Redis (or another store) can back it later.\n\n**Errors.** Modules return typed errors (`thiserror`), with what the caller needs to act (counts, dominant connector\nerror). Errors are logged once, at the boundary that answers the client. No `error!` inside a module for an expected\nfailure.\n\n**Logging.** `tracing` only, structured fields, short messages. Every endpoint line about a request goes through its\n`Log` (`logging.rs`) and carries `request_id`, `flow`, `handles`, `decryption_id`, the last two `none` until known:\na known event is a method on `Log`, any other line is `log!(level, log, fields…, \"message\")`. Aggregator lines carry\nthe same identifiers through the `aggregation` span; a task spawned for a request inherits it (`in_current_span`).\nEvery failed node attempt is one `warn`. Never log request or response bodies, shares, signatures, header values or\nURLs. The subscriber is installed by `main`, never by a module; `log:` is optional and defaults to JSON lines\n(`log.format`: `json` | `pretty` | `compact`, plus the relayer's `show_*` switches); the level filter is `RUST_LOG`,\ndefault `warn,relayer_http=info`.\n\n**Configuration.** Nested structs use `deny_unknown_fields`; `validate()` messages name the field with its dotted path\n(`kms_aggregator.call.timeout must …`); secrets appear only as env var names; durations carry a unit.\n\n**Minimal code.** Few types, one function per loop, a one-line doc comment per item, no framework where a function does.\nProduction-ready means no panic, typed errors, logs, cancellation and tests, not features.\n\n**Compatibility.** The connector interface comes from the `kms-connector-api` crate (path dependency, never its\n`endpoint` feature): DTOs, routes, error codes and their `retryable` flag are used as they are, never redefined.\n\n**Tests.** A unit test per function, next to it. Paused tokio time (`start_paused`) for anything timed, so durations\nare exact and tests are instant. Behaviour is described in YAML scenarios run by `cargo test`; adding a case is adding\na file.\n\n**Documentation.** Every module has a `docs.md` produced with the module and updated in the same change as any\nbehaviour change, plus a one-line doc comment on every item. The error code table in `endpoint/docs.md` (every code,\nits status, when it happens, how aggregation errors map to it) is updated in the same change as any change to that\nmapping. This `CLAUDE.md` is updated the same way: new rules and\nchanged descriptions land with the feature that motivates them.\n","gateway-contracts/docs/references/selectors.md":"## Smart Contract selectors\n\nAll smart contract selectors can be found in the [contract selectors](../../selectors.txt) file.\n","sdk/cli-js-sdk/docs/agents/TESTING.md":"# Testing\n\nUse pnpm scripts for verification.\n\n```bash\npnpm run typecheck\npnpm run test\npnpm run build\n```\n\nFor CLI changes, also run relevant help or parser checks, for example:\n\n```bash\npnpm --silent run cli --help\npnpm --silent run cli user-decrypt --help\npnpm --silent run cli delegated-user-decrypt --help\n```\n\nFor load-test changes, validate its complete private package and inspect the\naffected command groups:\n\n```bash\npnpm --filter @cli-fhevm-sdk/load-test run typecheck\npnpm --filter @cli-fhevm-sdk/load-test run test\npnpm load-test --help\npnpm load-test pool --help\npnpm load-test report --help\npnpm load-test baseline --help\n```\n\nAvoid network-dependent checks unless the user asks for them or credentials/RPC access are available.\n\nUnit tests must cover unit conversions and SDK adapter request shapes. In\nparticular, assert permit durations are sent to `@fhevm/sdk` as\n`durationSeconds`; type-checking alone does not catch semantic unit regressions.\n","sdk/cli-js-sdk/packages/cli/package.json":"{\n  \"name\": \"cli-fhevm-sdk\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"bin\": {\n    \"fhevm-sdk\": \"./bin/fhevm-sdk.mjs\"\n  },\n  \"engines\": {\n    \"node\": \">=22.0.0\"\n  },\n  \"scripts\": {\n    \"build\": \"tsdown\",\n    \"cli\": \"node dist/index.mjs\",\n    \"cli:dev\": \"node --import tsx index.ts\",\n    \"test\": \"vitest run\",\n    \"typecheck\": \"tsc --noEmit\"\n  },\n  \"devDependencies\": {\n    \"tsdown\": \"^0.22.2\",\n    \"tsx\": \"^4.21.0\",\n    \"vitest\": \"^3.2.4\"\n  },\n  \"dependencies\": {\n    \"@cli-fhevm-sdk/toolkit\": \"workspace:*\",\n    \"@commander-js/extra-typings\": \"^15.0.0\",\n    \"@fhevm/sdk\": \"0.13.2\",\n    \"@pnpm/tabtab\": \"^0.5.4\",\n    \"commander\": \"^15.0.0\",\n    \"consola\": \"^3.4.2\",\n    \"viem\": \"^2.50.4\"\n  }\n}\n","sdk/cli-js-sdk/docs/agents/ENGINE.md":"# TypeScript Engine\n\nDefault to Node.js with pnpm. The repository is a pnpm workspace (`packages/*`); run root scripts from the workspace root and use `pnpm --filter <package>` to target one package.\n\n- Use `pnpm install` for dependency installation.\n- Use `pnpm run <script>` for package scripts.\n- Use `pnpm exec <binary>` for local binaries.\n- Use `pnpm dlx <package> <command>` for one-off package execution.\n- Use `tsx` for running TypeScript entry points in development.\n- Use `tsdown` via `pnpm run build` for the compiled CLI artifact.\n- Use `tsc --noEmit` for type-checking.\n\n## APIs\n\n- Read environment variables from `process.env`.\n- Prefer built-in Node APIs for filesystem, path, URL, and process behavior.\n- This project targets Node.js 22 or newer because `@fhevm/sdk` requires it.\n","sdk/cli-js-sdk/packages/load-test/tsconfig.json":"# Load-test Skill\n\nPath: `sdk/cli-js-sdk/packages/load-test/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/load-test/tsconfig.json)","sdk/cli-js-sdk/packages/toolkit/package.json":"# Toolkit Skill\n\nPath: `sdk/cli-js-sdk/packages/toolkit/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/toolkit/package.json)","sdk/cli-js-sdk/packages/toolkit/tsconfig.json":"# Toolkit Skill\n\nPath: `sdk/cli-js-sdk/packages/toolkit/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/toolkit/tsconfig.json)","sdk/cli-js-sdk/packages/load-test/docs/OPERATIONS.md":"# Docs Skill\n\nPath: `sdk/cli-js-sdk/packages/load-test/docs/OPERATIONS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/load-test/docs/OPERATIONS.md)","sdk/cli-js-sdk/packages/load-test/docs/design/dual-relayer-dispatch.md":"# Design Skill\n\nPath: `sdk/cli-js-sdk/packages/load-test/docs/design/dual-relayer-dispatch.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/load-test/docs/design/dual-relayer-dispatch.md)"},"files":{"sdk/cli-js-sdk/docs/agents/CLI.md":"# CLI\n\nUse these tools for CLI work:\n\n- `commander` for CLI interface\n- `@commander-js/extra-typings` for TypeScript types\n- `consola` for Elegant Console Wrapper\n- `@pnpm/tabtab` for shell tab completion\n\nBehavioral guidance:\n\n- Keep progress and status logs on stderr.\n- Keep the final machine-readable response on stdout as JSON.\n- Update `README.md` examples and this guidance when changing command behavior, options, outputs, defaults, or supported flows.\n- Global options may be passed before or after subcommands; use `optsWithGlobals()` from the command action context.\n- The CLI ships as the `fhevm-sdk` binary (`packages/cli/bin/fhevm-sdk.mjs`, exposed via `pnpm link` run from `packages/cli`) and runs compiled `packages/cli/dist/index.mjs`; run `pnpm run build` before linking or using `pnpm run cli`.\n- Use `pnpm run cli:dev` for source-mode CLI checks without rebuilding.\n- The workspace-root `.env` is loaded by `packages/cli/src/env.ts` relative to the repository, not the working directory; shell variables take precedence.\n- `completion-server` is invoked by tabtab's shell templates; the binary routes it to `packages/cli/bin/completion-server.mjs` before loading `tsx` or runtime flow modules. Keep its stdout limited to completion items.\n- Keep completion metadata in `packages/cli/bin/completion-server.mjs` aligned with command help whenever changing commands, options, choices, or descriptions.\n- Keep CLI command modules free of top-level flow imports. Runtime flow modules should be loaded with dynamic imports inside `.action()` handlers so help and completion startup stay fast.\n- FHETest is the only contract target, except `token transfer`/`token balance`, which target ERC-7984 confidential tokens and require `--contract` since there is no per-network token default.\n- Networks may target different host chains; do not assume Ethereum Sepolia for every network.\n- Keep decrypt-family naming consistent: the `direct` subcommand does direct handle decryption, while `fresh` and `stored` are FHETest demo subcommands.\n- The decrypt family roots (`user-decrypt`, `public-decrypt`, `delegated-user-decrypt`) are pure dispatchers with no options of their own; their `direct` subcommands decrypt existing `--handle` values from any contract, where `--contract` is the ACL pairing contract and defaults to FHETest. A bare root command with no subcommand prints help.\n- `fresh` creates or stores a new FHETest handle before decrypting.\n- `stored` reads an existing FHETest handle from the wallet/account/delegator type slots (defaulting to the bool slot); it has no `--handle`.\n- Public decrypt `fresh` stores with `makePublic=true`.\n- User decrypt and delegated user decrypt `fresh` store with `makePublic=false`.\n- Delegated flows use `PRIVATE_KEY`/`MNEMONIC` for the delegate and `DELEGATOR_PRIVATE_KEY`/`DELEGATOR_MNEMONIC` for the encrypted data owner.\n- `fhe-test inspect` is read-only. Keep raw `--handle` inspection mutually exclusive with account/type inspection.\n- `fhe-test inspect --type <type>` defaults `--account` to the wallet address loaded from `PRIVATE_KEY`/`MNEMONIC` when no account is provided.\n- `fhe-test init --bulk` calls the contract-level all-types initializer and is mutually exclusive with `--type`.\n- `fhe-test init --type <type>` may be repeated to initialize selected types without bulk mode.\n- `fhe-test init` returns `transactionHashes` as an array because non-bulk initialization may send one transaction per initialized type.\n- `fhe-test op` exposes FHETest operator demos as explicit subcommands, not as a generic `--type` flag. Keep operation names aligned with the underlying behavior, such as `add-uint64` and `xor-uint256`.\n- `token transfer` uses `confidentialTransferFrom` when `--from` is set, spending an existing operator allowance instead of the loaded wallet's own balance.\n- `token transfer` returns `transferredHandle` because ERC-7984 does not revert on insufficient balance; the token ACL lets the recipient (not the sender) decrypt it with `user-decrypt direct --handle <transferredHandle> --contract <token address>`.\n- `token transfer --verify` decrypts the sender balance before/after and reports `deltaMatches` (`balanceBefore - balanceAfter === <requested amount>`); it is rejected together with `--from` because the operator wallet cannot decrypt the `--from` account's balance.\n- `token balance --account` defaults to the wallet address loaded from `PRIVATE_KEY`/`MNEMONIC` when omitted.\n","coprocessor/docs/references/fhevm_api.md":"# FHEVM API specifications\n","coprocessor/docs/references/gateway_api.md":"# Gateway API Specifications\n\n## Endpoints\n\n<details>\n  <summary>GET /keyurl ---- Retrieve links for retrieving the public keys and CRS' in the system.</summary>\n\n#### Description\n\nThis endpoint returns a JSON object containing URLs from an S3 bucket, allowing the client to download key files such as the blockchain public key, CRS files for input proof generation, the bootstrap key, and the address and public verification keys for each of the MPC servers running the TKMS.\n\nFor each file (with the exception of the verification key and address), a list of cryptographic signatures is provided to ensure the integrity and authenticity of the downloaded content. These signatures should be considered as a multi-sig. This means that instead of needing all the signatures to validate the content, only a subset, specifically >1/3 of the total signatures (if n nodes are signing), is required to verify that the content is legitimate. \n\nNo query parameters are required, as the gateway is already preconfigured for a specific blockchain.\n\n\n#### Query Parameters\n\nNo parameters.\n\n#### Headers\n\nNone.\n\n#### Response\n\n**Success (200 OK)**\n\nThe request is successful, and the response will include a JSON object with a `status` and a `response`. The response again consists of the following elements: \n- `crs`: A map of containing information on the different CRS'. The key of the map is the max amount of bits the CRS can support proofs for. The value is an object of the following elements for the given CRS:\n    * `data_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the CRS.\n    * `param_choice`: An integer representing the choice of parameters for the public key to be used with the CRS. \n    * `signatures`: A list of signatures (one from each MPC party constituting the TKMS backend). Each signature is a hex (lower-case) encoded EIP712 signature on the `safe_serialization` of `PublicParam<Bls12_446>`.\n    * `urls`: A list of URLs where the data can be fetched. The data at the end-point is a `safe_serialization` of `PublicParam<Bls12_446>`.\n- `fhe_key_info`: A list of objects, each representing information on a key-set in the system. More specifically each element consists of the following:\n    * `fhe_public_key`: An element which contains information about the public encryption key of a FHE key set. More specifically it consists of the following elements:\n        * `data_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the key.\n        * `param_choice`: An integer representing the choice of parameters used to generate the key. \n        * `signatures`: A list of signatures (one from each MPC party constituting the TKMS backend). Each signature is a hex (lower-case) encoded EIP712 signature on the `safe_serialization` of `CompactPublicKey`.\n        * `urls`: A list of URLs where the data can be fetched. The data at the end-point is a `safe_serialization` of `CompactPublicKey`.\n    * `fhe_server_key`: An element which contains information about the server key (the key used to perform FHE operations on ciphertexts) of a FHE key set. More specifically it consists of the following elements:\n        * `data_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the key.\n        * `param_choice`: An integer representing the choice of parameters used to generate the key. \n        * `signatures`: A list of signatures (one from each MPC party constituting the TKMS backend). Each signature is a hex (lower-case) encoded EIP712 signature on the `safe_serialization` of `CompactPublicKey`.\n        * `urls`: A list of URLs where the data can be fetched. The data at the end-point is a `safe_serialization` of `ServerKey`.\n- `verf_public_key`: **Deprecated and will be removed in the future. Should instead be fetched directly from the config contract on the TKMS blockchain** A list containing of elements, where each element is the information about a TKMS MPC server's signing key. That is, the key which a server uses to sign requests. More specifically each element of the vector consists of the following:\n        * `key_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the key. Currently this value is static for signing keys. That is, it will always be `408d8cbaa51dece7f782fe04ba0b1c1d017b1088`.\n        * `server_id`: The integer ID of the server whose key is being described in the current element. This is an integer in the range [1; n], where n is the amount of MPC servers.\n        * `verf_public_key_url`: The URL end-point of the given server where a serialization of the signing key can be found. The signing key is a `safe_serialization` of `PublicSigKey`.\n        * `verf_public_key_address`: The URL end-point of the given server where a file containing the human-readable Ethereum address of the server's signing key.\n\nFor example the following:\n\n```json\n{\n    \"response\": {\n        \"crs\": {\n            \"256\": {\n                \"data_id\": \"d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\",\n                \"param_choice\": 1,\n                \"signatures\": [\n                    \"0d13...\",\n                    \"4250...\",\n                    \"a42c...\",\n                    \"fhb5...\"\n                ],\n                \"urls\": [\n                    \"https://s3.amazonaws.com/bucket-name-1/PUB-p1/CRS/d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\",\n                    \"https://s3.amazonaws.com/bucket-name-4/PUB-p4/CRS/d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\",\n                    \"https://s3.amazonaws.com/bucket-name-2/PUB-p2/CRS/d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\",\n                    \"https://s3.amazonaws.com/bucket-name-3/PUB-p3/CRS/d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\"\n                ]\n            }\n        },\n        \"fhe_key_info\": [\n            {\n                \"fhe_public_key\": {\n                    \"data_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                    \"param_choice\": 1,\n                    \"signatures\": [\n                        \"cdff...\",\n                        \"123c...\",\n                        \"00ff...\",\n                        \"a367...\"\n                    ],\n                    \"urls\": [\n                        \"https://s3.amazonaws.com/bucket-name-1/PUB-p1/PublicKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-4/PUB-p4/PublicKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-2/PUB-p2/PublicKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-3/PUB-p3/PublicKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n                    ]\n                },\n                \"fhe_server_key\": {\n                    \"data_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                    \"param_choice\": 1,\n                    \"signatures\": [\n                        \"839b...\",\n                        \"baef...\",\n                        \"55cc...\",\n                        \"81a4...\"\n                    ],\n                    \"urls\": [\n                        \"https://s3.amazonaws.com/bucket-name-1/PUB-p1/ServerKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-4/PUB-p4/ServerKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-2/PUB-p2/ServerKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-3/PUB-p3/ServerKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n                    ]\n                }\n            }\n        ],\n        \"verf_public_key\": [\n            {\n                \"key_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"server_id\": 1,\n                \"verf_public_key_address\": \"https://s3.amazonaws.com/bucket-name-1/PUB-p1/VerfAddress/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"verf_public_key_url\": \"https://s3.amazonaws.com/bucket-name-1/PUB-p1/VerfKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n            },\n            {\n                \"key_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"server_id\": 4,\n                \"verf_public_key_address\": \"https://s3.amazonaws.com/bucket-name-4/PUB-p4/VerfAddress/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"verf_public_key_url\": \"https://s3.amazonaws.com/bucket-name-4//PUB-p4/VerfKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n            },\n            {\n                \"key_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"server_id\": 2,\n                \"verf_public_key_address\": \"https://s3.amazonaws.com/bucket-name-2/PUB-p2/VerfAddress/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"verf_public_key_url\": \"https://s3.amazonaws.com/bucket-name-2/PUB-p2/VerfKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n            },\n            {\n                \"key_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"server_id\": 3,\n                \"verf_public_key_address\": \"https://s3.amazonaws.com/bucket-name-3/PUB-p3/VerfAddress/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"verf_public_key_url\": \"https://s3.amazonaws.com/bucket-name-3/PUB-p3/VerfKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n            }\n        ]\n    },\n    \"status\": \"success\"\n}\n```\n\n**Error Responses**\n\n| Status Code | Error Code   | Description                                      |\n| ----------- | ------------ | ------------------------------------------------ |\n| 400         | `BadRequest` | The request is invalid or missing required parameters. |\n| 404         | `NotFound`   | The requested resource was not found.            |\n| 500         | `ServerError` | An internal server error occurred.                   |\n\n#### Example Error Responses\n\n```json\n{\n  \"error\": \"BadRequest\",\n  \"message\": \"The request is invalid or missing required parameters.\"\n}\n```\n\n```json\n{\n  \"error\": \"NotFound\",\n  \"message\": \"The requested resource was not found.\"\n}\n```\n\n```json\n{\n  \"error\": \"ServerError\",\n  \"message\": \"An internal server error occurred. Please try again later.\"\n}\n```\n\n</details>\n\n<details>\n  <summary>POST /verify_proven_ct ---- Input a batch of proven ciphertexts to be validated by the TKMS.</summary>\n\n#### Description\n\nThis endpoint returns a JSON object containing all the signatures on the proven ciphertexts from the TKMS servers. Furthermore the response contains some meta-information distinguishing if the response is for the co-processor setting or FHEVM native setting. In case of the co-processor setting, then the ciphertext storage handles and a signature from the co-processor attesting correct storage is also included.\n\nThe signatures from the TKMS should be considered as a multi-sig. This means that instead of needing all the signatures to validate the content, only a subset, specifically >1/3 of the total signatures, is required to verify that the content is legitimate. \n\n#### Query Parameters\n\nMultiple parameters must be supplied in JSON format:\n- `contract_address`: An EIP-55 encoded address (that is, including the `0x` prefix) of the contract where the proven ciphertext is to be submitted.\n- `caller_address`: An EIP-55 encoded address (that is, including the `0x` prefix) of the user who is providing the encrypted input.\n- `crs_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the CRS used to construct the proof.\n- `key_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the public key used to encrypt the ciphertext with.\n- `ct_proof`: A hex encoding of the serialization of the proven ciphertext. More specifically the TFHE-RS object `ProvenCompactCiphertextList` serialized using `safe_serialization`.\n\n```json\n{\n    \"contract_address\": \"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed\",\n    \"caller_address\": \"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb\" ,\n    \"crs_id\": \"d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\",\n    \"key_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n    \"ct_proof\": \"cdff...\",\n}\n```\n\n#### Headers\n\nNone.\n\n#### Response\n\n**Success (200 OK)**\n\nThe request is successful, and the response will include a JSON object with a `status` and a `response` which  consists of the following:\n\n- `handles`: A vector of handles to each of the ciphertexts which have been proven knowledge of. A handle is a 32 byte (lower-case) hex encoded handle/ID identifying the ciphertext.\n- `kms_signatures`: A list of signatures (one for each of the TKMS servers that respond to the query). Each signature is a hex (lower-case) encoded EIP712 signature on the `safe_serialization` of `ProvenCompactCiphertextList`.\n- `listener_type`: An enum expressing whether the result is for an FHEVM native (`FHEVM_NATIVE`) or co-processor respectively (`COPROCESSOR`).\n- `proof_of_storage`: An optional signature from the co-processor. More specifically if FHEVM native is used it will be an empty string, otherwise it will be a hex (lower-case) encoded EIP712 signature on the request. \n\nFor example the following:\n```json\n{\n    \"response\": {\n        \"handles\": [\n            \"0748b542afe2353c86cb707e3d21044b0be1fd18efc7cbaa6a415af055bfb358\",\n            \"054ab4515b1541878723431005054f154e15e45e15800adb67879679df670456\"\n        ],\n        \"kms_signatures\":[\n            \"15a4f9a8eb61459cfba7d103d8f911fb04ce91ecf841b34c49c0d56a70b896d20cbc31986188f91efc3842b7df215cee8acb40178daedb8b63d0ba5d199bce121c\", \n            \"118165165165423465234414c4c468a4d9684d8e18186d6f786161b4b436c58787cc68418186d6f786161b4b98461166a6a6668e8e118542c154867aab238abd79\", \n            \"1c849848940128065242121b2b12121ed876986da251561650c654564d684654e51610879a9a9798b78b78e7f8787d87c8c8894a454547809586616161464cc8a8\", \n            \"10c864ac145423466798808098c098b09a8908d6432da4544f5e54566b76740454654a54c65454565d65d657e44651241561342441234128888063304854897893\", \n        ],\n        \"listener_type\": \"COPROCESSOR\",\n        \"proof_of_storage\": \"17acd15648740c00849f489498489e4600a60a06068d484b084894988333000cff798751651498d68768753567a4356787c45787e79i8f64d128218927897c8789\"\n    },\n    \"status\": \"success\"\n}\n```\n\n**Error Responses**\n\n| Status Code | Error Code   | Description                                      |\n| ----------- | ------------ | ------------------------------------------------ |\n| 400         | `BadRequest` | The request is invalid or missing required parameters. |\n| 404         | `NotFound`   | The requested resource was not found.            |\n| 500         | `ServerError` | An internal server error occurred.                   |\n\n#### Example Error Responses\n\n```json\n{\n  \"error\": \"BadRequest\",\n  \"message\": \"The request is invalid or missing required parameters.\"\n}\n```\n\n```json\n{\n  \"error\": \"NotFound\",\n  \"message\": \"The requested resource was not found.\"\n}\n```\n\n```json\n{\n  \"error\": \"ServerError\",\n  \"message\": \"An internal server error occurred. Please try again later.\"\n}\n```\n\n</details>\n\n<details>\n  <summary>POST /reencrypt ---- Decrypt a ciphertext under an ephemeral key s.t. a client can learn the decrypted value privately.</summary>\n\n#### Description\n\nThis end-point returns a JSON object containing a signcryption of the plaintext value of an FHE ciphertext that has been (obliviously) decrypted by the TKMS. \nMore specifically the TKMS servers carry out a partial decryption resulting in each of them knowing a secret share of the plaintext (meaning that multiple servers need to maliciously collude in order to learn the decrypted plaintext). They each then signcrypt their share of the plaintext. The response consists of each of these signcryptions along with meta information about the threshold setup and which server provides each signcrypted share of the result. \nSince the signcryption is based on secret sharing it means that only a subset, specifically >1/3 of the total responses, is required to recover the result (assuming all returned signcryptions are correct). \n\n#### Query Parameters\n\nMultiple parameters must be supplied in JSON format:\n- `signature`: A hex (lower-case) encoded EIP712 signature on the public encryption key, `enc_key`, under which the of the ciphertext in question will be reencrypted. \n- `client_address`: An EIP-55 encoded address (that is, including the `0x` prefix) of the end-user who is supposed to learn the reencrypted response.\n- `enc_key`: The hex (lower-case) encoded public encryption key (libsodium) which the reencryption should be signcrypted under.\n- `ciphertext_handle`: The 32 byte (lower-case) hex encoded handle/ID identifying the ciphertext and hence allowing the gateway to fetch it.\n- `eip712_verifying_contract`: An EIP-55 encoded address (that is, including the `0x` prefix) of the contract holding the ciphertext to reencrypt.\n```json\n{\n     \"signature\": \"15a4f9a8eb61459cfba7d103d8f911fb04ce91ecf841b34c49c0d56a70b896d20cbc31986188f91efc3842b7df215cee8acb40178daedb8b63d0ba5d199bce121c\",\n     \"client_address\": \"0x17853A630aAe15AED549B2B874de08B73C0F59c5\",\n     \"enc_key\": \"2000000000000000df2fcacb774f03187f3802a27259f45c06d33cefa68d9c53426b15ad531aa822\",\n     \"ciphertext_handle\": \"0748b542afe2353c86cb707e3d21044b0be1fd18efc7cbaa6a415af055bfb358\",\n     \"eip712_verifying_contract\": \"0x66f9664f97F2b50F62D13eA064982f936dE76657\"\n}\n```\n\n#### Headers\n\nNone.\n\n#### Response\n\n**Success (200 OK)**\n\nThe request is successful, and the response will include a JSON object with a `status` and a `response` which is a list of responses from each TKMS. More specifically each element in the list consists of the following:\n- `payload`: A bincode encoding of the signcryption from a single server along with meta information including the server ID, threshold parameter, type of value encrypted and the specific public key of the server supplying the specific response. \n- `signature`: An EIP712 signature which is hex (low-case) encoded.\n\nFor example the following:\n```json\n{\n    \"response\": [\n        {\n            \"payload\": \"161c5...\",\n            \"signature\": \"15a4f9a8eb61459cfba7d103d8f911fb04ce91ecf841b34c49c0d56a70b896d20cbc31986188f91efc3842b7df215cee8acb40178daedb8b63d0ba5d199bce121c\"\n        },\n        {\n            \"payload\": \"44546...\",\n            \"signature\": \"118165165165423465234414c4c468a4d9684d8e18186d6f786161b4b436c58787cc68418186d6f786161b4b98461166a6a6668e8e118542c154867aab238abd79\"\n        },\n        {\n            \"payload\": \"54cd5...\",\n            \"signature\": \"1c849848940128065242121b2b12121ed876986da251561650c654564d684654e51610879a9a9798b78b78e7f8787d87c8c8894a454547809586616161464cc8a8\"\n        },\n        {\n            \"payload\": \"a516b...\",\n            \"signature\": \"10c864ac145423466798808098c098b09a8908d6432da4544f5e54566b76740454654a54c65454565d65d657e44651241561342441234128888063304854897893\"\n        },\n    ],\n    \"status\": \"success\"\n}\n```\n\n**Error Responses**\n\n| Status Code | Error Code   | Description                                      |\n| ----------- | ------------ | ------------------------------------------------ |\n| 400         | `BadRequest` | The request is invalid or missing required parameters. |\n| 404         | `NotFound`   | The requested resource was not found.            |\n| 500         | `ServerError` | An internal server error occurred.                   |\n\n#### Example Error Responses\n\n```json\n{\n  \"error\": \"BadRequest\",\n  \"message\": \"The request is invalid or missing required parameters.\"\n}\n```\n\n```json\n{\n  \"error\": \"NotFound\",\n  \"message\": \"The requested resource was not found.\"\n}\n```\n\n```json\n{\n  \"error\": \"ServerError\",\n  \"message\": \"An internal server error occurred. Please try again later.\"\n}\n```\n\n</details>","sdk/cli-js-sdk/docs/agents/ARCHITECTURE.md":"# Architecture\n\nThe repository is a pnpm workspace. Use the existing boundaries when adding behavior.\n\n## Packages\n\n- `packages/toolkit` (`@cli-fhevm-sdk/toolkit`): the library layer. It wraps `@fhevm/sdk` and FHETest with importable flows and must not depend on CLI packages (`commander`, `consola`, `@pnpm/tabtab`).\n- `packages/cli` (`cli-fhevm-sdk`): commander command registration and the `fhevm-sdk` binary. It consumes the toolkit through `@cli-fhevm-sdk/toolkit` package imports (root export or deep subpaths such as `@cli-fhevm-sdk/toolkit/flows/input-proof`), never through relative paths.\n- `packages/load-test` (`@cli-fhevm-sdk/load-test`): a private operator application, not a publishable SDK library. It owns load models, durable pools, raw relayer wire validation, collectors, reports, baselines, and its Commander surface. It may use public `@fhevm/sdk` entry points directly for SDK-native workload journeys and proof workers, and uses the toolkit for shared network, account, contract, ACL, and value behavior. Load orchestration must not move into toolkit.\n\nThe toolkit's `exports` map points at TypeScript source; the CLI build (`tsdown`) bundles the toolkit into `packages/cli/dist/` via `deps.alwaysBundle` while keeping npm dependencies external. Because of that, the toolkit's runtime npm dependencies must also be declared in `packages/cli/package.json`.\n\n## Toolkit boundaries (`packages/toolkit/src`)\n\n- `flows`: orchestration only. Compose config, SDK, contract, ACL, transaction, and value helpers here. Group command families into subfolders such as `fhe-test`, `public-decrypt`, `user-decrypt`, `delegated-user-decrypt`, and `token`.\n- `fhevm`: `@fhevm/sdk` adapters and SDK response normalization.\n- `fhe-test`: FHETest ABI and contract reads/writes.\n- `token`: ERC-7984 confidential token ABI and contract reads/writes.\n- `acl`: ACL delegation reads/writes.\n- `config`: network registry, runtime config, account loading, and client contexts.\n- `values`: clear-value parsing, random values, and JSON serialization helpers.\n- `shared`: cross-cutting helpers like progress and transaction waiting.\n- `types.ts`: networks, FHE value types, and flow result types shared across packages.\n- `index.ts`: the public API barrel; keep new public functions exported from here. Deep subpath exports stay available for lazy loading.\n\nKeep SDK integration on entry points declared by `@fhevm/sdk`; do not resolve or\nimport files from its private `_esm`, `_cjs`, or internal source layout. Toolkit\npermit APIs use seconds, matching `@fhevm/sdk`. Human-facing CLI options may use\ndays, but must convert at the CLI boundary.\n\nCustom FHEVM chains must include the host-chain `protocolConfig` contract used\nby the SDK to resolve the protocol and compatible WASM versions.\n\n## CLI boundaries (`packages/cli`)\n\n- `src/cli`: command registration, argument parsing, stdout/stderr behavior.\n- `bin/completion-server.mjs`: static tab completion resolver. It must stay lightweight and must not import TypeScript runtime, SDK clients, config, or flows.\n\nWhen adding a command, prefer:\n\n1. CLI module in `packages/cli/src/cli/commands`.\n2. Flow module in the matching `packages/toolkit/src/flows/<command-family>` folder.\n3. Adapter changes only at the boundary being crossed.\n\nKeep raw SDK response casts and raw contract calls out of CLI and flow code when practical.\nKeep expensive flow and SDK imports inside command actions, not at CLI module top level.\n\n## Load-test boundaries (`packages/load-test/src`)\n\n- `scenario` and `suite`: validated workload data, exact flow allocation, pool planning, and sequential suite orchestration.\n- `runner` and `flows`: scheduler lifecycle plus one executor per relayer flow.\n- `relayer`: bounded, runtime-validated raw HTTP protocol adapters. Never trust wire data through TypeScript casts.\n- `pool`: durable pool schemas, writers, cursors, and on-chain/off-chain preparation.\n- `collectors` and `report`: optional observations, strict versioned report schema, rendering, comparison, and explicit baseline blessing.\n- `cli`: argument parsing and lazy action wiring only.\n\nReport and baseline reads must pass the versioned runtime schema. A missing\nbaseline may skip a comparison; a corrupt or incompatible baseline must fail.\nBaseline mutation belongs only to the explicit `baseline bless` command and is\nstaged only after every suite report validates.\n","relayer-http/CLAUDE.md":"# relayer-http — development guide\n\nThis file is living: add a rule or change a description here whenever a feature lands that affects them, in the same\nchange. It describes a minimal first version.\n\n## What this repo is\n\nThe Zama relayer over HTTP. It replaces the gateway-chain decryption path: request handlers receive the SDK's\ndecryption requests and the `kms_aggregator` module fans them out to the KMS connector endpoints and aggregates the\nt-of-n answers.\n\n**Minimal first version**: the handlers and the fan-out/aggregation only.\n- No ACL check and no ciphertext-commit (readiness) check in the relayer: the connector's worker performs them and their\n  failures come back as connector error codes. Both can come back later as optional modules in front of the aggregator.\n- No database, no queue, no cache, no response storage.\n\n## Layout\n\n```\nrelayer-http/\n├── Cargo.toml, Cargo.lock, rust-toolchain.toml   # workspace, exact dependency pins (=x.y.z), toolchain 1.97.1\n├── Dockerfile                                     # container image, built from the repository root (see Container image)\n├── .gitignore                                     # target/, config/*.local.yaml (local variants of the configuration)\n├── config/config.yaml                             # example configuration: name, log, http, kms_aggregator\n├── dev/                                           # local development tooling: Makefile, per-topology configs, proxy port-forwards, flow scripts; start with its README.md\n└── crates/relayer-http/src/\n    ├── main.rs                # load config → init logging → App → serve until SIGINT/SIGTERM → drain → exit\n    ├── lib.rs                 # App: the one shared state (both aggregators, http config, shutdown token)\n    ├── config.rs              # RelayerConfig, LogConfig, HttpConfig: YAML + APP_<SECTION>__<FIELD> overrides\n    ├── logging.rs             # tracing subscriber (json | pretty | compact, RUST_LOG) + Log: one request's identifiers on every line\n    ├── endpoint/              # the HTTP layer; start with its docs.md\n    │   ├── mod.rs             # router() and serve()\n    │   ├── error.rs           # ApiError: the one error body and its mapping\n    │   ├── validate.rs        # rules shared by the routes (handles, extraData)\n    │   ├── ops.rs             # GET /liveness, GET /healthz\n    │   └── flows/{mod,user_decrypt,public_decrypt}.rs   # one file per route: wire types, validation, handler (logs each step)\n    └── kms_aggregator/        # fan-out to the KMS connectors and t-of-n aggregation; start with its docs.md\n        ├── mod.rs, config.rs, client.rs, call.rs, aggregator.rs\n        ├── flows/{mod,user_decrypt,public_decrypt}.rs   # one file per flow: checks, counting, output\n        ├── mock.rs, scenarios.rs                       # test only: scripted connector, YAML scenario runner\n        └── scenarios/*.yaml                            # behaviour scenarios, run by cargo test\n```\n\nTwo modules, each with its `docs.md` next to the code: `endpoint/docs.md` (routes, payloads, responses, every\nerror code and its mapping) and `kms_aggregator/docs.md` (how an aggregation runs, one node call, checks,\nconfiguration → behaviour). The implementation plans live outside the repository (`relayer_specs_plans/`).\n\n## Configuration\n\nOne YAML file (`config/config.yaml` is the example), four sections: `name`, `log` (optional, defaults to JSON\nlines), `http` (bind address, body limit, body read timeout, supported chain ids) and `kms_aggregator` (deadline,\nretries, thresholds, optional checks, the KMS endpoints). Any field can be overridden with `APP_<SECTION>__<FIELD>` (durations carry a\nunit, e.g. `APP_KMS_AGGREGATOR__CALL__TIMEOUT=7s`). API keys are never in the file: each endpoint names the env var\nholding its key. Local variants go to `config/*.local.yaml`, ignored by git.\n\n## Commands\n\nFrom `relayer-http/`:\n\n```sh\ncargo fmt -- --check      # not --all: cargo-fmt would follow the kms-connector-api path dependency into generated bindings\ncargo clippy --workspace --all-targets -- -W clippy::perf -W clippy::suspicious -W clippy::style -D warnings\ncargo test --workspace\ncargo test -p relayer-http yaml_scenarios          # the aggregator scenarios only\ncargo run -p relayer-http -- config/config.yaml    # needs the KMS_<i>_API_KEY env vars named in the config\n```\n\nEvery change must pass the first three. Check exit codes strictly (a grep on the output hides a failing build).\n\nAgainst the local fhevm stack: `make -C dev up` (connector proxies and their host port-forwards), `make -C dev run`\n(the relayer with the config matching the running topology), `make -C dev public-decrypt` / `user-decrypt` (one flow\neach, from the e2e container), `make -C dev check` (the three commands above). See `dev/README.md`.\n\n## Container image\n\n`Dockerfile` follows the relayer's and the kms-connector's model: the golden `rust-glibc` builder pinned by\n`RUST_IMAGE_VERSION` (single source of truth: `rust-toolchain.toml`, read by the CI template), `cargo build --locked\n--release`, a `glibc-dynamic` runtime running as the `fhevm` user, no configuration baked in. The build context is the\n**repository root**: the crate depends on `kms-connector/crates/api` by path and that workspace references its\nsiblings, which the Dockerfile copies at the same relative places.\n\n```sh\n# from the repository root\ndocker build -f relayer-http/Dockerfile --build-arg RUST_IMAGE_VERSION=1.97.1 -t relayer-http .\ndocker run --rm -p 8080:8080 -v \"$PWD/relayer-http/config/config.yaml:/app/config/config.yaml:ro\" \\\n  -e KMS_00_API_KEY=... relayer-http            # the config is mounted at /app/config/config.yaml\n```\n\nCI publishes the image as `ghcr.io/zama-ai/fhevm/relayer-http` through `.github/workflows/relayer-http-docker-build.yml`\n(pushes to `main`/`release/*`, releases, manual runs, or a call from the e2e orchestrator). The two other workflows,\n`relayer-http-tests.yml` and `relayer-http-dependency-analysis.yml`, run on pull requests: the three commands above,\nthen `cargo update -w --locked`, `cargo-deny check license` against `deny.toml` (every allowed license must be used)\nand `cargo-audit audit` with `.cargo/audit.toml`. All three are gated on changes under `relayer-http/**`,\n`kms-connector/crates/api/**` and `kms-connector/Cargo.toml`.\n\n## Rules\n\n**No gateway interaction.** The relayer never talks to the gateway chain and carries no gateway-specific\nconfiguration, optional checks included. Every on-chain read goes to a host chain through host contracts, Ethereum\nbeing the reference.\n\n**No unexpected panic.** Both crate roots deny `clippy::unwrap_used`, `expect_used`, `indexing_slicing` and `panic`\n(allowed in tests). Every failure is a typed error returned to the caller. Configuration validation bounds every value\nthe runtime arithmetic relies on (`call.timeout <= 60s`, `backoff_max <= call.timeout`, semaphore size capped) so that no\narithmetic can overflow later. A panic inside a spawned task is counted as a failure, never propagated.\n\n**Fail fast.** Never wait for something that cannot change the outcome: when `counted + pending < threshold` the\nremaining calls are cancelled at once. One deadline per request, no queue, no ETA; the client retries.\n\n**HPA compatible.** No per-request state outside the request's own future: no shared map, no registry, no sticky\nsession. Every replica is identical; the call semaphore is per pod. If per-request state is ever needed, it goes behind\na trait so that Redis (or another store) can back it later.\n\n**Errors.** Modules return typed errors (`thiserror`), with what the caller needs to act (counts, dominant connector\nerror). Errors are logged once, at the boundary that answers the client. No `error!` inside a module for an expected\nfailure.\n\n**Logging.** `tracing` only, structured fields, short messages. Every endpoint line about a request goes through its\n`Log` (`logging.rs`) and carries `request_id`, `flow`, `handles`, `decryption_id`, the last two `none` until known:\na known event is a method on `Log`, any other line is `log!(level, log, fields…, \"message\")`. Aggregator lines carry\nthe same identifiers through the `aggregation` span; a task spawned for a request inherits it (`in_current_span`).\nEvery failed node attempt is one `warn`. Never log request or response bodies, shares, signatures, header values or\nURLs. The subscriber is installed by `main`, never by a module; `log:` is optional and defaults to JSON lines\n(`log.format`: `json` | `pretty` | `compact`, plus the relayer's `show_*` switches); the level filter is `RUST_LOG`,\ndefault `warn,relayer_http=info`.\n\n**Configuration.** Nested structs use `deny_unknown_fields`; `validate()` messages name the field with its dotted path\n(`kms_aggregator.call.timeout must …`); secrets appear only as env var names; durations carry a unit.\n\n**Minimal code.** Few types, one function per loop, a one-line doc comment per item, no framework where a function does.\nProduction-ready means no panic, typed errors, logs, cancellation and tests, not features.\n\n**Compatibility.** The connector interface comes from the `kms-connector-api` crate (path dependency, never its\n`endpoint` feature): DTOs, routes, error codes and their `retryable` flag are used as they are, never redefined.\n\n**Tests.** A unit test per function, next to it. Paused tokio time (`start_paused`) for anything timed, so durations\nare exact and tests are instant. Behaviour is described in YAML scenarios run by `cargo test`; adding a case is adding\na file.\n\n**Documentation.** Every module has a `docs.md` produced with the module and updated in the same change as any\nbehaviour change, plus a one-line doc comment on every item. The error code table in `endpoint/docs.md` (every code,\nits status, when it happens, how aggregation errors map to it) is updated in the same change as any change to that\nmapping. This `CLAUDE.md` is updated the same way: new rules and\nchanged descriptions land with the feature that motivates them.\n","gateway-contracts/docs/references/selectors.md":"## Smart Contract selectors\n\nAll smart contract selectors can be found in the [contract selectors](../../selectors.txt) file.\n","sdk/cli-js-sdk/docs/agents/TESTING.md":"# Testing\n\nUse pnpm scripts for verification.\n\n```bash\npnpm run typecheck\npnpm run test\npnpm run build\n```\n\nFor CLI changes, also run relevant help or parser checks, for example:\n\n```bash\npnpm --silent run cli --help\npnpm --silent run cli user-decrypt --help\npnpm --silent run cli delegated-user-decrypt --help\n```\n\nFor load-test changes, validate its complete private package and inspect the\naffected command groups:\n\n```bash\npnpm --filter @cli-fhevm-sdk/load-test run typecheck\npnpm --filter @cli-fhevm-sdk/load-test run test\npnpm load-test --help\npnpm load-test pool --help\npnpm load-test report --help\npnpm load-test baseline --help\n```\n\nAvoid network-dependent checks unless the user asks for them or credentials/RPC access are available.\n\nUnit tests must cover unit conversions and SDK adapter request shapes. In\nparticular, assert permit durations are sent to `@fhevm/sdk` as\n`durationSeconds`; type-checking alone does not catch semantic unit regressions.\n","sdk/cli-js-sdk/packages/cli/package.json":"{\n  \"name\": \"cli-fhevm-sdk\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"bin\": {\n    \"fhevm-sdk\": \"./bin/fhevm-sdk.mjs\"\n  },\n  \"engines\": {\n    \"node\": \">=22.0.0\"\n  },\n  \"scripts\": {\n    \"build\": \"tsdown\",\n    \"cli\": \"node dist/index.mjs\",\n    \"cli:dev\": \"node --import tsx index.ts\",\n    \"test\": \"vitest run\",\n    \"typecheck\": \"tsc --noEmit\"\n  },\n  \"devDependencies\": {\n    \"tsdown\": \"^0.22.2\",\n    \"tsx\": \"^4.21.0\",\n    \"vitest\": \"^3.2.4\"\n  },\n  \"dependencies\": {\n    \"@cli-fhevm-sdk/toolkit\": \"workspace:*\",\n    \"@commander-js/extra-typings\": \"^15.0.0\",\n    \"@fhevm/sdk\": \"0.13.2\",\n    \"@pnpm/tabtab\": \"^0.5.4\",\n    \"commander\": \"^15.0.0\",\n    \"consola\": \"^3.4.2\",\n    \"viem\": \"^2.50.4\"\n  }\n}\n","sdk/cli-js-sdk/docs/agents/ENGINE.md":"# TypeScript Engine\n\nDefault to Node.js with pnpm. The repository is a pnpm workspace (`packages/*`); run root scripts from the workspace root and use `pnpm --filter <package>` to target one package.\n\n- Use `pnpm install` for dependency installation.\n- Use `pnpm run <script>` for package scripts.\n- Use `pnpm exec <binary>` for local binaries.\n- Use `pnpm dlx <package> <command>` for one-off package execution.\n- Use `tsx` for running TypeScript entry points in development.\n- Use `tsdown` via `pnpm run build` for the compiled CLI artifact.\n- Use `tsc --noEmit` for type-checking.\n\n## APIs\n\n- Read environment variables from `process.env`.\n- Prefer built-in Node APIs for filesystem, path, URL, and process behavior.\n- This project targets Node.js 22 or newer because `@fhevm/sdk` requires it.\n","sdk/cli-js-sdk/packages/load-test/tsconfig.json":"# Load-test Skill\n\nPath: `sdk/cli-js-sdk/packages/load-test/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/load-test/tsconfig.json)","sdk/cli-js-sdk/packages/toolkit/package.json":"# Toolkit Skill\n\nPath: `sdk/cli-js-sdk/packages/toolkit/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/toolkit/package.json)","sdk/cli-js-sdk/packages/toolkit/tsconfig.json":"# Toolkit Skill\n\nPath: `sdk/cli-js-sdk/packages/toolkit/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/toolkit/tsconfig.json)","sdk/cli-js-sdk/packages/load-test/docs/OPERATIONS.md":"# Docs Skill\n\nPath: `sdk/cli-js-sdk/packages/load-test/docs/OPERATIONS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/load-test/docs/OPERATIONS.md)","sdk/cli-js-sdk/packages/load-test/docs/design/dual-relayer-dispatch.md":"# Design Skill\n\nPath: `sdk/cli-js-sdk/packages/load-test/docs/design/dual-relayer-dispatch.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/load-test/docs/design/dual-relayer-dispatch.md)"},"items":[{"name":"fhevm_api.md","path":"coprocessor/docs/references/fhevm_api.md","rawUrl":"https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/coprocessor/docs/references/fhevm_api.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# FHEVM API specifications\n","isInternal":false,"tokens":7,"sizeBytes":27},{"name":"gateway_api.md","path":"coprocessor/docs/references/gateway_api.md","rawUrl":"https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/coprocessor/docs/references/gateway_api.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Gateway API Specifications\n\n## Endpoints\n\n<details>\n  <summary>GET /keyurl ---- Retrieve links for retrieving the public keys and CRS' in the system.</summary>\n\n#### Description\n\nThis endpoint returns a JSON object containing URLs from an S3 bucket, allowing the client to download key files such as the blockchain public key, CRS files for input proof generation, the bootstrap key, and the address and public verification keys for each of the MPC servers running the TKMS.\n\nFor each file (with the exception of the verification key and address), a list of cryptographic signatures is provided to ensure the integrity and authenticity of the downloaded content. These signatures should be considered as a multi-sig. This means that instead of needing all the signatures to validate the content, only a subset, specifically >1/3 of the total signatures (if n nodes are signing), is required to verify that the content is legitimate. \n\nNo query parameters are required, as the gateway is already preconfigured for a specific blockchain.\n\n\n#### Query Parameters\n\nNo parameters.\n\n#### Headers\n\nNone.\n\n#### Response\n\n**Success (200 OK)**\n\nThe request is successful, and the response will include a JSON object with a `status` and a `response`. The response again consists of the following elements: \n- `crs`: A map of containing information on the different CRS'. The key of the map is the max amount of bits the CRS can support proofs for. The value is an object of the following elements for the given CRS:\n    * `data_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the CRS.\n    * `param_choice`: An integer representing the choice of parameters for the public key to be used with the CRS. \n    * `signatures`: A list of signatures (one from each MPC party constituting the TKMS backend). Each signature is a hex (lower-case) encoded EIP712 signature on the `safe_serialization` of `PublicParam<Bls12_446>`.\n    * `urls`: A list of URLs where the data can be fetched. The data at the end-point is a `safe_serialization` of `PublicParam<Bls12_446>`.\n- `fhe_key_info`: A list of objects, each representing information on a key-set in the system. More specifically each element consists of the following:\n    * `fhe_public_key`: An element which contains information about the public encryption key of a FHE key set. More specifically it consists of the following elements:\n        * `data_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the key.\n        * `param_choice`: An integer representing the choice of parameters used to generate the key. \n        * `signatures`: A list of signatures (one from each MPC party constituting the TKMS backend). Each signature is a hex (lower-case) encoded EIP712 signature on the `safe_serialization` of `CompactPublicKey`.\n        * `urls`: A list of URLs where the data can be fetched. The data at the end-point is a `safe_serialization` of `CompactPublicKey`.\n    * `fhe_server_key`: An element which contains information about the server key (the key used to perform FHE operations on ciphertexts) of a FHE key set. More specifically it consists of the following elements:\n        * `data_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the key.\n        * `param_choice`: An integer representing the choice of parameters used to generate the key. \n        * `signatures`: A list of signatures (one from each MPC party constituting the TKMS backend). Each signature is a hex (lower-case) encoded EIP712 signature on the `safe_serialization` of `CompactPublicKey`.\n        * `urls`: A list of URLs where the data can be fetched. The data at the end-point is a `safe_serialization` of `ServerKey`.\n- `verf_public_key`: **Deprecated and will be removed in the future. Should instead be fetched directly from the config contract on the TKMS blockchain** A list containing of elements, where each element is the information about a TKMS MPC server's signing key. That is, the key which a server uses to sign requests. More specifically each element of the vector consists of the following:\n        * `key_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the key. Currently this value is static for signing keys. That is, it will always be `408d8cbaa51dece7f782fe04ba0b1c1d017b1088`.\n        * `server_id`: The integer ID of the server whose key is being described in the current element. This is an integer in the range [1; n], where n is the amount of MPC servers.\n        * `verf_public_key_url`: The URL end-point of the given server where a serialization of the signing key can be found. The signing key is a `safe_serialization` of `PublicSigKey`.\n        * `verf_public_key_address`: The URL end-point of the given server where a file containing the human-readable Ethereum address of the server's signing key.\n\nFor example the following:\n\n```json\n{\n    \"response\": {\n        \"crs\": {\n            \"256\": {\n                \"data_id\": \"d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\",\n                \"param_choice\": 1,\n                \"signatures\": [\n                    \"0d13...\",\n                    \"4250...\",\n                    \"a42c...\",\n                    \"fhb5...\"\n                ],\n                \"urls\": [\n                    \"https://s3.amazonaws.com/bucket-name-1/PUB-p1/CRS/d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\",\n                    \"https://s3.amazonaws.com/bucket-name-4/PUB-p4/CRS/d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\",\n                    \"https://s3.amazonaws.com/bucket-name-2/PUB-p2/CRS/d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\",\n                    \"https://s3.amazonaws.com/bucket-name-3/PUB-p3/CRS/d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\"\n                ]\n            }\n        },\n        \"fhe_key_info\": [\n            {\n                \"fhe_public_key\": {\n                    \"data_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                    \"param_choice\": 1,\n                    \"signatures\": [\n                        \"cdff...\",\n                        \"123c...\",\n                        \"00ff...\",\n                        \"a367...\"\n                    ],\n                    \"urls\": [\n                        \"https://s3.amazonaws.com/bucket-name-1/PUB-p1/PublicKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-4/PUB-p4/PublicKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-2/PUB-p2/PublicKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-3/PUB-p3/PublicKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n                    ]\n                },\n                \"fhe_server_key\": {\n                    \"data_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                    \"param_choice\": 1,\n                    \"signatures\": [\n                        \"839b...\",\n                        \"baef...\",\n                        \"55cc...\",\n                        \"81a4...\"\n                    ],\n                    \"urls\": [\n                        \"https://s3.amazonaws.com/bucket-name-1/PUB-p1/ServerKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-4/PUB-p4/ServerKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-2/PUB-p2/ServerKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-3/PUB-p3/ServerKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n                    ]\n                }\n            }\n        ],\n        \"verf_public_key\": [\n            {\n                \"key_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"server_id\": 1,\n                \"verf_public_key_address\": \"https://s3.amazonaws.com/bucket-name-1/PUB-p1/VerfAddress/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"verf_public_key_url\": \"https://s3.amazonaws.com/bucket-name-1/PUB-p1/VerfKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n            },\n            {\n                \"key_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"server_id\": 4,\n                \"verf_public_key_address\": \"https://s3.amazonaws.com/bucket-name-4/PUB-p4/VerfAddress/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"verf_public_key_url\": \"https://s3.amazonaws.com/bucket-name-4//PUB-p4/VerfKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n            },\n            {\n                \"key_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"server_id\": 2,\n                \"verf_public_key_address\": \"https://s3.amazonaws.com/bucket-name-2/PUB-p2/VerfAddress/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"verf_public_key_url\": \"https://s3.amazonaws.com/bucket-name-2/PUB-p2/VerfKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n            },\n            {\n                \"key_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"server_id\": 3,\n                \"verf_public_key_address\": \"https://s3.amazonaws.com/bucket-name-3/PUB-p3/VerfAddress/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"verf_public_key_url\": \"https://s3.amazonaws.com/bucket-name-3/PUB-p3/VerfKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n            }\n        ]\n    },\n    \"status\": \"success\"\n}\n```\n\n**Error Responses**\n\n| Status Code | Error Code   | Description                                      |\n| ----------- | ------------ | ------------------------------------------------ |\n| 400         | `BadRequest` | The request is invalid or missing required parameters. |\n| 404         | `NotFound`   | The requested resource was not found.            |\n| 500         | `ServerError` | An internal server error occurred.                   |\n\n#### Example Error Responses\n\n```json\n{\n  \"error\": \"BadRequest\",\n  \"message\": \"The request is invalid or missing required parameters.\"\n}\n```\n\n```json\n{\n  \"error\": \"NotFound\",\n  \"message\": \"The requested resource was not found.\"\n}\n```\n\n```json\n{\n  \"error\": \"ServerError\",\n  \"message\": \"An internal server error occurred. Please try again later.\"\n}\n```\n\n</details>\n\n<details>\n  <summary>POST /verify_proven_ct ---- Input a batch of proven ciphertexts to be validated by the TKMS.</summary>\n\n#### Description\n\nThis endpoint returns a JSON object containing all the signatures on the proven ciphertexts from the TKMS servers. Furthermore the response contains some meta-information distinguishing if the response is for the co-processor setting or FHEVM native setting. In case of the co-processor setting, then the ciphertext storage handles and a signature from the co-processor attesting correct storage is also included.\n\nThe signatures from the TKMS should be considered as a multi-sig. This means that instead of needing all the signatures to validate the content, only a subset, specifically >1/3 of the total signatures, is required to verify that the content is legitimate. \n\n#### Query Parameters\n\nMultiple parameters must be supplied in JSON format:\n- `contract_address`: An EIP-55 encoded address (that is, including the `0x` prefix) of the contract where the proven ciphertext is to be submitted.\n- `caller_address`: An EIP-55 encoded address (that is, including the `0x` prefix) of the user who is providing the encrypted input.\n- `crs_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the CRS used to construct the proof.\n- `key_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the public key used to encrypt the ciphertext with.\n- `ct_proof`: A hex encoding of the serialization of the proven ciphertext. More specifically the TFHE-RS object `ProvenCompactCiphertextList` serialized using `safe_serialization`.\n\n```json\n{\n    \"contract_address\": \"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed\",\n    \"caller_address\": \"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb\" ,\n    \"crs_id\": \"d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\",\n    \"key_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n    \"ct_proof\": \"cdff...\",\n}\n```\n\n#### Headers\n\nNone.\n\n#### Response\n\n**Success (200 OK)**\n\nThe request is successful, and the response will include a JSON object with a `status` and a `response` which  consists of the following:\n\n- `handles`: A vector of handles to each of the ciphertexts which have been proven knowledge of. A handle is a 32 byte (lower-case) hex encoded handle/ID identifying the ciphertext.\n- `kms_signatures`: A list of signatures (one for each of the TKMS servers that respond to the query). Each signature is a hex (lower-case) encoded EIP712 signature on the `safe_serialization` of `ProvenCompactCiphertextList`.\n- `listener_type`: An enum expressing whether the result is for an FHEVM native (`FHEVM_NATIVE`) or co-processor respectively (`COPROCESSOR`).\n- `proof_of_storage`: An optional signature from the co-processor. More specifically if FHEVM native is used it will be an empty string, otherwise it will be a hex (lower-case) encoded EIP712 signature on the request. \n\nFor example the following:\n```json\n{\n    \"response\": {\n        \"handles\": [\n            \"0748b542afe2353c86cb707e3d21044b0be1fd18efc7cbaa6a415af055bfb358\",\n            \"054ab4515b1541878723431005054f154e15e45e15800adb67879679df670456\"\n        ],\n        \"kms_signatures\":[\n            \"15a4f9a8eb61459cfba7d103d8f911fb04ce91ecf841b34c49c0d56a70b896d20cbc31986188f91efc3842b7df215cee8acb40178daedb8b63d0ba5d199bce121c\", \n            \"118165165165423465234414c4c468a4d9684d8e18186d6f786161b4b436c58787cc68418186d6f786161b4b98461166a6a6668e8e118542c154867aab238abd79\", \n            \"1c849848940128065242121b2b12121ed876986da251561650c654564d684654e51610879a9a9798b78b78e7f8787d87c8c8894a454547809586616161464cc8a8\", \n            \"10c864ac145423466798808098c098b09a8908d6432da4544f5e54566b76740454654a54c65454565d65d657e44651241561342441234128888063304854897893\", \n        ],\n        \"listener_type\": \"COPROCESSOR\",\n        \"proof_of_storage\": \"17acd15648740c00849f489498489e4600a60a06068d484b084894988333000cff798751651498d68768753567a4356787c45787e79i8f64d128218927897c8789\"\n    },\n    \"status\": \"success\"\n}\n```\n\n**Error Responses**\n\n| Status Code | Error Code   | Description                                      |\n| ----------- | ------------ | ------------------------------------------------ |\n| 400         | `BadRequest` | The request is invalid or missing required parameters. |\n| 404         | `NotFound`   | The requested resource was not found.            |\n| 500         | `ServerError` | An internal server error occurred.                   |\n\n#### Example Error Responses\n\n```json\n{\n  \"error\": \"BadRequest\",\n  \"message\": \"The request is invalid or missing required parameters.\"\n}\n```\n\n```json\n{\n  \"error\": \"NotFound\",\n  \"message\": \"The requested resource was not found.\"\n}\n```\n\n```json\n{\n  \"error\": \"ServerError\",\n  \"message\": \"An internal server error occurred. Please try again later.\"\n}\n```\n\n</details>\n\n<details>\n  <summary>POST /reencrypt ---- Decrypt a ciphertext under an ephemeral key s.t. a client can learn the decrypted value privately.</summary>\n\n#### Description\n\nThis end-point returns a JSON object containing a signcryption of the plaintext value of an FHE ciphertext that has been (obliviously) decrypted by the TKMS. \nMore specifically the TKMS servers carry out a partial decryption resulting in each of them knowing a secret share of the plaintext (meaning that multiple servers need to maliciously collude in order to learn the decrypted plaintext). They each then signcrypt their share of the plaintext. The response consists of each of these signcryptions along with meta information about the threshold setup and which server provides each signcrypted share of the result. \nSince the signcryption is based on secret sharing it means that only a subset, specifically >1/3 of the total responses, is required to recover the result (assuming all returned signcryptions are correct). \n\n#### Query Parameters\n\nMultiple parameters must be supplied in JSON format:\n- `signature`: A hex (lower-case) encoded EIP712 signature on the public encryption key, `enc_key`, under which the of the ciphertext in question will be reencrypted. \n- `client_address`: An EIP-55 encoded address (that is, including the `0x` prefix) of the end-user who is supposed to learn the reencrypted response.\n- `enc_key`: The hex (lower-case) encoded public encryption key (libsodium) which the reencryption should be signcrypted under.\n- `ciphertext_handle`: The 32 byte (lower-case) hex encoded handle/ID identifying the ciphertext and hence allowing the gateway to fetch it.\n- `eip712_verifying_contract`: An EIP-55 encoded address (that is, including the `0x` prefix) of the contract holding the ciphertext to reencrypt.\n```json\n{\n     \"signature\": \"15a4f9a8eb61459cfba7d103d8f911fb04ce91ecf841b34c49c0d56a70b896d20cbc31986188f91efc3842b7df215cee8acb40178daedb8b63d0ba5d199bce121c\",\n     \"client_address\": \"0x17853A630aAe15AED549B2B874de08B73C0F59c5\",\n     \"enc_key\": \"2000000000000000df2fcacb774f03187f3802a27259f45c06d33cefa68d9c53426b15ad531aa822\",\n     \"ciphertext_handle\": \"0748b542afe2353c86cb707e3d21044b0be1fd18efc7cbaa6a415af055bfb358\",\n     \"eip712_verifying_contract\": \"0x66f9664f97F2b50F62D13eA064982f936dE76657\"\n}\n```\n\n#### Headers\n\nNone.\n\n#### Response\n\n**Success (200 OK)**\n\nThe request is successful, and the response will include a JSON object with a `status` and a `response` which is a list of responses from each TKMS. More specifically each element in the list consists of the following:\n- `payload`: A bincode encoding of the signcryption from a single server along with meta information including the server ID, threshold parameter, type of value encrypted and the specific public key of the server supplying the specific response. \n- `signature`: An EIP712 signature which is hex (low-case) encoded.\n\nFor example the following:\n```json\n{\n    \"response\": [\n        {\n            \"payload\": \"161c5...\",\n            \"signature\": \"15a4f9a8eb61459cfba7d103d8f911fb04ce91ecf841b34c49c0d56a70b896d20cbc31986188f91efc3842b7df215cee8acb40178daedb8b63d0ba5d199bce121c\"\n        },\n        {\n            \"payload\": \"44546...\",\n            \"signature\": \"118165165165423465234414c4c468a4d9684d8e18186d6f786161b4b436c58787cc68418186d6f786161b4b98461166a6a6668e8e118542c154867aab238abd79\"\n        },\n        {\n            \"payload\": \"54cd5...\",\n            \"signature\": \"1c849848940128065242121b2b12121ed876986da251561650c654564d684654e51610879a9a9798b78b78e7f8787d87c8c8894a454547809586616161464cc8a8\"\n        },\n        {\n            \"payload\": \"a516b...\",\n            \"signature\": \"10c864ac145423466798808098c098b09a8908d6432da4544f5e54566b76740454654a54c65454565d65d657e44651241561342441234128888063304854897893\"\n        },\n    ],\n    \"status\": \"success\"\n}\n```\n\n**Error Responses**\n\n| Status Code | Error Code   | Description                                      |\n| ----------- | ------------ | ------------------------------------------------ |\n| 400         | `BadRequest` | The request is invalid or missing required parameters. |\n| 404         | `NotFound`   | The requested resource was not found.            |\n| 500         | `ServerError` | An internal server error occurred.                   |\n\n#### Example Error Responses\n\n```json\n{\n  \"error\": \"BadRequest\",\n  \"message\": \"The request is invalid or missing required parameters.\"\n}\n```\n\n```json\n{\n  \"error\": \"NotFound\",\n  \"message\": \"The requested resource was not found.\"\n}\n```\n\n```json\n{\n  \"error\": \"ServerError\",\n  \"message\": \"An internal server error occurred. Please try again later.\"\n}\n```\n\n</details>","isInternal":false,"tokens":5383,"sizeBytes":19581},{"name":"selectors.md","path":"gateway-contracts/docs/references/selectors.md","rawUrl":"https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/gateway-contracts/docs/references/selectors.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"## Smart Contract selectors\n\nAll smart contract selectors can be found in the [contract selectors](../../selectors.txt) file.\n","isInternal":false,"tokens":24,"sizeBytes":126},{"name":"package.json","path":"sdk/cli-js-sdk/packages/cli/package.json","rawUrl":"https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/cli/package.json","title":"cli-fhevm-sdk","category":"anthropic-skill","format":"json","content":"{\n  \"name\": \"cli-fhevm-sdk\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"bin\": {\n    \"fhevm-sdk\": \"./bin/fhevm-sdk.mjs\"\n  },\n  \"engines\": {\n    \"node\": \">=22.0.0\"\n  },\n  \"scripts\": {\n    \"build\": \"tsdown\",\n    \"cli\": \"node dist/index.mjs\",\n    \"cli:dev\": \"node --import tsx index.ts\",\n    \"test\": \"vitest run\",\n    \"typecheck\": \"tsc --noEmit\"\n  },\n  \"devDependencies\": {\n    \"tsdown\": \"^0.22.2\",\n    \"tsx\": \"^4.21.0\",\n    \"vitest\": \"^3.2.4\"\n  },\n  \"dependencies\": {\n    \"@cli-fhevm-sdk/toolkit\": \"workspace:*\",\n    \"@commander-js/extra-typings\": \"^15.0.0\",\n    \"@fhevm/sdk\": \"0.13.2\",\n    \"@pnpm/tabtab\": \"^0.5.4\",\n    \"commander\": \"^15.0.0\",\n    \"consola\": \"^3.4.2\",\n    \"viem\": \"^2.50.4\"\n  }\n}\n","frontmatter":{"name":"cli-fhevm-sdk","type":"module","private":true,"bin":{"fhevm-sdk":"./bin/fhevm-sdk.mjs"},"engines":{"node":">=22.0.0"},"scripts":{"build":"tsdown","cli":"node dist/index.mjs","cli:dev":"node --import tsx index.ts","test":"vitest run","typecheck":"tsc --noEmit"},"devDependencies":{"tsdown":"^0.22.2","tsx":"^4.21.0","vitest":"^3.2.4"},"dependencies":{"@cli-fhevm-sdk/toolkit":"workspace:*","@commander-js/extra-typings":"^15.0.0","@fhevm/sdk":"0.13.2","@pnpm/tabtab":"^0.5.4","commander":"^15.0.0","consola":"^3.4.2","viem":"^2.50.4"}},"isInternal":false,"tokens":278,"sizeBytes":694},{"name":"dual-relayer-dispatch.md","path":"sdk/cli-js-sdk/packages/load-test/docs/design/dual-relayer-dispatch.md","rawUrl":"https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/load-test/docs/design/dual-relayer-dispatch.md","title":"Design Skill","category":"anthropic-skill","format":"markdown","content":"# Design Skill\n\nPath: `sdk/cli-js-sdk/packages/load-test/docs/design/dual-relayer-dispatch.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/load-test/docs/design/dual-relayer-dispatch.md)","tokens":300,"sizeBytes":249},{"name":"OPERATIONS.md","path":"sdk/cli-js-sdk/packages/load-test/docs/OPERATIONS.md","rawUrl":"https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/load-test/docs/OPERATIONS.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Docs Skill\n\nPath: `sdk/cli-js-sdk/packages/load-test/docs/OPERATIONS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/load-test/docs/OPERATIONS.md)","tokens":300,"sizeBytes":211},{"name":"tsconfig.json","path":"sdk/cli-js-sdk/packages/load-test/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/load-test/tsconfig.json","title":"Load-test Skill","category":"anthropic-skill","format":"json","content":"# Load-test Skill\n\nPath: `sdk/cli-js-sdk/packages/load-test/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/load-test/tsconfig.json)","tokens":300,"sizeBytes":206},{"name":"package.json","path":"sdk/cli-js-sdk/packages/toolkit/package.json","rawUrl":"https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/toolkit/package.json","title":"Toolkit Skill","category":"anthropic-skill","format":"json","content":"# Toolkit Skill\n\nPath: `sdk/cli-js-sdk/packages/toolkit/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/toolkit/package.json)","tokens":300,"sizeBytes":198},{"name":"tsconfig.json","path":"sdk/cli-js-sdk/packages/toolkit/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/toolkit/tsconfig.json","title":"Toolkit Skill","category":"anthropic-skill","format":"json","content":"# Toolkit Skill\n\nPath: `sdk/cli-js-sdk/packages/toolkit/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/toolkit/tsconfig.json)","tokens":300,"sizeBytes":200},{"name":"CLAUDE.md","path":"relayer-http/CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/relayer-http/CLAUDE.md","title":"relayer-http - Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# relayer-http — development guide\n\nThis file is living: add a rule or change a description here whenever a feature lands that affects them, in the same\nchange. It describes a minimal first version.\n\n## What this repo is\n\nThe Zama relayer over HTTP. It replaces the gateway-chain decryption path: request handlers receive the SDK's\ndecryption requests and the `kms_aggregator` module fans them out to the KMS connector endpoints and aggregates the\nt-of-n answers.\n\n**Minimal first version**: the handlers and the fan-out/aggregation only.\n- No ACL check and no ciphertext-commit (readiness) check in the relayer: the connector's worker performs them and their\n  failures come back as connector error codes. Both can come back later as optional modules in front of the aggregator.\n- No database, no queue, no cache, no response storage.\n\n## Layout\n\n```\nrelayer-http/\n├── Cargo.toml, Cargo.lock, rust-toolchain.toml   # workspace, exact dependency pins (=x.y.z), toolchain 1.97.1\n├── Dockerfile                                     # container image, built from the repository root (see Container image)\n├── .gitignore                                     # target/, config/*.local.yaml (local variants of the configuration)\n├── config/config.yaml                             # example configuration: name, log, http, kms_aggregator\n├── dev/                                           # local development tooling: Makefile, per-topology configs, proxy port-forwards, flow scripts; start with its README.md\n└── crates/relayer-http/src/\n    ├── main.rs                # load config → init logging → App → serve until SIGINT/SIGTERM → drain → exit\n    ├── lib.rs                 # App: the one shared state (both aggregators, http config, shutdown token)\n    ├── config.rs              # RelayerConfig, LogConfig, HttpConfig: YAML + APP_<SECTION>__<FIELD> overrides\n    ├── logging.rs             # tracing subscriber (json | pretty | compact, RUST_LOG) + Log: one request's identifiers on every line\n    ├── endpoint/              # the HTTP layer; start with its docs.md\n    │   ├── mod.rs             # router() and serve()\n    │   ├── error.rs           # ApiError: the one error body and its mapping\n    │   ├── validate.rs        # rules shared by the routes (handles, extraData)\n    │   ├── ops.rs             # GET /liveness, GET /healthz\n    │   └── flows/{mod,user_decrypt,public_decrypt}.rs   # one file per route: wire types, validation, handler (logs each step)\n    └── kms_aggregator/        # fan-out to the KMS connectors and t-of-n aggregation; start with its docs.md\n        ├── mod.rs, config.rs, client.rs, call.rs, aggregator.rs\n        ├── flows/{mod,user_decrypt,public_decrypt}.rs   # one file per flow: checks, counting, output\n        ├── mock.rs, scenarios.rs                       # test only: scripted connector, YAML scenario runner\n        └── scenarios/*.yaml                            # behaviour scenarios, run by cargo test\n```\n\nTwo modules, each with its `docs.md` next to the code: `endpoint/docs.md` (routes, payloads, responses, every\nerror code and its mapping) and `kms_aggregator/docs.md` (how an aggregation runs, one node call, checks,\nconfiguration → behaviour). The implementation plans live outside the repository (`relayer_specs_plans/`).\n\n## Configuration\n\nOne YAML file (`config/config.yaml` is the example), four sections: `name`, `log` (optional, defaults to JSON\nlines), `http` (bind address, body limit, body read timeout, supported chain ids) and `kms_aggregator` (deadline,\nretries, thresholds, optional checks, the KMS endpoints). Any field can be overridden with `APP_<SECTION>__<FIELD>` (durations carry a\nunit, e.g. `APP_KMS_AGGREGATOR__CALL__TIMEOUT=7s`). API keys are never in the file: each endpoint names the env var\nholding its key. Local variants go to `config/*.local.yaml`, ignored by git.\n\n## Commands\n\nFrom `relayer-http/`:\n\n```sh\ncargo fmt -- --check      # not --all: cargo-fmt would follow the kms-connector-api path dependency into generated bindings\ncargo clippy --workspace --all-targets -- -W clippy::perf -W clippy::suspicious -W clippy::style -D warnings\ncargo test --workspace\ncargo test -p relayer-http yaml_scenarios          # the aggregator scenarios only\ncargo run -p relayer-http -- config/config.yaml    # needs the KMS_<i>_API_KEY env vars named in the config\n```\n\nEvery change must pass the first three. Check exit codes strictly (a grep on the output hides a failing build).\n\nAgainst the local fhevm stack: `make -C dev up` (connector proxies and their host port-forwards), `make -C dev run`\n(the relayer with the config matching the running topology), `make -C dev public-decrypt` / `user-decrypt` (one flow\neach, from the e2e container), `make -C dev check` (the three commands above). See `dev/README.md`.\n\n## Container image\n\n`Dockerfile` follows the relayer's and the kms-connector's model: the golden `rust-glibc` builder pinned by\n`RUST_IMAGE_VERSION` (single source of truth: `rust-toolchain.toml`, read by the CI template), `cargo build --locked\n--release`, a `glibc-dynamic` runtime running as the `fhevm` user, no configuration baked in. The build context is the\n**repository root**: the crate depends on `kms-connector/crates/api` by path and that workspace references its\nsiblings, which the Dockerfile copies at the same relative places.\n\n```sh\n# from the repository root\ndocker build -f relayer-http/Dockerfile --build-arg RUST_IMAGE_VERSION=1.97.1 -t relayer-http .\ndocker run --rm -p 8080:8080 -v \"$PWD/relayer-http/config/config.yaml:/app/config/config.yaml:ro\" \\\n  -e KMS_00_API_KEY=... relayer-http            # the config is mounted at /app/config/config.yaml\n```\n\nCI publishes the image as `ghcr.io/zama-ai/fhevm/relayer-http` through `.github/workflows/relayer-http-docker-build.yml`\n(pushes to `main`/`release/*`, releases, manual runs, or a call from the e2e orchestrator). The two other workflows,\n`relayer-http-tests.yml` and `relayer-http-dependency-analysis.yml`, run on pull requests: the three commands above,\nthen `cargo update -w --locked`, `cargo-deny check license` against `deny.toml` (every allowed license must be used)\nand `cargo-audit audit` with `.cargo/audit.toml`. All three are gated on changes under `relayer-http/**`,\n`kms-connector/crates/api/**` and `kms-connector/Cargo.toml`.\n\n## Rules\n\n**No gateway interaction.** The relayer never talks to the gateway chain and carries no gateway-specific\nconfiguration, optional checks included. Every on-chain read goes to a host chain through host contracts, Ethereum\nbeing the reference.\n\n**No unexpected panic.** Both crate roots deny `clippy::unwrap_used`, `expect_used`, `indexing_slicing` and `panic`\n(allowed in tests). Every failure is a typed error returned to the caller. Configuration validation bounds every value\nthe runtime arithmetic relies on (`call.timeout <= 60s`, `backoff_max <= call.timeout`, semaphore size capped) so that no\narithmetic can overflow later. A panic inside a spawned task is counted as a failure, never propagated.\n\n**Fail fast.** Never wait for something that cannot change the outcome: when `counted + pending < threshold` the\nremaining calls are cancelled at once. One deadline per request, no queue, no ETA; the client retries.\n\n**HPA compatible.** No per-request state outside the request's own future: no shared map, no registry, no sticky\nsession. Every replica is identical; the call semaphore is per pod. If per-request state is ever needed, it goes behind\na trait so that Redis (or another store) can back it later.\n\n**Errors.** Modules return typed errors (`thiserror`), with what the caller needs to act (counts, dominant connector\nerror). Errors are logged once, at the boundary that answers the client. No `error!` inside a module for an expected\nfailure.\n\n**Logging.** `tracing` only, structured fields, short messages. Every endpoint line about a request goes through its\n`Log` (`logging.rs`) and carries `request_id`, `flow`, `handles`, `decryption_id`, the last two `none` until known:\na known event is a method on `Log`, any other line is `log!(level, log, fields…, \"message\")`. Aggregator lines carry\nthe same identifiers through the `aggregation` span; a task spawned for a request inherits it (`in_current_span`).\nEvery failed node attempt is one `warn`. Never log request or response bodies, shares, signatures, header values or\nURLs. The subscriber is installed by `main`, never by a module; `log:` is optional and defaults to JSON lines\n(`log.format`: `json` | `pretty` | `compact`, plus the relayer's `show_*` switches); the level filter is `RUST_LOG`,\ndefault `warn,relayer_http=info`.\n\n**Configuration.** Nested structs use `deny_unknown_fields`; `validate()` messages name the field with its dotted path\n(`kms_aggregator.call.timeout must …`); secrets appear only as env var names; durations carry a unit.\n\n**Minimal code.** Few types, one function per loop, a one-line doc comment per item, no framework where a function does.\nProduction-ready means no panic, typed errors, logs, cancellation and tests, not features.\n\n**Compatibility.** The connector interface comes from the `kms-connector-api` crate (path dependency, never its\n`endpoint` feature): DTOs, routes, error codes and their `retryable` flag are used as they are, never redefined.\n\n**Tests.** A unit test per function, next to it. Paused tokio time (`start_paused`) for anything timed, so durations\nare exact and tests are instant. Behaviour is described in YAML scenarios run by `cargo test`; adding a case is adding\na file.\n\n**Documentation.** Every module has a `docs.md` produced with the module and updated in the same change as any\nbehaviour change, plus a one-line doc comment on every item. The error code table in `endpoint/docs.md` (every code,\nits status, when it happens, how aggregation errors map to it) is updated in the same change as any change to that\nmapping. This `CLAUDE.md` is updated the same way: new rules and\nchanged descriptions land with the feature that motivates them.\n","isInternal":false,"tokens":2393,"sizeBytes":10154},{"name":"ARCHITECTURE.md","path":"sdk/cli-js-sdk/docs/agents/ARCHITECTURE.md","rawUrl":"https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/docs/agents/ARCHITECTURE.md","title":"Subagent: architecture","category":"subagent-persona","format":"markdown","content":"# Architecture\n\nThe repository is a pnpm workspace. Use the existing boundaries when adding behavior.\n\n## Packages\n\n- `packages/toolkit` (`@cli-fhevm-sdk/toolkit`): the library layer. It wraps `@fhevm/sdk` and FHETest with importable flows and must not depend on CLI packages (`commander`, `consola`, `@pnpm/tabtab`).\n- `packages/cli` (`cli-fhevm-sdk`): commander command registration and the `fhevm-sdk` binary. It consumes the toolkit through `@cli-fhevm-sdk/toolkit` package imports (root export or deep subpaths such as `@cli-fhevm-sdk/toolkit/flows/input-proof`), never through relative paths.\n- `packages/load-test` (`@cli-fhevm-sdk/load-test`): a private operator application, not a publishable SDK library. It owns load models, durable pools, raw relayer wire validation, collectors, reports, baselines, and its Commander surface. It may use public `@fhevm/sdk` entry points directly for SDK-native workload journeys and proof workers, and uses the toolkit for shared network, account, contract, ACL, and value behavior. Load orchestration must not move into toolkit.\n\nThe toolkit's `exports` map points at TypeScript source; the CLI build (`tsdown`) bundles the toolkit into `packages/cli/dist/` via `deps.alwaysBundle` while keeping npm dependencies external. Because of that, the toolkit's runtime npm dependencies must also be declared in `packages/cli/package.json`.\n\n## Toolkit boundaries (`packages/toolkit/src`)\n\n- `flows`: orchestration only. Compose config, SDK, contract, ACL, transaction, and value helpers here. Group command families into subfolders such as `fhe-test`, `public-decrypt`, `user-decrypt`, `delegated-user-decrypt`, and `token`.\n- `fhevm`: `@fhevm/sdk` adapters and SDK response normalization.\n- `fhe-test`: FHETest ABI and contract reads/writes.\n- `token`: ERC-7984 confidential token ABI and contract reads/writes.\n- `acl`: ACL delegation reads/writes.\n- `config`: network registry, runtime config, account loading, and client contexts.\n- `values`: clear-value parsing, random values, and JSON serialization helpers.\n- `shared`: cross-cutting helpers like progress and transaction waiting.\n- `types.ts`: networks, FHE value types, and flow result types shared across packages.\n- `index.ts`: the public API barrel; keep new public functions exported from here. Deep subpath exports stay available for lazy loading.\n\nKeep SDK integration on entry points declared by `@fhevm/sdk`; do not resolve or\nimport files from its private `_esm`, `_cjs`, or internal source layout. Toolkit\npermit APIs use seconds, matching `@fhevm/sdk`. Human-facing CLI options may use\ndays, but must convert at the CLI boundary.\n\nCustom FHEVM chains must include the host-chain `protocolConfig` contract used\nby the SDK to resolve the protocol and compatible WASM versions.\n\n## CLI boundaries (`packages/cli`)\n\n- `src/cli`: command registration, argument parsing, stdout/stderr behavior.\n- `bin/completion-server.mjs`: static tab completion resolver. It must stay lightweight and must not import TypeScript runtime, SDK clients, config, or flows.\n\nWhen adding a command, prefer:\n\n1. CLI module in `packages/cli/src/cli/commands`.\n2. Flow module in the matching `packages/toolkit/src/flows/<command-family>` folder.\n3. Adapter changes only at the boundary being crossed.\n\nKeep raw SDK response casts and raw contract calls out of CLI and flow code when practical.\nKeep expensive flow and SDK imports inside command actions, not at CLI module top level.\n\n## Load-test boundaries (`packages/load-test/src`)\n\n- `scenario` and `suite`: validated workload data, exact flow allocation, pool planning, and sequential suite orchestration.\n- `runner` and `flows`: scheduler lifecycle plus one executor per relayer flow.\n- `relayer`: bounded, runtime-validated raw HTTP protocol adapters. Never trust wire data through TypeScript casts.\n- `pool`: durable pool schemas, writers, cursors, and on-chain/off-chain preparation.\n- `collectors` and `report`: optional observations, strict versioned report schema, rendering, comparison, and explicit baseline blessing.\n- `cli`: argument parsing and lazy action wiring only.\n\nReport and baseline reads must pass the versioned runtime schema. A missing\nbaseline may skip a comparison; a corrupt or incompatible baseline must fail.\nBaseline mutation belongs only to the explicit `baseline bless` command and is\nstaged only after every suite report validates.\n","isInternal":false,"tokens":982,"sizeBytes":4399},{"name":"CLI.md","path":"sdk/cli-js-sdk/docs/agents/CLI.md","rawUrl":"https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/docs/agents/CLI.md","title":"Subagent: cli","category":"subagent-persona","format":"markdown","content":"# CLI\n\nUse these tools for CLI work:\n\n- `commander` for CLI interface\n- `@commander-js/extra-typings` for TypeScript types\n- `consola` for Elegant Console Wrapper\n- `@pnpm/tabtab` for shell tab completion\n\nBehavioral guidance:\n\n- Keep progress and status logs on stderr.\n- Keep the final machine-readable response on stdout as JSON.\n- Update `README.md` examples and this guidance when changing command behavior, options, outputs, defaults, or supported flows.\n- Global options may be passed before or after subcommands; use `optsWithGlobals()` from the command action context.\n- The CLI ships as the `fhevm-sdk` binary (`packages/cli/bin/fhevm-sdk.mjs`, exposed via `pnpm link` run from `packages/cli`) and runs compiled `packages/cli/dist/index.mjs`; run `pnpm run build` before linking or using `pnpm run cli`.\n- Use `pnpm run cli:dev` for source-mode CLI checks without rebuilding.\n- The workspace-root `.env` is loaded by `packages/cli/src/env.ts` relative to the repository, not the working directory; shell variables take precedence.\n- `completion-server` is invoked by tabtab's shell templates; the binary routes it to `packages/cli/bin/completion-server.mjs` before loading `tsx` or runtime flow modules. Keep its stdout limited to completion items.\n- Keep completion metadata in `packages/cli/bin/completion-server.mjs` aligned with command help whenever changing commands, options, choices, or descriptions.\n- Keep CLI command modules free of top-level flow imports. Runtime flow modules should be loaded with dynamic imports inside `.action()` handlers so help and completion startup stay fast.\n- FHETest is the only contract target, except `token transfer`/`token balance`, which target ERC-7984 confidential tokens and require `--contract` since there is no per-network token default.\n- Networks may target different host chains; do not assume Ethereum Sepolia for every network.\n- Keep decrypt-family naming consistent: the `direct` subcommand does direct handle decryption, while `fresh` and `stored` are FHETest demo subcommands.\n- The decrypt family roots (`user-decrypt`, `public-decrypt`, `delegated-user-decrypt`) are pure dispatchers with no options of their own; their `direct` subcommands decrypt existing `--handle` values from any contract, where `--contract` is the ACL pairing contract and defaults to FHETest. A bare root command with no subcommand prints help.\n- `fresh` creates or stores a new FHETest handle before decrypting.\n- `stored` reads an existing FHETest handle from the wallet/account/delegator type slots (defaulting to the bool slot); it has no `--handle`.\n- Public decrypt `fresh` stores with `makePublic=true`.\n- User decrypt and delegated user decrypt `fresh` store with `makePublic=false`.\n- Delegated flows use `PRIVATE_KEY`/`MNEMONIC` for the delegate and `DELEGATOR_PRIVATE_KEY`/`DELEGATOR_MNEMONIC` for the encrypted data owner.\n- `fhe-test inspect` is read-only. Keep raw `--handle` inspection mutually exclusive with account/type inspection.\n- `fhe-test inspect --type <type>` defaults `--account` to the wallet address loaded from `PRIVATE_KEY`/`MNEMONIC` when no account is provided.\n- `fhe-test init --bulk` calls the contract-level all-types initializer and is mutually exclusive with `--type`.\n- `fhe-test init --type <type>` may be repeated to initialize selected types without bulk mode.\n- `fhe-test init` returns `transactionHashes` as an array because non-bulk initialization may send one transaction per initialized type.\n- `fhe-test op` exposes FHETest operator demos as explicit subcommands, not as a generic `--type` flag. Keep operation names aligned with the underlying behavior, such as `add-uint64` and `xor-uint256`.\n- `token transfer` uses `confidentialTransferFrom` when `--from` is set, spending an existing operator allowance instead of the loaded wallet's own balance.\n- `token transfer` returns `transferredHandle` because ERC-7984 does not revert on insufficient balance; the token ACL lets the recipient (not the sender) decrypt it with `user-decrypt direct --handle <transferredHandle> --contract <token address>`.\n- `token transfer --verify` decrypts the sender balance before/after and reports `deltaMatches` (`balanceBefore - balanceAfter === <requested amount>`); it is rejected together with `--from` because the operator wallet cannot decrypt the `--from` account's balance.\n- `token balance --account` defaults to the wallet address loaded from `PRIVATE_KEY`/`MNEMONIC` when omitted.\n","isInternal":false,"tokens":1022,"sizeBytes":4472},{"name":"ENGINE.md","path":"sdk/cli-js-sdk/docs/agents/ENGINE.md","rawUrl":"https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/docs/agents/ENGINE.md","title":"Subagent: engine","category":"subagent-persona","format":"markdown","content":"# TypeScript Engine\n\nDefault to Node.js with pnpm. The repository is a pnpm workspace (`packages/*`); run root scripts from the workspace root and use `pnpm --filter <package>` to target one package.\n\n- Use `pnpm install` for dependency installation.\n- Use `pnpm run <script>` for package scripts.\n- Use `pnpm exec <binary>` for local binaries.\n- Use `pnpm dlx <package> <command>` for one-off package execution.\n- Use `tsx` for running TypeScript entry points in development.\n- Use `tsdown` via `pnpm run build` for the compiled CLI artifact.\n- Use `tsc --noEmit` for type-checking.\n\n## APIs\n\n- Read environment variables from `process.env`.\n- Prefer built-in Node APIs for filesystem, path, URL, and process behavior.\n- This project targets Node.js 22 or newer because `@fhevm/sdk` requires it.\n","isInternal":false,"tokens":199,"sizeBytes":797},{"name":"TESTING.md","path":"sdk/cli-js-sdk/docs/agents/TESTING.md","rawUrl":"https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/docs/agents/TESTING.md","title":"Subagent: testing","category":"subagent-persona","format":"markdown","content":"# Testing\n\nUse pnpm scripts for verification.\n\n```bash\npnpm run typecheck\npnpm run test\npnpm run build\n```\n\nFor CLI changes, also run relevant help or parser checks, for example:\n\n```bash\npnpm --silent run cli --help\npnpm --silent run cli user-decrypt --help\npnpm --silent run cli delegated-user-decrypt --help\n```\n\nFor load-test changes, validate its complete private package and inspect the\naffected command groups:\n\n```bash\npnpm --filter @cli-fhevm-sdk/load-test run typecheck\npnpm --filter @cli-fhevm-sdk/load-test run test\npnpm load-test --help\npnpm load-test pool --help\npnpm load-test report --help\npnpm load-test baseline --help\n```\n\nAvoid network-dependent checks unless the user asks for them or credentials/RPC access are available.\n\nUnit tests must cover unit conversions and SDK adapter request shapes. In\nparticular, assert permit durations are sent to `@fhevm/sdk` as\n`durationSeconds`; type-checking alone does not catch semantic unit regressions.\n","isInternal":false,"tokens":236,"sizeBytes":964}],"systemPromptSnippet":"<yakaai_skills repo=\"zama-ai/fhevm\">\n<!-- File: coprocessor/docs/references/fhevm_api.md (Tokens: ~7 | Category: anthropic-skill) -->\n# FHEVM API specifications\n\n<!-- File: coprocessor/docs/references/gateway_api.md (Tokens: ~5383 | Category: anthropic-skill) -->\n# Gateway API Specifications\n\n## Endpoints\n\n<details>\n  <summary>GET /keyurl ---- Retrieve links for retrieving the public keys and CRS' in the system.</summary>\n\n#### Description\n\nThis endpoint returns a JSON object containing URLs from an S3 bucket, allowing the client to download key files such as the blockchain public key, CRS files for input proof generation, the bootstrap key, and the address and public verification keys for each of the MPC servers running the TKMS.\n\nFor each file (with the exception of the verification key and address), a list of cryptographic signatures is provided to ensure the integrity and authenticity of the downloaded content. These signatures should be considered as a multi-sig. This means that instead of needing all the signatures to validate the content, only a subset, specifically >1/3 of the total signatures (if n nodes are signing), is required to verify that the content is legitimate. \n\nNo query parameters are required, as the gateway is already preconfigured for a specific blockchain.\n\n\n#### Query Parameters\n\nNo parameters.\n\n#### Headers\n\nNone.\n\n#### Response\n\n**Success (200 OK)**\n\nThe request is successful, and the response will include a JSON object with a `status` and a `response`. The response again consists of the following elements: \n- `crs`: A map of containing information on the different CRS'. The key of the map is the max amount of bits the CRS can support proofs for. The value is an object of the following elements for the given CRS:\n    * `data_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the CRS.\n    * `param_choice`: An integer representing the choice of parameters for the public key to be used with the CRS. \n    * `signatures`: A list of signatures (one from each MPC party constituting the TKMS backend). Each signature is a hex (lower-case) encoded EIP712 signature on the `safe_serialization` of `PublicParam<Bls12_446>`.\n    * `urls`: A list of URLs where the data can be fetched. The data at the end-point is a `safe_serialization` of `PublicParam<Bls12_446>`.\n- `fhe_key_info`: A list of objects, each representing information on a key-set in the system. More specifically each element consists of the following:\n    * `fhe_public_key`: An element which contains information about the public encryption key of a FHE key set. More specifically it consists of the following elements:\n        * `data_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the key.\n        * `param_choice`: An integer representing the choice of parameters used to generate the key. \n        * `signatures`: A list of signatures (one from each MPC party constituting the TKMS backend). Each signature is a hex (lower-case) encoded EIP712 signature on the `safe_serialization` of `CompactPublicKey`.\n        * `urls`: A list of URLs where the data can be fetched. The data at the end-point is a `safe_serialization` of `CompactPublicKey`.\n    * `fhe_server_key`: An element which contains information about the server key (the key used to perform FHE operations on ciphertexts) of a FHE key set. More specifically it consists of the following elements:\n        * `data_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the key.\n        * `param_choice`: An integer representing the choice of parameters used to generate the key. \n        * `signatures`: A list of signatures (one from each MPC party constituting the TKMS backend). Each signature is a hex (lower-case) encoded EIP712 signature on the `safe_serialization` of `CompactPublicKey`.\n        * `urls`: A list of URLs where the data can be fetched. The data at the end-point is a `safe_serialization` of `ServerKey`.\n- `verf_public_key`: **Deprecated and will be removed in the future. Should instead be fetched directly from the config contract on the TKMS blockchain** A list containing of elements, where each element is the information about a TKMS MPC server's signing key. That is, the key which a server uses to sign requests. More specifically each element of the vector consists of the following:\n        * `key_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the key. Currently this value is static for signing keys. That is, it will always be `408d8cbaa51dece7f782fe04ba0b1c1d017b1088`.\n        * `server_id`: The integer ID of the server whose key is being described in the current element. This is an integer in the range [1; n], where n is the amount of MPC servers.\n        * `verf_public_key_url`: The URL end-point of the given server where a serialization of the signing key can be found. The signing key is a `safe_serialization` of `PublicSigKey`.\n        * `verf_public_key_address`: The URL end-point of the given server where a file containing the human-readable Ethereum address of the server's signing key.\n\nFor example the following:\n\n```json\n{\n    \"response\": {\n        \"crs\": {\n            \"256\": {\n                \"data_id\": \"d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\",\n                \"param_choice\": 1,\n                \"signatures\": [\n                    \"0d13...\",\n                    \"4250...\",\n                    \"a42c...\",\n                    \"fhb5...\"\n                ],\n                \"urls\": [\n                    \"https://s3.amazonaws.com/bucket-name-1/PUB-p1/CRS/d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\",\n                    \"https://s3.amazonaws.com/bucket-name-4/PUB-p4/CRS/d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\",\n                    \"https://s3.amazonaws.com/bucket-name-2/PUB-p2/CRS/d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\",\n                    \"https://s3.amazonaws.com/bucket-name-3/PUB-p3/CRS/d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\"\n                ]\n            }\n        },\n        \"fhe_key_info\": [\n            {\n                \"fhe_public_key\": {\n                    \"data_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                    \"param_choice\": 1,\n                    \"signatures\": [\n                        \"cdff...\",\n                        \"123c...\",\n                        \"00ff...\",\n                        \"a367...\"\n                    ],\n                    \"urls\": [\n                        \"https://s3.amazonaws.com/bucket-name-1/PUB-p1/PublicKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-4/PUB-p4/PublicKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-2/PUB-p2/PublicKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-3/PUB-p3/PublicKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n                    ]\n                },\n                \"fhe_server_key\": {\n                    \"data_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                    \"param_choice\": 1,\n                    \"signatures\": [\n                        \"839b...\",\n                        \"baef...\",\n                        \"55cc...\",\n                        \"81a4...\"\n                    ],\n                    \"urls\": [\n                        \"https://s3.amazonaws.com/bucket-name-1/PUB-p1/ServerKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-4/PUB-p4/ServerKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-2/PUB-p2/ServerKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                        \"https://s3.amazonaws.com/bucket-name-3/PUB-p3/ServerKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n                    ]\n                }\n            }\n        ],\n        \"verf_public_key\": [\n            {\n                \"key_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"server_id\": 1,\n                \"verf_public_key_address\": \"https://s3.amazonaws.com/bucket-name-1/PUB-p1/VerfAddress/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"verf_public_key_url\": \"https://s3.amazonaws.com/bucket-name-1/PUB-p1/VerfKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n            },\n            {\n                \"key_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"server_id\": 4,\n                \"verf_public_key_address\": \"https://s3.amazonaws.com/bucket-name-4/PUB-p4/VerfAddress/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"verf_public_key_url\": \"https://s3.amazonaws.com/bucket-name-4//PUB-p4/VerfKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n            },\n            {\n                \"key_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"server_id\": 2,\n                \"verf_public_key_address\": \"https://s3.amazonaws.com/bucket-name-2/PUB-p2/VerfAddress/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"verf_public_key_url\": \"https://s3.amazonaws.com/bucket-name-2/PUB-p2/VerfKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n            },\n            {\n                \"key_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"server_id\": 3,\n                \"verf_public_key_address\": \"https://s3.amazonaws.com/bucket-name-3/PUB-p3/VerfAddress/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n                \"verf_public_key_url\": \"https://s3.amazonaws.com/bucket-name-3/PUB-p3/VerfKey/408d8cbaa51dece7f782fe04ba0b1c1d017b1088\"\n            }\n        ]\n    },\n    \"status\": \"success\"\n}\n```\n\n**Error Responses**\n\n| Status Code | Error Code   | Description                                      |\n| ----------- | ------------ | ------------------------------------------------ |\n| 400         | `BadRequest` | The request is invalid or missing required parameters. |\n| 404         | `NotFound`   | The requested resource was not found.            |\n| 500         | `ServerError` | An internal server error occurred.                   |\n\n#### Example Error Responses\n\n```json\n{\n  \"error\": \"BadRequest\",\n  \"message\": \"The request is invalid or missing required parameters.\"\n}\n```\n\n```json\n{\n  \"error\": \"NotFound\",\n  \"message\": \"The requested resource was not found.\"\n}\n```\n\n```json\n{\n  \"error\": \"ServerError\",\n  \"message\": \"An internal server error occurred. Please try again later.\"\n}\n```\n\n</details>\n\n<details>\n  <summary>POST /verify_proven_ct ---- Input a batch of proven ciphertexts to be validated by the TKMS.</summary>\n\n#### Description\n\nThis endpoint returns a JSON object containing all the signatures on the proven ciphertexts from the TKMS servers. Furthermore the response contains some meta-information distinguishing if the response is for the co-processor setting or FHEVM native setting. In case of the co-processor setting, then the ciphertext storage handles and a signature from the co-processor attesting correct storage is also included.\n\nThe signatures from the TKMS should be considered as a multi-sig. This means that instead of needing all the signatures to validate the content, only a subset, specifically >1/3 of the total signatures, is required to verify that the content is legitimate. \n\n#### Query Parameters\n\nMultiple parameters must be supplied in JSON format:\n- `contract_address`: An EIP-55 encoded address (that is, including the `0x` prefix) of the contract where the proven ciphertext is to be submitted.\n- `caller_address`: An EIP-55 encoded address (that is, including the `0x` prefix) of the user who is providing the encrypted input.\n- `crs_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the CRS used to construct the proof.\n- `key_id`: The 20 byte (lower-case) hex encoded handle/ID identifying the public key used to encrypt the ciphertext with.\n- `ct_proof`: A hex encoding of the serialization of the proven ciphertext. More specifically the TFHE-RS object `ProvenCompactCiphertextList` serialized using `safe_serialization`.\n\n```json\n{\n    \"contract_address\": \"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed\",\n    \"caller_address\": \"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb\" ,\n    \"crs_id\": \"d8d94eb3a23d22d3eb6b5e7b694e8afcd571d906\",\n    \"key_id\": \"408d8cbaa51dece7f782fe04ba0b1c1d017b1088\",\n    \"ct_proof\": \"cdff...\",\n}\n```\n\n#### Headers\n\nNone.\n\n#### Response\n\n**Success (200 OK)**\n\nThe request is successful, and the response will include a JSON object with a `status` and a `response` which  consists of the following:\n\n- `handles`: A vector of handles to each of the ciphertexts which have been proven knowledge of. A handle is a 32 byte (lower-case) hex encoded handle/ID identifying the ciphertext.\n- `kms_signatures`: A list of signatures (one for each of the TKMS servers that respond to the query). Each signature is a hex (lower-case) encoded EIP712 signature on the `safe_serialization` of `ProvenCompactCiphertextList`.\n- `listener_type`: An enum expressing whether the result is for an FHEVM native (`FHEVM_NATIVE`) or co-processor respectively (`COPROCESSOR`).\n- `proof_of_storage`: An optional signature from the co-processor. More specifically if FHEVM native is used it will be an empty string, otherwise it will be a hex (lower-case) encoded EIP712 signature on the request. \n\nFor example the following:\n```json\n{\n    \"response\": {\n        \"handles\": [\n            \"0748b542afe2353c86cb707e3d21044b0be1fd18efc7cbaa6a415af055bfb358\",\n            \"054ab4515b1541878723431005054f154e15e45e15800adb67879679df670456\"\n        ],\n        \"kms_signatures\":[\n            \"15a4f9a8eb61459cfba7d103d8f911fb04ce91ecf841b34c49c0d56a70b896d20cbc31986188f91efc3842b7df215cee8acb40178daedb8b63d0ba5d199bce121c\", \n            \"118165165165423465234414c4c468a4d9684d8e18186d6f786161b4b436c58787cc68418186d6f786161b4b98461166a6a6668e8e118542c154867aab238abd79\", \n            \"1c849848940128065242121b2b12121ed876986da251561650c654564d684654e51610879a9a9798b78b78e7f8787d87c8c8894a454547809586616161464cc8a8\", \n            \"10c864ac145423466798808098c098b09a8908d6432da4544f5e54566b76740454654a54c65454565d65d657e44651241561342441234128888063304854897893\", \n        ],\n        \"listener_type\": \"COPROCESSOR\",\n        \"proof_of_storage\": \"17acd15648740c00849f489498489e4600a60a06068d484b084894988333000cff798751651498d68768753567a4356787c45787e79i8f64d128218927897c8789\"\n    },\n    \"status\": \"success\"\n}\n```\n\n**Error Responses**\n\n| Status Code | Error Code   | Description                                      |\n| ----------- | ------------ | ------------------------------------------------ |\n| 400         | `BadRequest` | The request is invalid or missing required parameters. |\n| 404         | `NotFound`   | The requested resource was not found.            |\n| 500         | `ServerError` | An internal server error occurred.                   |\n\n#### Example Error Responses\n\n```json\n{\n  \"error\": \"BadRequest\",\n  \"message\": \"The request is invalid or missing required parameters.\"\n}\n```\n\n```json\n{\n  \"error\": \"NotFound\",\n  \"message\": \"The requested resource was not found.\"\n}\n```\n\n```json\n{\n  \"error\": \"ServerError\",\n  \"message\": \"An internal server error occurred. Please try again later.\"\n}\n```\n\n</details>\n\n<details>\n  <summary>POST /reencrypt ---- Decrypt a ciphertext under an ephemeral key s.t. a client can learn the decrypted value privately.</summary>\n\n#### Description\n\nThis end-point returns a JSON object containing a signcryption of the plaintext value of an FHE ciphertext that has been (obliviously) decrypted by the TKMS. \nMore specifically the TKMS servers carry out a partial decryption resulting in each of them knowing a secret share of the plaintext (meaning that multiple servers need to maliciously collude in order to learn the decrypted plaintext). They each then signcrypt their share of the plaintext. The response consists of each of these signcryptions along with meta information about the threshold setup and which server provides each signcrypted share of the result. \nSince the signcryption is based on secret sharing it means that only a subset, specifically >1/3 of the total responses, is required to recover the result (assuming all returned signcryptions are correct). \n\n#### Query Parameters\n\nMultiple parameters must be supplied in JSON format:\n- `signature`: A hex (lower-case) encoded EIP712 signature on the public encryption key, `enc_key`, under which the of the ciphertext in question will be reencrypted. \n- `client_address`: An EIP-55 encoded address (that is, including the `0x` prefix) of the end-user who is supposed to learn the reencrypted response.\n- `enc_key`: The hex (lower-case) encoded public encryption key (libsodium) which the reencryption should be signcrypted under.\n- `ciphertext_handle`: The 32 byte (lower-case) hex encoded handle/ID identifying the ciphertext and hence allowing the gateway to fetch it.\n- `eip712_verifying_contract`: An EIP-55 encoded address (that is, including the `0x` prefix) of the contract holding the ciphertext to reencrypt.\n```json\n{\n     \"signature\": \"15a4f9a8eb61459cfba7d103d8f911fb04ce91ecf841b34c49c0d56a70b896d20cbc31986188f91efc3842b7df215cee8acb40178daedb8b63d0ba5d199bce121c\",\n     \"client_address\": \"0x17853A630aAe15AED549B2B874de08B73C0F59c5\",\n     \"enc_key\": \"2000000000000000df2fcacb774f03187f3802a27259f45c06d33cefa68d9c53426b15ad531aa822\",\n     \"ciphertext_handle\": \"0748b542afe2353c86cb707e3d21044b0be1fd18efc7cbaa6a415af055bfb358\",\n     \"eip712_verifying_contract\": \"0x66f9664f97F2b50F62D13eA064982f936dE76657\"\n}\n```\n\n#### Headers\n\nNone.\n\n#### Response\n\n**Success (200 OK)**\n\nThe request is successful, and the response will include a JSON object with a `status` and a `response` which is a list of responses from each TKMS. More specifically each element in the list consists of the following:\n- `payload`: A bincode encoding of the signcryption from a single server along with meta information including the server ID, threshold parameter, type of value encrypted and the specific public key of the server supplying the specific response. \n- `signature`: An EIP712 signature which is hex (low-case) encoded.\n\nFor example the following:\n```json\n{\n    \"response\": [\n        {\n            \"payload\": \"161c5...\",\n            \"signature\": \"15a4f9a8eb61459cfba7d103d8f911fb04ce91ecf841b34c49c0d56a70b896d20cbc31986188f91efc3842b7df215cee8acb40178daedb8b63d0ba5d199bce121c\"\n        },\n        {\n            \"payload\": \"44546...\",\n            \"signature\": \"118165165165423465234414c4c468a4d9684d8e18186d6f786161b4b436c58787cc68418186d6f786161b4b98461166a6a6668e8e118542c154867aab238abd79\"\n        },\n        {\n            \"payload\": \"54cd5...\",\n            \"signature\": \"1c849848940128065242121b2b12121ed876986da251561650c654564d684654e51610879a9a9798b78b78e7f8787d87c8c8894a454547809586616161464cc8a8\"\n        },\n        {\n            \"payload\": \"a516b...\",\n            \"signature\": \"10c864ac145423466798808098c098b09a8908d6432da4544f5e54566b76740454654a54c65454565d65d657e44651241561342441234128888063304854897893\"\n        },\n    ],\n    \"status\": \"success\"\n}\n```\n\n**Error Responses**\n\n| Status Code | Error Code   | Description                                      |\n| ----------- | ------------ | ------------------------------------------------ |\n| 400         | `BadRequest` | The request is invalid or missing required parameters. |\n| 404         | `NotFound`   | The requested resource was not found.            |\n| 500         | `ServerError` | An internal server error occurred.                   |\n\n#### Example Error Responses\n\n```json\n{\n  \"error\": \"BadRequest\",\n  \"message\": \"The request is invalid or missing required parameters.\"\n}\n```\n\n```json\n{\n  \"error\": \"NotFound\",\n  \"message\": \"The requested resource was not found.\"\n}\n```\n\n```json\n{\n  \"error\": \"ServerError\",\n  \"message\": \"An internal server error occurred. Please try again later.\"\n}\n```\n\n</details>\n\n<!-- File: gateway-contracts/docs/references/selectors.md (Tokens: ~24 | Category: anthropic-skill) -->\n## Smart Contract selectors\n\nAll smart contract selectors can be found in the [contract selectors](../../selectors.txt) file.\n\n<!-- File: sdk/cli-js-sdk/packages/cli/package.json (Tokens: ~278 | Category: anthropic-skill) -->\n{\n  \"name\": \"cli-fhevm-sdk\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"bin\": {\n    \"fhevm-sdk\": \"./bin/fhevm-sdk.mjs\"\n  },\n  \"engines\": {\n    \"node\": \">=22.0.0\"\n  },\n  \"scripts\": {\n    \"build\": \"tsdown\",\n    \"cli\": \"node dist/index.mjs\",\n    \"cli:dev\": \"node --import tsx index.ts\",\n    \"test\": \"vitest run\",\n    \"typecheck\": \"tsc --noEmit\"\n  },\n  \"devDependencies\": {\n    \"tsdown\": \"^0.22.2\",\n    \"tsx\": \"^4.21.0\",\n    \"vitest\": \"^3.2.4\"\n  },\n  \"dependencies\": {\n    \"@cli-fhevm-sdk/toolkit\": \"workspace:*\",\n    \"@commander-js/extra-typings\": \"^15.0.0\",\n    \"@fhevm/sdk\": \"0.13.2\",\n    \"@pnpm/tabtab\": \"^0.5.4\",\n    \"commander\": \"^15.0.0\",\n    \"consola\": \"^3.4.2\",\n    \"viem\": \"^2.50.4\"\n  }\n}\n\n<!-- File: sdk/cli-js-sdk/packages/load-test/docs/design/dual-relayer-dispatch.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Design Skill\n\nPath: `sdk/cli-js-sdk/packages/load-test/docs/design/dual-relayer-dispatch.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/load-test/docs/design/dual-relayer-dispatch.md)\n\n<!-- File: sdk/cli-js-sdk/packages/load-test/docs/OPERATIONS.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Docs Skill\n\nPath: `sdk/cli-js-sdk/packages/load-test/docs/OPERATIONS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/load-test/docs/OPERATIONS.md)\n\n<!-- File: sdk/cli-js-sdk/packages/load-test/tsconfig.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Load-test Skill\n\nPath: `sdk/cli-js-sdk/packages/load-test/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/load-test/tsconfig.json)\n\n<!-- File: sdk/cli-js-sdk/packages/toolkit/package.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Toolkit Skill\n\nPath: `sdk/cli-js-sdk/packages/toolkit/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/toolkit/package.json)\n\n<!-- File: sdk/cli-js-sdk/packages/toolkit/tsconfig.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Toolkit Skill\n\nPath: `sdk/cli-js-sdk/packages/toolkit/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/zama-ai/fhevm/HEAD/sdk/cli-js-sdk/packages/toolkit/tsconfig.json)\n\n<!-- File: relayer-http/CLAUDE.md (Tokens: ~2393 | Category: claude-rule) -->\n# relayer-http — development guide\n\nThis file is living: add a rule or change a description here whenever a feature lands that affects them, in the same\nchange. It describes a minimal first version.\n\n## What this repo is\n\nThe Zama relayer over HTTP. It replaces the gateway-chain decryption path: request handlers receive the SDK's\ndecryption requests and the `kms_aggregator` module fans them out to the KMS connector endpoints and aggregates the\nt-of-n answers.\n\n**Minimal first version**: the handlers and the fan-out/aggregation only.\n- No ACL check and no ciphertext-commit (readiness) check in the relayer: the connector's worker performs them and their\n  failures come back as connector error codes. Both can come back later as optional modules in front of the aggregator.\n- No database, no queue, no cache, no response storage.\n\n## Layout\n\n```\nrelayer-http/\n├── Cargo.toml, Cargo.lock, rust-toolchain.toml   # workspace, exact dependency pins (=x.y.z), toolchain 1.97.1\n├── Dockerfile                                     # container image, built from the repository root (see Container image)\n├── .gitignore                                     # target/, config/*.local.yaml (local variants of the configuration)\n├── config/config.yaml                             # example configuration: name, log, http, kms_aggregator\n├── dev/                                           # local development tooling: Makefile, per-topology configs, proxy port-forwards, flow scripts; start with its README.md\n└── crates/relayer-http/src/\n    ├── main.rs                # load config → init logging → App → serve until SIGINT/SIGTERM → drain → exit\n    ├── lib.rs                 # App: the one shared state (both aggregators, http config, shutdown token)\n    ├── config.rs              # RelayerConfig, LogConfig, HttpConfig: YAML + APP_<SECTION>__<FIELD> overrides\n    ├── logging.rs             # tracing subscriber (json | pretty | compact, RUST_LOG) + Log: one request's identifiers on every line\n    ├── endpoint/              # the HTTP layer; start with its docs.md\n    │   ├── mod.rs             # router() and serve()\n    │   ├── error.rs           # ApiError: the one error body and its mapping\n    │   ├── validate.rs        # rules shared by the routes (handles, extraData)\n    │   ├── ops.rs             # GET /liveness, GET /healthz\n    │   └── flows/{mod,user_decrypt,public_decrypt}.rs   # one file per route: wire types, validation, handler (logs each step)\n    └── kms_aggregator/        # fan-out to the KMS connectors and t-of-n aggregation; start with its docs.md\n        ├── mod.rs, config.rs, client.rs, call.rs, aggregator.rs\n        ├── flows/{mod,user_decrypt,public_decrypt}.rs   # one file per flow: checks, counting, output\n        ├── mock.rs, scenarios.rs                       # test only: scripted connector, YAML scenario runner\n        └── scenarios/*.yaml                            # behaviour scenarios, run by cargo test\n```\n\nTwo modules, each with its `docs.md` next to the code: `endpoint/docs.md` (routes, payloads, responses, every\nerror code and its mapping) and `kms_aggregator/docs.md` (how an aggregation runs, one node call, checks,\nconfiguration → behaviour). The implementation plans live outside the repository (`relayer_specs_plans/`).\n\n## Configuration\n\nOne YAML file (`config/config.yaml` is the example), four sections: `name`, `log` (optional, defaults to JSON\nlines), `http` (bind address, body limit, body read timeout, supported chain ids) and `kms_aggregator` (deadline,\nretries, thresholds, optional checks, the KMS endpoints). Any field can be overridden with `APP_<SECTION>__<FIELD>` (durations carry a\nunit, e.g. `APP_KMS_AGGREGATOR__CALL__TIMEOUT=7s`). API keys are never in the file: each endpoint names the env var\nholding its key. Local variants go to `config/*.local.yaml`, ignored by git.\n\n## Commands\n\nFrom `relayer-http/`:\n\n```sh\ncargo fmt -- --check      # not --all: cargo-fmt would follow the kms-connector-api path dependency into generated bindings\ncargo clippy --workspace --all-targets -- -W clippy::perf -W clippy::suspicious -W clippy::style -D warnings\ncargo test --workspace\ncargo test -p relayer-http yaml_scenarios          # the aggregator scenarios only\ncargo run -p relayer-http -- config/config.yaml    # needs the KMS_<i>_API_KEY env vars named in the config\n```\n\nEvery change must pass the first three. Check exit codes strictly (a grep on the output hides a failing build).\n\nAgainst the local fhevm stack: `make -C dev up` (connector proxies and their host port-forwards), `make -C dev run`\n(the relayer with the config matching the running topology), `make -C dev public-decrypt` / `user-decrypt` (one flow\neach, from the e2e container), `make -C dev check` (the three commands above). See `dev/README.md`.\n\n## Container image\n\n`Dockerfile` follows the relayer's and the kms-connector's model: the golden `rust-glibc` builder pinned by\n`RUST_IMAGE_VERSION` (single source of truth: `rust-toolchain.toml`, read by the CI template), `cargo build --locked\n--release`, a `glibc-dynamic` runtime running as the `fhevm` user, no configuration baked in. The build context is the\n**repository root**: the crate depends on `kms-connector/crates/api` by path and that workspace references its\nsiblings, which the Dockerfile copies at the same relative places.\n\n```sh\n# from the repository root\ndocker build -f relayer-http/Dockerfile --build-arg RUST_IMAGE_VERSION=1.97.1 -t relayer-http .\ndocker run --rm -p 8080:8080 -v \"$PWD/relayer-http/config/config.yaml:/app/config/config.yaml:ro\" \\\n  -e KMS_00_API_KEY=... relayer-http            # the config is mounted at /app/config/config.yaml\n```\n\nCI publishes the image as `ghcr.io/zama-ai/fhevm/relayer-http` through `.github/workflows/relayer-http-docker-build.yml`\n(pushes to `main`/`release/*`, releases, manual runs, or a call from the e2e orchestrator). The two other workflows,\n`relayer-http-tests.yml` and `relayer-http-dependency-analysis.yml`, run on pull requests: the three commands above,\nthen `cargo update -w --locked`, `cargo-deny check license` against `deny.toml` (every allowed license must be used)\nand `cargo-audit audit` with `.cargo/audit.toml`. All three are gated on changes under `relayer-http/**`,\n`kms-connector/crates/api/**` and `kms-connector/Cargo.toml`.\n\n## Rules\n\n**No gateway interaction.** The relayer never talks to the gateway chain and carries no gateway-specific\nconfiguration, optional checks included. Every on-chain read goes to a host chain through host contracts, Ethereum\nbeing the reference.\n\n**No unexpected panic.** Both crate roots deny `clippy::unwrap_used`, `expect_used`, `indexing_slicing` and `panic`\n(allowed in tests). Every failure is a typed error returned to the caller. Configuration validation bounds every value\nthe runtime arithmetic relies on (`call.timeout <= 60s`, `backoff_max <= call.timeout`, semaphore size capped) so that no\narithmetic can overflow later. A panic inside a spawned task is counted as a failure, never propagated.\n\n**Fail fast.** Never wait for something that cannot change the outcome: when `counted + pending < threshold` the\nremaining calls are cancelled at once. One deadline per request, no queue, no ETA; the client retries.\n\n**HPA compatible.** No per-request state outside the request's own future: no shared map, no registry, no sticky\nsession. Every replica is identical; the call semaphore is per pod. If per-request state is ever needed, it goes behind\na trait so that Redis (or another store) can back it later.\n\n**Errors.** Modules return typed errors (`thiserror`), with what the caller needs to act (counts, dominant connector\nerror). Errors are logged once, at the boundary that answers the client. No `error!` inside a module for an expected\nfailure.\n\n**Logging.** `tracing` only, structured fields, short messages. Every endpoint line about a request goes through its\n`Log` (`logging.rs`) and carries `request_id`, `flow`, `handles`, `decryption_id`, the last two `none` until known:\na known event is a method on `Log`, any other line is `log!(level, log, fields…, \"message\")`. Aggregator lines carry\nthe same identifiers through the `aggregation` span; a task spawned for a request inherits it (`in_current_span`).\nEvery failed node attempt is one `warn`. Never log request or response bodies, shares, signatures, header values or\nURLs. The subscriber is installed by `main`, never by a module; `log:` is optional and defaults to JSON lines\n(`log.format`: `json` | `pretty` | `compact`, plus the relayer's `show_*` switches); the level filter is `RUST_LOG`,\ndefault `warn,relayer_http=info`.\n\n**Configuration.** Nested structs use `deny_unknown_fields`; `validate()` messages name the field with its dotted path\n(`kms_aggregator.call.timeout must …`); secrets appear only as env var names; durations carry a unit.\n\n**Minimal code.** Few types, one function per loop, a one-line doc comment per item, no framework where a function does.\nProduction-ready means no panic, typed errors, logs, cancellation and tests, not features.\n\n**Compatibility.** The connector interface comes from the `kms-connector-api` crate (path dependency, never its\n`endpoint` feature): DTOs, routes, error codes and their `retryable` flag are used as they are, never redefined.\n\n**Tests.** A unit test per function, next to it. Paused tokio time (`start_paused`) for anything timed, so durations\nare exact and tests are instant. Behaviour is described in YAML scenarios run by `cargo test`; adding a case is adding\na file.\n\n**Documentation.** Every module has a `docs.md` produced with the module and updated in the same change as any\nbehaviour change, plus a one-line doc comment on every item. The error code table in `endpoint/docs.md` (every code,\nits status, when it happens, how aggregation errors map to it) is updated in the same change as any change to that\nmapping. This `CLAUDE.md` is updated the same way: new rules and\nchanged descriptions land with the feature that motivates them.\n\n<!-- File: sdk/cli-js-sdk/docs/agents/ARCHITECTURE.md (Tokens: ~982 | Category: subagent-persona) -->\n# Architecture\n\nThe repository is a pnpm workspace. Use the existing boundaries when adding behavior.\n\n## Packages\n\n- `packages/toolkit` (`@cli-fhevm-sdk/toolkit`): the library layer. It wraps `@fhevm/sdk` and FHETest with importable flows and must not depend on CLI packages (`commander`, `consola`, `@pnpm/tabtab`).\n- `packages/cli` (`cli-fhevm-sdk`): commander command registration and the `fhevm-sdk` binary. It consumes the toolkit through `@cli-fhevm-sdk/toolkit` package imports (root export or deep subpaths such as `@cli-fhevm-sdk/toolkit/flows/input-proof`), never through relative paths.\n- `packages/load-test` (`@cli-fhevm-sdk/load-test`): a private operator application, not a publishable SDK library. It owns load models, durable pools, raw relayer wire validation, collectors, reports, baselines, and its Commander surface. It may use public `@fhevm/sdk` entry points directly for SDK-native workload journeys and proof workers, and uses the toolkit for shared network, account, contract, ACL, and value behavior. Load orchestration must not move into toolkit.\n\nThe toolkit's `exports` map points at TypeScript source; the CLI build (`tsdown`) bundles the toolkit into `packages/cli/dist/` via `deps.alwaysBundle` while keeping npm dependencies external. Because of that, the toolkit's runtime npm dependencies must also be declared in `packages/cli/package.json`.\n\n## Toolkit boundaries (`packages/toolkit/src`)\n\n- `flows`: orchestration only. Compose config, SDK, contract, ACL, transaction, and value helpers here. Group command families into subfolders such as `fhe-test`, `public-decrypt`, `user-decrypt`, `delegated-user-decrypt`, and `token`.\n- `fhevm`: `@fhevm/sdk` adapters and SDK response normalization.\n- `fhe-test`: FHETest ABI and contract reads/writes.\n- `token`: ERC-7984 confidential token ABI and contract reads/writes.\n- `acl`: ACL delegation reads/writes.\n- `config`: network registry, runtime config, account loading, and client contexts.\n- `values`: clear-value parsing, random values, and JSON serialization helpers.\n- `shared`: cross-cutting helpers like progress and transaction waiting.\n- `types.ts`: networks, FHE value types, and flow result types shared across packages.\n- `index.ts`: the public API barrel; keep new public functions exported from here. Deep subpath exports stay available for lazy loading.\n\nKeep SDK integration on entry points declared by `@fhevm/sdk`; do not resolve or\nimport files from its private `_esm`, `_cjs`, or internal source layout. Toolkit\npermit APIs use seconds, matching `@fhevm/sdk`. Human-facing CLI options may use\ndays, but must convert at the CLI boundary.\n\nCustom FHEVM chains must include the host-chain `protocolConfig` contract used\nby the SDK to resolve the protocol and compatible WASM versions.\n\n## CLI boundaries (`packages/cli`)\n\n- `src/cli`: command registration, argument parsing, stdout/stderr behavior.\n- `bin/completion-server.mjs`: static tab completion resolver. It must stay lightweight and must not import TypeScript runtime, SDK clients, config, or flows.\n\nWhen adding a command, prefer:\n\n1. CLI module in `packages/cli/src/cli/commands`.\n2. Flow module in the matching `packages/toolkit/src/flows/<command-family>` folder.\n3. Adapter changes only at the boundary being crossed.\n\nKeep raw SDK response casts and raw contract calls out of CLI and flow code when practical.\nKeep expensive flow and SDK imports inside command actions, not at CLI module top level.\n\n## Load-test boundaries (`packages/load-test/src`)\n\n- `scenario` and `suite`: validated workload data, exact flow allocation, pool planning, and sequential suite orchestration.\n- `runner` and `flows`: scheduler lifecycle plus one executor per relayer flow.\n- `relayer`: bounded, runtime-validated raw HTTP protocol adapters. Never trust wire data through TypeScript casts.\n- `pool`: durable pool schemas, writers, cursors, and on-chain/off-chain preparation.\n- `collectors` and `report`: optional observations, strict versioned report schema, rendering, comparison, and explicit baseline blessing.\n- `cli`: argument parsing and lazy action wiring only.\n\nReport and baseline reads must pass the versioned runtime schema. A missing\nbaseline may skip a comparison; a corrupt or incompatible baseline must fail.\nBaseline mutation belongs only to the explicit `baseline bless` command and is\nstaged only after every suite report validates.\n\n<!-- File: sdk/cli-js-sdk/docs/agents/CLI.md (Tokens: ~1022 | Category: subagent-persona) -->\n# CLI\n\nUse these tools for CLI work:\n\n- `commander` for CLI interface\n- `@commander-js/extra-typings` for TypeScript types\n- `consola` for Elegant Console Wrapper\n- `@pnpm/tabtab` for shell tab completion\n\nBehavioral guidance:\n\n- Keep progress and status logs on stderr.\n- Keep the final machine-readable response on stdout as JSON.\n- Update `README.md` examples and this guidance when changing command behavior, options, outputs, defaults, or supported flows.\n- Global options may be passed before or after subcommands; use `optsWithGlobals()` from the command action context.\n- The CLI ships as the `fhevm-sdk` binary (`packages/cli/bin/fhevm-sdk.mjs`, exposed via `pnpm link` run from `packages/cli`) and runs compiled `packages/cli/dist/index.mjs`; run `pnpm run build` before linking or using `pnpm run cli`.\n- Use `pnpm run cli:dev` for source-mode CLI checks without rebuilding.\n- The workspace-root `.env` is loaded by `packages/cli/src/env.ts` relative to the repository, not the working directory; shell variables take precedence.\n- `completion-server` is invoked by tabtab's shell templates; the binary routes it to `packages/cli/bin/completion-server.mjs` before loading `tsx` or runtime flow modules. Keep its stdout limited to completion items.\n- Keep completion metadata in `packages/cli/bin/completion-server.mjs` aligned with command help whenever changing commands, options, choices, or descriptions.\n- Keep CLI command modules free of top-level flow imports. Runtime flow modules should be loaded with dynamic imports inside `.action()` handlers so help and completion startup stay fast.\n- FHETest is the only contract target, except `token transfer`/`token balance`, which target ERC-7984 confidential tokens and require `--contract` since there is no per-network token default.\n- Networks may target different host chains; do not assume Ethereum Sepolia for every network.\n- Keep decrypt-family naming consistent: the `direct` subcommand does direct handle decryption, while `fresh` and `stored` are FHETest demo subcommands.\n- The decrypt family roots (`user-decrypt`, `public-decrypt`, `delegated-user-decrypt`) are pure dispatchers with no options of their own; their `direct` subcommands decrypt existing `--handle` values from any contract, where `--contract` is the ACL pairing contract and defaults to FHETest. A bare root command with no subcommand prints help.\n- `fresh` creates or stores a new FHETest handle before decrypting.\n- `stored` reads an existing FHETest handle from the wallet/account/delegator type slots (defaulting to the bool slot); it has no `--handle`.\n- Public decrypt `fresh` stores with `makePublic=true`.\n- User decrypt and delegated user decrypt `fresh` store with `makePublic=false`.\n- Delegated flows use `PRIVATE_KEY`/`MNEMONIC` for the delegate and `DELEGATOR_PRIVATE_KEY`/`DELEGATOR_MNEMONIC` for the encrypted data owner.\n- `fhe-test inspect` is read-only. Keep raw `--handle` inspection mutually exclusive with account/type inspection.\n- `fhe-test inspect --type <type>` defaults `--account` to the wallet address loaded from `PRIVATE_KEY`/`MNEMONIC` when no account is provided.\n- `fhe-test init --bulk` calls the contract-level all-types initializer and is mutually exclusive with `--type`.\n- `fhe-test init --type <type>` may be repeated to initialize selected types without bulk mode.\n- `fhe-test init` returns `transactionHashes` as an array because non-bulk initialization may send one transaction per initialized type.\n- `fhe-test op` exposes FHETest operator demos as explicit subcommands, not as a generic `--type` flag. Keep operation names aligned with the underlying behavior, such as `add-uint64` and `xor-uint256`.\n- `token transfer` uses `confidentialTransferFrom` when `--from` is set, spending an existing operator allowance instead of the loaded wallet's own balance.\n- `token transfer` returns `transferredHandle` because ERC-7984 does not revert on insufficient balance; the token ACL lets the recipient (not the sender) decrypt it with `user-decrypt direct --handle <transferredHandle> --contract <token address>`.\n- `token transfer --verify` decrypts the sender balance before/after and reports `deltaMatches` (`balanceBefore - balanceAfter === <requested amount>`); it is rejected together with `--from` because the operator wallet cannot decrypt the `--from` account's balance.\n- `token balance --account` defaults to the wallet address loaded from `PRIVATE_KEY`/`MNEMONIC` when omitted.\n\n<!-- File: sdk/cli-js-sdk/docs/agents/ENGINE.md (Tokens: ~199 | Category: subagent-persona) -->\n# TypeScript Engine\n\nDefault to Node.js with pnpm. The repository is a pnpm workspace (`packages/*`); run root scripts from the workspace root and use `pnpm --filter <package>` to target one package.\n\n- Use `pnpm install` for dependency installation.\n- Use `pnpm run <script>` for package scripts.\n- Use `pnpm exec <binary>` for local binaries.\n- Use `pnpm dlx <package> <command>` for one-off package execution.\n- Use `tsx` for running TypeScript entry points in development.\n- Use `tsdown` via `pnpm run build` for the compiled CLI artifact.\n- Use `tsc --noEmit` for type-checking.\n\n## APIs\n\n- Read environment variables from `process.env`.\n- Prefer built-in Node APIs for filesystem, path, URL, and process behavior.\n- This project targets Node.js 22 or newer because `@fhevm/sdk` requires it.\n\n<!-- File: sdk/cli-js-sdk/docs/agents/TESTING.md (Tokens: ~236 | Category: subagent-persona) -->\n# Testing\n\nUse pnpm scripts for verification.\n\n```bash\npnpm run typecheck\npnpm run test\npnpm run build\n```\n\nFor CLI changes, also run relevant help or parser checks, for example:\n\n```bash\npnpm --silent run cli --help\npnpm --silent run cli user-decrypt --help\npnpm --silent run cli delegated-user-decrypt --help\n```\n\nFor load-test changes, validate its complete private package and inspect the\naffected command groups:\n\n```bash\npnpm --filter @cli-fhevm-sdk/load-test run typecheck\npnpm --filter @cli-fhevm-sdk/load-test run test\npnpm load-test --help\npnpm load-test pool --help\npnpm load-test report --help\npnpm load-test baseline --help\n```\n\nAvoid network-dependent checks unless the user asks for them or credentials/RPC access are available.\n\nUnit tests must cover unit conversions and SDK adapter request shapes. In\nparticular, assert permit durations are sent to `@fhevm/sdk` as\n`durationSeconds`; type-checking alone does not catch semantic unit regressions.\n</yakaai_skills>"}