Repository navigation
Conversation
aelmanaa
force-pushed
the
feat/azure-key-vault-signer
branch
from
September 28, 2026 16:12
34fcb54 to
e7a2b06
Compare
aelmanaa
marked this pull request as ready for review
September 28, 2026 16:23
aelmanaa
requested review from
0xrusowsky,
DaniPopes,
figtracer,
grandizzy,
mablr,
mattsse and
stevencartavia
as code owners
September 28, 2026 16:23
mablr
reviewed
Sep 29, 2026
mablr
left a comment
Member
There was a problem hiding this comment.
Thanks, marking this blocked until foundry-rs/foundry-core#228 is reviewed.
mablr
marked this pull request as draft
September 29, 2026 12:54
This was referenced Sep 29, 2026
aelmanaa
added a commit
to aelmanaa/hardhat-kms
that referenced
this pull request
Oct 3, 2026
The --kms option help said every provider uses Foundry's variables. aws and gcp do; azure uses the names proposed in foundry-rs/foundry#17120, which no Foundry release includes. The Azure credential and adapter comments now say the same. Refs #221 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
aelmanaa
added a commit
to aelmanaa/hardhat-kms
that referenced
this pull request
Oct 3, 2026
) Closes #218 Closes #221 ## What changes **Ignition guide (#218).** `docs/user/guides/deploy-with-ignition.md`: - Step 1's config adds `rehearsalCli: { type: "edr-simulated" }`, a network with no KMS keys, and step 3's `--kms` command passes `--network rehearsalCli`. The page says why it does not use `rehearsal`: that network already lists `deployer`, and the same key passed twice is an error (decision 0008). An earlier revision ran `--kms` without `--network`; that works but prints the plugin's warning against KMS keys on `default`, so review moved it to a named network. - `configuration.md`: the default-network warning sentence now says it also fires for `--kms` without `--network`. - Step 1 shows `contracts/Counter.sol`, byte for byte the same as `examples/ignition/contracts/Counter.sol`. - Step 1's config adds a `sepoliaFork` network (`forking: { url: configVariable("SEPOLIA_RPC_URL") }`), and step 3 shows the command that rehearses on it. Step 2's account-index sentence now names both simulated networks. **Foundry's Azure signer (#221).** Foundry has no released Azure Key Vault signer. Checked with `gh` on 2026-10-03: - foundry-rs/foundry#17120: open, draft. foundry-rs/foundry-core#228: open, draft. - Latest release: v1.8.4 (2026-10-01). Its notes do not mention Azure. The pages that said or implied a released `--azure` now say the Azure variable names and credential order follow the proposal in #17120, and link it: `migrate-from-foundry.md` (intro sentence plus a note under the variables table), `azure-key-vault-setup.md` (the one Foundry sentence in step 3), `configuration.md` (the `--kms` paragraph and the Azure credential chain) and `multiple-keys.md` (the `--kms` intro). The `--kms azure` behaviour is unchanged. Decision 0008 already qualifies the Azure names as following the open PRs, so it is unchanged. The same fix in code (second commit): - The `--kms` option's help text now reads: "Load KMS keys from environment variables for these providers: aws, gcp, azure (comma-separated). aws and gcp use Foundry's variables; azure uses the names proposed in foundry-rs/foundry#17120". `npx hardhat --help` shows the new text. No test or doc quotes it. A `hardhat-kms` patch changeset covers it. - The `KmsOption` TSDoc in `packages/hardhat-kms/src/type-extensions.ts` says the same. `pnpm run docs:api` regenerated no page, because the API reference does not include this global-option augmentation. - The comments in `packages/hardhat-kms-azure/src/internal/credential.ts` (credential order) now refer to the signer proposed in foundry-rs/foundry#17120. The `adapter.ts` comment on the `kid` check now names alloy's Azure signer (alloy-rs/alloy#4267, merged 2026-09-30), whose `sign` checks the response's key version (`crates/signer-azure/src/signer.rs:316` at `3834f7e`). Comment changes need no changeset. - The two "another order than Foundry's" comparisons (`hook-handlers/kms.ts:49`, `scripts/type-escapes.json`) are unchanged: they compare orders and claim no release. ## Evidence Run on 2026-10-03 from this branch: `pnpm run build`, then `pnpm pack` of `hardhat-kms` and `@hardhat-kms/aws` into a new Hardhat 3 project (hardhat 3.18.1, hardhat-ignition 3.1.8, hardhat-ignition-viem 3.1.6, Node 24). The project's `hardhat.config.ts`, `contracts/Counter.sol` and both Ignition modules were extracted from the guide's code blocks by a script. The one change was `keyId: "alias/deployer"`, replaced with a `configVariable` that names an existing AWS test key (a diff confirmed that this was the only difference). `--kms` runs set `AWS_KMS_KEY_ID` to the same key. Simulated networks only: no live broadcast, no funds. Addresses masked. | Command (guide step) | Result | | --- | --- | | `kms accounts --network rehearsal` | `deployer aws kms.keys 0x<addr>` | | `ignition deploy …Counter.ts --network rehearsal --default-sender 0x<addr>` (3) | exit 0, `[ Counter ] successfully deployed`, `Counter.add` executed | | `ignition deploy …Counter.ts --network sepoliaFork --default-sender 0x<addr>` (3), `SEPOLIA_RPC_URL` = a public keyless Sepolia endpoint | exit 0, deployed, `add` executed; a script on `sepoliaFork` read block 11836750, so the fork reads Sepolia | | `AWS_KMS_KEY_ID=… ignition deploy …Counter.ts --network rehearsalCli --kms aws --default-sender 0x<addr>` (3, new) | exit 0, deployed, `add` executed, no plugin warning | | `ignition deploy …CounterFromKms.ts --network rehearsal` (2, `m.getAccount(20)`) | exit 0, deployed | | The old step 3 command, `--network rehearsal --kms aws` | exit 1, as the page now says: `aws, load accounts: AWS_KMS_KEY_ID is already networks.rehearsal.kmsAccounts[0] ("deployer"); use one of them` | `Counter.add` requires `msg.sender == owner`, so each executed `add` shows that the KMS account deployed the contract and sent the call. The `sepolia` commands in steps 2 and 4, and the script in step 2, broadcast to Sepolia, so they were not run. CI already covers `--kms aws` on a network without `kmsAccounts`: the examples test (`packages/hardhat-kms-aws/test/examples/examples.test.ts`) runs `ignition deploy --network localhost --kms aws --default-sender` against LocalStack. No test change was needed. Gates: `pnpm run docs:check` (53 pages, snippets typecheck), `pnpm run check` and `pnpm test` (1,567 tests, 0 failures) pass. The prose slop gate reports 0 findings. ## AI use An AI coding agent (Claude Code) wrote the changes and ran the checks above. A maintainer reviews the PR before merge. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
aelmanaa
added a commit
to aelmanaa/hardhat-kms
that referenced
this pull request
Oct 3, 2026
Closes #224 User pages (`docs/user/**`, `README.md`, `packages/*/README.md`) no longer carry milestone codes, maintainer notes in HTML comments, or links that work only inside the repository. ## What changes - **Opening lines.** Each page's opening now says what works and what was checked, in terms a reader outside the project understands, without a `Status:` prefix. Lines that only said "Implemented, on `main`" or listed the issues that built a feature are gone. Caveats a user needs stay, reworded: - the AWS policy, the Google Cloud least-privilege setup and the Azure custom role are not yet checked against real KMS (the Azure caveat is new; the live tests ran with the developer's own identity); - the plugin is not on npm yet; - each tutorial gives the date and versions it was followed with. - **Issue links.** The links that recorded which issue built a feature are removed. - **Contributor links.** Inline links to the signing pipeline, testing and decision records now point at a user page (the security model) or are dropped. The links that stay are in "Read next" lists or for provider authors, and say "optional" and "in the contributor docs". Two facts that lived only behind those links are now written into the user pages: - in `configuration.md`, how the plugin order with hardhat-ledger changes `eth_accounts` and `eth_requestAccounts`, and why that matters for index-based picks such as Ignition's `m.getAccount(index)`; - in `debug-output.md`, that the providers and signer namespaces print nothing until a connection first uses a key. - **viem authorizations.** The viem `SignedAuthorization` row in the `kms sign-auth` table said about one tuple in 128 is refused, and to use `provider.request` until #140 is fixed. #142 fixed it for KMS senders. `canonicalAuthorizationSignatures` in `transaction-filler.ts` accepts `r` and `s` as quantities and pads them to 32 bytes before signing. Tests send viem authorizations with a leading zero byte in `r` and in `s`, in `transaction-filler.test.ts` (unit) and `sign-transactions.test.ts` (integration). The row now says that. It also says that from an account in the network's `accounts`, Hardhat still refuses a short `r` or `s`: `rpcAuthorizationList` in hardhat-zod-utils 3.0.6 types them as `rpcHash`, exactly 32 bytes. The issue link is gone. - **Template note.** The HTML comment at the top of `first-deploy-aws.md` moves to the rules in `docs/contributor/documentation.md`. That page's milestone rule for user pages is replaced by the new rule. - **Check.** `pnpm run docs:check` now runs a user-page rule, in `scripts/user-pages.ts`, with unit tests in `test/scripts/user-pages.test.ts` (12 cases, in `pnpm test`). - It fails on a milestone code or an HTML comment in a user page. - Fenced, indented and inline code, URLs, link targets and Apple chip names such as "M1 chip" do not count. - Two comments are allowed by name: `<!-- docs-check: skip -->`, and the "Pre-release only." note at the top of `install-before-release.md`, which the release PR uses. ## Before and after Occurrences across `docs/user/**`, `README.md` and `packages/*/README.md`: | Pattern | Before | After | | ------------------------------------- | -----: | ----: | | Milestone codes (`\bM\d+\b`) | 15 | 0 | | HTML comments | 3 | 2 | | Links into `docs/contributor/` | 30 | 7 | | Links to this repository's issues | 38 | 3 | | Links to `docs/live-proof.md` | 1 | 0 | What remains, and why: - **HTML comments (2).** The `docs-check: skip` marker in `configuration.md` is a tooling directive. The pre-release note in `install-before-release.md` is kept on purpose for the release PR. - **Contributor links (7).** Each is labelled optional and in the contributor docs: - `how-it-works.md` "Read next" (2); - `security-model.md` "Read next" (1) and its send-lock paragraph (2); - `configuration.md` provider contract (1); - `tasks.md` history readers (1). - **Issue links (3).** - `install-before-release.md` links #48 and #47. Readers of that page need read access to the repository, so the links resolve for them, and the page goes away with the release. - The `errors.md` row `core.provider.not-available` shows an issue URL template. The page is generated from the error catalogue, so changing it means changing source. - **Not counted.** `foundry-rs/foundry#17120` is a public upstream PR that readers need. The tutorials' commit links (`7c4262e`, `0afbad3`, `ab3ee2a`) show the exact code each run used, and they resolve once the repository is public. `examples/` links stay because the examples are written for users. ## Follow-up The generated pages `docs/user/reference/api/README.md` and `docs/user/reference/errors.md` keep a `Status:` line written for maintainers ("Do not edit by hand; `pnpm run docs:check` fails…"). Changing them means changing `scripts/generate-api-docs.ts` and `scripts/generate-errors-doc.ts`, so it is left for a separate change. ## How it was tested - `pnpm run docs:check`, `pnpm run check`, `pnpm run pkg:check` and `pnpm test` pass. - `test/scripts/user-pages.test.ts` covers: - codes in prose, parentheses and link text, with line numbers; - codes in inline code (including a double-backtick span), fences, a four-backtick fence holding a three-backtick one, and indented code; - a list item's indented continuation, checked as prose; - URLs and link targets, Apple chip names, and identifiers such as `0xM5abc`; - maintainer comments, comments in code, the skip marker, and the pre-release note on its own page and on another page. - lychee 0.24.2 offline over the CI file set reported 0 errors after the first commit, and the new anchors resolve. ## AI use Claude Code wrote the changes and this description. I reviewed every edit against the reader notes for #75 (P1, P4, X10), the issue's acceptance criteria and a separate QA pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
aelmanaa
added a commit
to aelmanaa/hardhat-kms
that referenced
this pull request
Oct 4, 2026
…#269) Closes #242 ## What changes - **Contributor architecture, "Cloud access and credentials"** (`docs/contributor/architecture.md`). It has one flowchart each for AWS, Google Cloud and Azure. Each shows the credential order, the config fields that change it, and where the SDK clients are built, cached and closed. A "Where each step is" list under each diagram cites `path:line` for every arrow and order, in this repo or the SDK at the lockfile versions. - **User page, "How the plugin reaches your cloud"** (`docs/user/explanation/cloud-access.md`). It has a precedence table per provider, the three rules that decide which identity signs, and one diagram each for a laptop, CI with OIDC, a server, VM or container, and a long-lived secret in the environment. The three setup guides, `how-it-works.md`, `docs/README.md` and `AGENTS.md` link it. - **Foundry comparison**: a Credentials section with the AWS and Google Cloud chains, the AWS profile difference, per-key `profile`, and the Azure chain proposed in foundry-rs/foundry#17120. `migrate-from-foundry.md` links it. - **Audit fixes** in the existing diagrams and the text next to them (table below). - **Mermaid check**: `pnpm docs:check` parses every ` ```mermaid ` block with `mermaid.parse()` (`scripts/mermaid-blocks.ts`, tests in `test/scripts/mermaid-blocks.test.ts`, added to the root `test` script). New dev dependencies: `mermaid` 12.1.0 and `dompurify` 3.4.16, both in the catalog. No code under `packages/` changes. ### Spike: `mermaid.parse()` in Node It works, with one shim. In a scratch project, `mermaid` 12.1.0 imported in Node 22 in about 0.6 s, and `parse()` accepted and refused sequence diagrams and unknown diagram types correctly. Flowcharts and state diagrams failed with `DOMPurify.addHook is not a function`. Without a `window`, DOMPurify builds without its API; Mermaid sets up sanitising hooks while it parses labels. Parsing needs only the syntax. So the check gives Mermaid's copy of DOMPurify a no-op `addHook` and `sanitize` before it imports Mermaid, and then flowcharts parse while broken ones fail: an unclosed label, an edge without a target, or a node named `call`. `dompurify` is a direct dev dependency at the version Mermaid resolves, so the check and Mermaid share one copy; a second copy would make the check fail loudly with that same `addHook` error, not pass silently. No browser and no Puppeteer. Cost: parsing the docs' Mermaid blocks adds under a second of CPU to `docs:check` on a warm cache. The test file, which also loads Mermaid, takes about 1.4 s of user CPU (`node --test test/scripts/mermaid-blocks.test.ts`). `mermaid` also adds 117 packages to the dev install. The check found a real error on its first run: the Google Cloud diagram used `call` as a node id, which Mermaid reads as a keyword. Mermaid's line number in its message does not match the block's lines for flowcharts, so the check reports the block's opening fence and Mermaid's text. GitHub renders with its own Mermaid build, which can differ from 12.1.0. Please open the three changed pages on this branch to confirm they render: `docs/contributor/architecture.md`, `docs/user/explanation/cloud-access.md`, `docs/user/explanation/how-it-works.md`. ### Audit of the existing diagrams | Diagram | Finding | Change | | --- | --- | --- | | `architecture.md` Module map | Azure missing from the provider packages node; no `history/`; no history readers | Added Azure and "history reader" to the packages node, and a `history/` node (`tasks` imports `history`, which imports `registry`, `descriptors` and `signer`, from the imports of `history/read.ts`, `history/mask.ts`, `tasks/history.ts`). Removed the "blue = implemented" class: every module is implemented, and it was the only brand colour. | | `architecture.md` Packages table | One SDK per package | Lists `@aws-sdk/client-cloudtrail` and `client-sts`; `google-gax` and `google-auth-library`; `@azure/core-rest-pipeline` (from each `package.json`). The SDK loading paragraph says the same. | | `architecture.md` Sending a transaction | `nonce = max(pending, high-water + 1)` | `max(pending, high-water + 1, highest reservation + 1)` (`send-guard.ts:579-592`). Also added the `eth_chainId` read before the lock (`dispatcher.ts:628-636`) and the uncertain-transaction lookup inside it (`dispatcher.ts:658-660`, `716`), with a cited paragraph below. | | `transactions.md` nonce paragraph (not a diagram) | Same stale rule | Fixed, with a link to the reservations section. | | `how-it-works.md` diagram | Current | No change. | | `how-it-works.md` step 4 | Pre-#199 rule, and "the node's pending count alone decides" on simulated networks, which reservations now contradict | States the three numbers, and that only the high-water mark is off on simulated networks. | | `architecture.md` Signing a message, Library accounts | Checked against `kms-signer.ts:197-237`, `viem/account.ts`, `viem/inputs.ts` | No stale node. | | #177 removed fields, #208 package names | `idempotencyKey`, `approvalTimeoutMs`, `SignContext.chainId` and unscoped package names appear in no diagram | No change. Directory paths keep `packages/hardhat-kms-*`, which is correct. | | Module layout blocks (text, not Mermaid) | Core tree missing `history/` and the `history` task; AWS tree missing `client-settings.ts`, `history.ts`, `history-api.ts` | Added. The code map gains `client-settings` and a history readers row. | ### Facts that changed since #242 was filed - Azure (#255): the plugin picks `ClientSecretCredential` or `ClientCertificateCredential` itself, wraps it so any failure stops the chain, and throws for username and password only when they would be used. The diagram follows `credential.ts` at this base. - AWS (#260): `profile` and `region` can be configuration variables, read in `client-settings.ts` when the adapter is built; an empty value is unset. - Log Analytics host (#261): `api.loganalytics.azure.com`, with the `api.loganalytics.io` token scope. - #242 describes one Azure chain for the keys and the history reader. In the code, `kms history` builds a new chain for each read (`hook-handlers/kms.ts:77-85`); the keys share one per runtime. The docs say so. ### Citation table Repository paths are at 1a5b13d. SDK paths are inside each package in `node_modules`, at the lockfile versions: `@aws-sdk/client-kms` 3.1143.0, `@aws-sdk/core` 3.978.1, `@aws-sdk/credential-provider-node` 3.972.84, `google-gax` 6.10.0, `google-auth-library` 11.1.0, `@azure/identity` 4.13.3. | Diagram step | Source | | --- | --- | | Signer cache keys signers by identity | `packages/hardhat-kms/src/internal/signer/key-cache.ts:79-94` | | Identity: AWS region, profile, endpoint; Google Cloud and Azure none | `packages/hardhat-kms/src/internal/signer/signer-identity.ts:53-74` | | A new signer runs the `createKeyAdapter` hook chain | `key-cache.ts:149`, `packages/hardhat-kms/src/internal/providers/create-adapter.ts:123-132` | | Idle close after 5 s closes the signers and adapters | `key-cache.ts:13`, `key-cache.ts:104-145`, `packages/hardhat-kms/src/internal/signer/kms-signer.ts:236-237` | | `kms history` runs the `readSignHistory` hook chain | `packages/hardhat-kms/src/internal/history/read.ts:111-127` | | AWS handler loads adapter and SDK | `packages/hardhat-kms-aws/src/internal/hook-handlers/kms.ts:48-63` | | AWS region order | `packages/hardhat-kms/src/internal/providers/aws/config.ts:98-107`, `packages/hardhat-kms-aws/src/internal/client-settings.ts:11-14`, `client-settings.ts:26-36` | | `new KMSClient({ customUserAgent, region, profile, endpoint })` | `packages/hardhat-kms-aws/src/internal/adapter.ts:175-184` | | Client config reaches the default provider | `@aws-sdk/client-kms` `dist-cjs/index.js:2175`; `@aws-sdk/core` `dist-cjs/submodules/httpAuthSchemes/index.js:292-305` | | AWS chain order; profile skips environment keys; SSO-in-code step never applies | `@aws-sdk/credential-provider-node` `dist-cjs/index.js:96-160`, `97-125`, `126-134` | | Shared config, `credential_process`, web identity, remote | `index.js:135-139`, `140-144`, `145-149`, `150-153` | | Container credentials, else IMDS unless disabled | `index.js:5-19` | | A non-"try next" error stops the chain; credentials memoised, refreshed 5 min early | `index.js:78-93`, `index.js:21-77`, `index.js:162` | | AWS `destroy()` on idle close | `adapter.ts:148-149` | | AWS history clients, destroyed after the read | `packages/hardhat-kms-aws/src/internal/history-api.ts:94-97`, `119`, `125-128`, `133-138`; `hook-handlers/kms.ts:78-92` | | Google Cloud handler loads adapter, `@google-cloud/kms`, `google-gax` | `packages/hardhat-kms-gcp/src/internal/hook-handlers/kms.ts:40-43`, `94-105` | | Adapter keeps a factory; client built on a call, `fallback: true` | `packages/hardhat-kms-gcp/src/internal/adapter.ts:403-413`, `313-316`, `366-369`, `409-411` | | `google-gax` builds the `GoogleAuth` | `google-gax` `build/src/fallback.js:141-153` | | A failed `initialize()` closes and drops the client; error mapping | `adapter.ts:370-381`, `adapter.ts:345-348`, `packages/hardhat-kms-gcp/src/internal/wire.ts:128-143` | | Google Cloud `close()` on idle close | `adapter.ts:256-258` | | ADC order, no fallback after an unreadable file, quota project | `google-auth-library` `build/src/auth/googleauth.js:245-286`, `257-267`, `269-279`, `281-285`, `287-290`, `315-330`, `336-365` | | Google Cloud history `GoogleAuth` per read | `hook-handlers/kms.ts:52-58`, `88-92` | | Azure factory and credential once per runtime; failed load retried | `packages/hardhat-kms-azure/src/internal/hook-handlers/kms.ts:51-54`, `57-67`, `123-141` | | Chain built from the sources that apply; shared token per scope and tenant | `packages/hardhat-kms-azure/src/internal/credential.ts:443-484`, `288-336` | | Tenant id and username/password throws | `credential.ts:218-224`, `277-280` | | Source 1: secret, else certificate; options; failure stops the chain | `credential.ts:185-188`, `248-282`, `158-178`, `238` | | Source 2: workload identity only when its variables are set | `credential.ts:454-458`; `@azure/identity` `dist/commonjs/credentials/workloadIdentityCredential.js:50-70` | | Source 3: `az`, then `azd` | `credential.ts:459` | | Source 4: managed identity, client id, Cloud Shell and Service Fabric exclusion, 10 s and 3 s | `credential.ts:460-472`, `386-398`, `16`, `23`, `371-379`, `461-464`, `473-481`; `@azure/identity` `dist/commonjs/credentials/managedIdentityCredential/index.js:106-137` | | Chain goes on only on "unavailable"; error ids | `@azure/identity` `dist/commonjs/credentials/chainedTokenCredential.js:79-98`; `packages/hardhat-kms-azure/src/internal/adapter.ts:89-92`, `318-322` | | Key Vault clients per signer; no adapter `close` | `adapter.ts:175`, `212-217`, `389-392` | | Azure history: new chain per read, Log Analytics host and scope | `hook-handlers/kms.ts:77-85`, `packages/hardhat-kms-azure/src/internal/log-analytics.ts:20-26`, `56-60` | | User page diagrams (laptop, CI, server, secret) | The same sources as the rows above; the CI rows also rest on the READMEs of `aws-actions/configure-aws-credentials`, `google-github-actions/auth` and `azure/login`, not on a CI run | | Foundry: AWS and Google Cloud construction | foundry-rs/foundry-core@6228965 `crates/wallets/src/signer.rs:95-107`, `116-130` (read through the GitHub API) | | Foundry: AWS order, Google ADC order, proposed Azure chain | `aws-config` 1.12.0 `src/default_provider/credentials.rs:183-193`, `gcloud-sdk` 0.29.0 `src/token_source/mod.rs:60-77`, foundry#17120 `crates/wallets/src/azure.rs:31-82` at 30544e0, read on 2026-10-03 and not read again for this PR. foundry#17120 and foundry-core#228 are still open; alloy#4267 merged on 2026-09-30. | The user page has no `path:line` citations: user pages stay in terms a reader outside the project understands. It links to the contributor section, marked optional, which carries them. ## How it was tested - `pnpm docs:check` passes. It failed first on the `call` node id, which shows the new check catches a broken block. - `node --test test/scripts/mermaid-blocks.test.ts`: 9 cases pass: no blocks; a valid flowchart; a valid sequence diagram; an unclosed label; an edge without a target; an unknown diagram type; a keyword node id; a broken sequence message; and a mix of valid and broken blocks, including a pie chart. - `pnpm check` passes; `knip` reports nothing. - `prose-slop-gate.py --diff origin/main`: 0 findings. - Only the Mermaid tests ran locally: no package test suite and no cloud calls. CI runs the rest, and lychee in the CI Docs job checks the links and anchors; `docs:check` does not. ## Docs - New: `docs/user/explanation/cloud-access.md`, linked from `AGENTS.md` and `docs/README.md`. - Changed: `docs/contributor/architecture.md`, `docs/contributor/transactions.md`, `docs/contributor/documentation.md` (the seventh check), `docs/user/explanation/how-it-works.md`, `docs/user/explanation/foundry-comparison.md`, the three setup guides, `docs/user/guides/migrate-from-foundry.md`, `AGENTS.md` and `CONTRIBUTING.md` (the `docs:check` comment). ## AI use Claude Code (Claude Opus 5.5) wrote this change: the spike, the check, the diagrams and the text. It read the source and the installed SDK files cited above. The maintainer reviews before merge. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Contributor
|
This pull request is stale because it has been open for 14 days with no activity. It will be closed in 7 days if there is no further activity. |
Wire the `azure-key-vault` wallet feature from foundry-wallets through cast and forge, and enable it in release builds. `--azure` signs with an Azure Key Vault or Managed HSM `P-256K` key selected by `AZURE_KEY_VAULT_KEY_ID`, and is also accepted by `cast wallet list`, Tempo sessions, and `--tempo.sponsor-signer azure://`. foundry-core and alloy are patched from git until both are released. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
aelmanaa
force-pushed
the
feat/azure-key-vault-signer
branch
from
October 18, 2026 22:59
e7a2b06 to
994f338
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Depends on foundry-rs/foundry-core#228 and the next alloy release. alloy-rs/alloy#4267 is merged, but
alloy-signer-azureisn't on crates.io yet. Until both are released, alloy is patched from upstream git at the #4267 merge commit and foundry-core from my fork; the patches will be replaced by the releases before merging.Closes #17112
Wires the
azure-key-vaultwallet feature fromfoundry-walletsthrough cast and forge and enables it in release builds, so--azuresigns with an Azure Key Vault or Managed HSMP-256Kkey selected byAZURE_KEY_VAULT_KEY_ID, like--aws,--gcp, and--turnkey. It is also accepted bycast wallet list --azure, Tempo sessions, and--tempo.sponsor-signer azure://, conflicts withforge script --unlocked, and the key identifier variables are removed fromcast wallet sessionchild processes. The feature is added to the Makefile, release, and Docker feature lists together.I tested a build end to end against a real Key Vault on Sepolia:
cast send --azure, andforge script --azure --broadcastdeploying and calling a contract, with both an Azure CLI login and a service principal. CLI tests cover the missing key identifier and both feature-on and feature-off builds. This depends on foundry-rs/foundry-core#228 and the release of alloy-rs/alloy#4267, which are patched from git until then.This PR was written primarily with Claude Code; I reviewed it and ran the end-to-end test against a real Azure Key Vault.