Skip to content

feat(go): remote signer backends to thirteen-backend parity (stacked on #164) - #179

Open
amilz wants to merge 39 commits into
mainfrom
claude/go-signer-support-4cdff0
Open

feat(go): remote signer backends to thirteen-backend parity (stacked on #164)#179
amilz wants to merge 39 commits into
mainfrom
claude/go-signer-support-4cdff0

Conversation

@amilz

@amilz amilz commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

Builds on #164 (Go foundation: core + memory) to bring the Go implementation to full thirteen-backend parity with Rust and TypeScript:

Memory · Vault · Privy · Turnkey · AWS KMS · Fireblocks · GCP KMS · Dfns · Crossmint · CDP · Para · Openfort · Utila

Stacked on #164. This branch contains #164's commit (rebased onto current main) plus the work below; the diff shown here includes both. If #164 merges first, this PR reduces to the backend work.

What's included

Quality pass on the #164 foundation

  • 64-byte keypair bytes now validate the embedded public half against the seed-derived key (parity with Rust Keypair::try_from)
  • memory.Config.PrivateKey retyped to []byte — the 32-byte seed form is not a valid ed25519.PrivateKey value
  • core.NewHTTPClient honors HTTP(S)_PROXY env config and refuses all redirects (auth headers must never replay against a redirect target)
  • Keypair-file error taxonomy: read failures are IO_ERROR, malformed contents INVALID_PRIVATE_KEY

Thirteen backends (go/signers/<pkg>)

Each is a port of the corresponding Rust module (authoritative spec), with the Rust wiremock unit tests ported to httptest/stubbed-client tests — race-clean across all 14 packages:

Backend Notable behavior ported
vault transit sign endpoint, vault:vN: prefix stripping, key-metadata health check
turnkey P-256 API-key stamping (X-Stamp), r/s left-padding quirk + dedicated test
privy basic auth + privy-app-id, wallet lookup at construction, chain-type guard, authorization-context signing
para sk_/UUID/HTTPS config validation, hex sign-raw with 0x handling, 5s-bounded availability
awskms RAW + ED25519_SHA_512, DescribeKey gate (ECC_NIST_EDWARDS25519, enabled, SIGN_VERIFY)
gcpkms PureEdDSA — raw data, never Digest, EC_SIGN_ED25519 health check
fireblocks RS256 request JWTs (uri/nonce/bodyHash), RAW polling; UseProgramCall rejected at construction before any network call (PROGRAM_CALL broadcasts on-chain — duplicate-spend risk, parity with Rust #153)
dfns User Action Signing challenge flow, Ed25519/P-256/RSA credential keys, serde-exact clientData bytes
cdp EdDSA bearer + ES256 wallet-auth JWTs with key-sorted reqHash, UTF-8-only SignMessage, tamper rejection
crossmint HKDF delegated-signer derivation, encodeURIComponent-exact locators, create/poll/approve flow, SignMessage intentionally unsupported
openfort ES256 x-wallet-auth JWTs, dual-format wallet secret (PEM / bare base64 DER)
utila poll-to-SIGNED flow with tamper detection against the submitted message

Shared conventions across all backends

  • Config struct + New constructor returning a ready-to-use signer; backends with a Rust init() take a context.Context and initialize inline (analog of Rust Signer::from_* / TS async factories)
  • HTTPS enforced by default via core.NewHTTPClient; optional HTTPClient (or SDK-level client) override is the documented escape hatch — the Go analog of Rust with_client
  • Remote signatures verified locally with core.VerifyEd25519 before use, wherever Rust does
  • Transport-raised *core.SignerErrors pass through unwrapped in every backend; untrusted remote text passes through core.SanitizeRemoteResponse
  • Redacting String()/GoString() on every remote signer; no logging, no globals; signers immutable and concurrency-safe after construction

Integration & tooling

  • Vault integration test (-tags=integration) mirroring test_vault_integration.rs, wired to the existing just go-test-integration recipe
  • go-ci.yml: build / vet / race-enabled tests / golangci-lint, gated on go/ changes; just go-test runs -race to match
  • Cross-language parity vectors pinned on both the Go and Rust sides
  • golangci-lint clean at zero findings (including --max-same-issues=0)
  • Dependency isolation is structural: every backend is its own Go module (15 modules: core, testutils, 13 signers) — a memory-only consumer's module graph carries no AWS/GCP SDKs, and the go 1.25.8 toolchain floor forced by google.golang.org/api is confined to the gcpkms module (everything else is go 1.25)

Per-backend Go modules

In-repo replace directives wire the modules together (the cargo path-dep pattern); requires get real versions at first tag, releases tag go/core + go/testutils before the signer modules. justfile go recipes and go-ci.yml iterate every go.mod. Until the first go/... tags exist, @latest cannot resolve the in-repo go/core requirement (documented in go/README.md).

Umbrella package: intentionally omitted

The TS umbrella and Rust enum stay lean via tree-shaking / cargo features. Go has no dead-code elimination across a runtime dispatch switch, so an umbrella would force the AWS + GCP SDKs into every consumer's build. Importing the backend package is the Go-native selector; rationale documented in go/README.md.

Known follow-up

Testing

  • just go-build, just go-fmt (gofmt + vet per module) — clean
  • just go-test (go test -race -count=1 per module) — 14/14 test packages ok across all 15 modules
  • golangci-lint — 0 issues per module (enforced in CI)
  • go build -tags=integration ./... — compiles; vault integration runs under just go-test-integration

Deferred

  • Publish workflow (go/vX.Y.Z), fork-live-tests for Go
  • docs/ADDING_SIGNERS.md Go section + root README three-language presentation
  • Audit-scope decision for Go

🤖 Generated with Claude Code

https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT

HealthyBuilder and others added 16 commits July 2, 2026 18:41
Adds a third-language implementation alongside Rust and TypeScript with full
parity to the shared SolanaSigner contract. Foundation phase only.

- core: Signer interface, SignedTransaction/Completeness, redacting SignerError
  (+ SanitizeRemoteResponse), txutil (bincode+base64 serialize / add-signature /
  classify), VerifyEd25519, HTTPS-only HTTP client, concurrent batch helpers
- signers/memory: in-memory Ed25519 reference backend (base58 / u8-array / raw
  bytes / Solana CLI keypair file)
- testutils: deterministic keypair + test-transaction helpers
- dev tooling: justfile go-* recipes wired into fmt/build/test/test-integration,
  .golangci.yml, .gitignore, .pre-commit-config.yaml

Single Go module at go/ (github.com/solana-foundation/solana-keychain/go),
backends grouped under signers/. Built on gagliardetto/solana-go; no v2/v3 SDK
adapter. Transaction serialization verified byte-identical to Rust bincode via a
pinned cross-language golden vector (core/parity_test.go).
- validate the embedded public half of 64-byte keypair bytes (parity with
  Rust Keypair::try_from, which rejects inconsistent keypair bytes)
- type memory.Config.PrivateKey as []byte: the 32-byte seed form is not a
  valid ed25519.PrivateKey value
- honor HTTP(S)_PROXY environment configuration in core.NewHTTPClient
  (parity with reqwest's default system-proxy behavior)
- relax the go directive from a pinned patch (1.25.6) to 1.25.0 so consumers
  are not forced onto a specific patch toolchain

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT
Port of rust/src/vault: transit sign endpoint, vault:vN: prefix stripping,
local signature verification, key-metadata health check, and the wiremock
test suite (httptest). Includes the -tags=integration test mirroring
test_vault_integration.rs, wired to 'just go-test-integration'.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT
Port of rust/src/turnkey: P-256 API-key request stamping (X-Stamp), the
r/s left-padding quirk with its dedicated unit test, whoami availability
check, and the full wiremock test suite (httptest).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT
Port of rust/src/privy: basic auth + privy-app-id headers, wallet lookup
at construction (Rust init() parity), signMessage RPC with base64
encoding, local signature verification, and the wiremock test suite.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT
Port of rust/src/gcp_kms: PureEdDSA via AsymmetricSign with raw data
(EC_SIGN_ED25519, never Digest), GetPublicKey algorithm health check,
client-injection seam for tests, and the full unit test suite.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT
Port of rust/src/para: X-API-Key auth, sk_ prefix + UUID + HTTPS config
validation, hex sign-raw flow with 0x-prefix handling, status-gated
availability with the 5s bound, and the full wiremock test suite.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT
Port of rust/src/openfort: x-wallet-auth ES256 JWT (uris/reqHash claims,
canonical key-sorted JSON hash), dual-format wallet secret (PEM or bare
base64 DER) parsed lazily at sign time, 0x-hex signature flow with local
verification, and the full wiremock test suite.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT
Port of rust/src/aws_kms: RAW MessageType + ED25519_SHA_512 signing,
config-supplied base58 pubkey with local signature verification,
DescribeKey availability gate (ECC_NIST_EDWARDS25519, enabled,
SIGN_VERIFY), SDK client-injection seam, and the full test suite
(stubbed API + real SDK against httptest).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT
Port of rust/src/fireblocks: RS256 request JWTs (uri/nonce/sub/bodyHash
claims with the 60s skew window), RAW and PROGRAM_CALL signing flows with
status polling, txHash-is-not-a-signature rejection, local signature
verification, and the full wiremock test suite.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT
Port of rust/src/dfns: User Action Signing flow (init challenge, local
credential signing, useraction token), Ed25519/P-256/RSA credential keys
via stdlib PKCS#8/SEC1 parsing, serde-exact clientData bytes, r||s
signature combining with local verification, and the full wiremock test
suite.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT
Port of rust/src/cdp: EdDSA bearer JWT + ES256 X-Wallet-Auth JWT with the
key-sorted reqHash canonicalization, UTF-8-only sign_message quirk,
base58 signature / base64 wire-transaction handling with tamper rejection
before mutating the input, and the full wiremock test suite.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT
Port of rust/src/crossmint: HKDF-SHA256 delegated-signer key derivation,
encodeURIComponent-exact locator encoding, create/poll/approve
transaction flow with signature-source precedence and local verification,
the intentionally-unsupported sign_message quirk, and the full wiremock
test suite.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT
Checked deferred body closes, unused test handler params, doc comments on
exported const blocks, and a Sprintf->String simplification.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT
Documents the config/New pattern, the HTTPClient and SDK-level override
seams, the cross-language sign_message quirks, and the rationale for
omitting an umbrella package in Go.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT
@amilz
amilz marked this pull request as ready for review July 2, 2026 19:59
@amilz
amilz requested a review from dev-jodee as a code owner July 2, 2026 19:59
@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR brings the Go implementation to full thirteen-backend parity with the Rust and TypeScript implementations, adding vault, turnkey, privy, awskms, fireblocks, gcpkms, dfns, crossmint, cdp, para, openfort, and utila signers on top of the core + memory foundation from #164. Each backend is its own Go module (15 modules total), isolating heavy dependencies like the AWS and GCP SDKs from minimal consumers.

  • Turnkey P-256 key derivation (stamp.go): uses ecdh.P256().NewPrivateKey for scalar validation, then correctly extracts X (bytes 1–32) and Y (bytes 33–64) from the 65-byte uncompressed point to construct ecdsa.PrivateKey — verified end-to-end in TestCreateStamp.
  • Crossmint unsigned-wire-format pin (TestSignTransactionSendsPlaceholderSignatures): asserts the posted transaction is exactly [count byte][zero-padded sigs][message bytes], matching Rust Transaction::new_unsigned and the TS kit wire encoding.
  • Openfort unconditional HTTPS check (signer.go): the parsed.Scheme != "https" guard fires before the HTTP client is set, even when HTTPClient is supplied — tests use httptest.NewTLSServer to satisfy it; TestNewRejectsNonHTTPSBaseURL documents this is intentional.

Confidence Score: 5/5

All thirteen backends are ready to merge — the three areas added since the last review (turnkey crypto/ecdh derivation, crossmint unsigned-wire-format test pin, openfort unconditional HTTPS check) each check out, and the issues flagged in previous threads are fixed.

The turnkey P-256 key derivation correctly uses ecdh.P256().NewPrivateKey for scalar validation then extracts X and Y from the right offsets of the 65-byte uncompressed point, with an end-to-end test verifying ecdsa.VerifyASN1 round-trips. The crossmint unsigned-wire-format test pins [count][zero-sigs][message] across all three languages. The openfort HTTPS check is unconditional and tests correctly use httptest.NewTLSServer. Previously flagged issues (stagger cancellation wrapping, dfns combineSignature length validation, para/openfort SignerError passthrough) are all addressed. No new correctness or security issues found across the 13 backends and shared core.

No files require special attention.

Important Files Changed

Filename Overview
go/signers/turnkey/stamp.go parseP256PrivateKey correctly validates the P-256 scalar via ecdh.P256().NewPrivateKey, then splits the 65-byte uncompressed public key at the right offsets (X=point[1:33], Y=point[33:65]) to build ecdsa.PrivateKey — end-to-end verified by TestCreateStamp.
go/signers/crossmint/signer_test.go TestSignTransactionSendsPlaceholderSignatures correctly pins the unsigned-transaction wire format ([count][zero sigs][message]) sent to Crossmint, matching Rust and TS cross-language semantics.
go/signers/openfort/signer.go Unconditional HTTPS base-URL check fires before any network call or client assignment; tests use httptest.NewTLSServer (HTTPS) and TestNewRejectsNonHTTPSBaseURL explicitly documents the custom-client case is intentionally rejected.
go/core/httpclient.go httpsOnlyTransport and CheckRedirect hook correctly block non-HTTPS and redirect requests, returning *core.SignerError that backends correctly unwrap via errors.As through the url.Error wrapper.
go/signers/dfns/signer.go combineSignature tightened to require exactly 32-byte r and s (addressed prior review comment); SignTransaction correctly verifies the returned sig against message bytes, not the full serialized transaction.
go/signers/fireblocks/signer.go UseProgramCall correctly rejected before any network call; pollForSignature properly wraps context cancellation as CodeHTTPError with the cause chained; errors.As guard in doRequest preserves transport-level SignerError codes.
go/signers/crossmint/signer.go Faithful Rust-parity port; extractSignatureFromSerializedTransaction verifies against remote bytes (deliberate, follow-up filed as #181); HTTPS enforced unconditionally; SignMessage correctly unsupported.
go/core/batch.go stagger now wraps context cancellation as CodeHTTPError (addressed prior review comment); batch ordering and cancellation are covered by batch_test.go.
go/signers/awskms/signer.go DescribeKey gate correctly validates ECC_NIST_EDWARDS25519/SIGN_VERIFY/enabled; core.NewHTTPClient transport injected into the AWS SDK HTTP client for HTTPS enforcement.
go/signers/dfns/auth.go signChallenge correctly dispatches on PKCS#8 key type (Ed25519, ECDSA P-256, RSA) and SEC1 P-256, with proper DER encoding for P-256/RSA and raw bytes for Ed25519.
.github/workflows/go-ci.yml CI correctly gates on go/ path changes, runs -race tests and golangci-lint across all 15 modules, mirrors the Rust/TS CI structure.

Reviews (11): Last reviewed commit: "test(go): port the live integration test..." | Re-trigger Greptile

Comment thread go/signers/para/signer.go
Comment thread go/signers/para/signer.go
Comment thread go/signers/openfort/signer.go
Comment thread go/signers/openfort/signer.go
Comment thread go/signers/dfns/signer.go
- para, openfort: preserve SignerError codes raised inside the transport
  (e.g. the HTTPS-only guard's CodeConfigError) instead of re-wrapping as
  CodeHTTPError, consistent with the other HTTP backends; regression
  tests added
- dfns: require r and s to each be exactly 32 bytes in combineSignature
  so a misaligned split fails with an accurate error instead of a
  downstream verification failure; regression test added

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT
Comment thread go/core/batch.go
claude added 3 commits July 3, 2026 03:37
A context cancelled during the stagger delay surfaced as a raw
context.Canceled, breaking the everything-is-a-SignerError contract that
the crossmint/fireblocks polling cancellation sites honor. Wrap it as
CodeHTTPError with the context error reachable via errors.Is; regression
test added (batch.go previously had no test file).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT
Return the transport-raised SignerError directly (errors.As) instead of
re-wrapping its code in a second layer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT
A non-Solana wallet ID now fails with CodeRemoteAPIError ('expected
Solana wallet, got chain_type=...') like the TypeScript signer, instead
of falling through to CodeInvalidPublicKey; missing address is guarded
the same way. Regression tests added.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT
Comment thread go/signers/crossmint/signer.go
PROGRAM_CALL signing broadcasts on-chain without a reusable signature;
rejecting the returned txHash after the fact risks duplicate spends.
Port of the Rust init() rejection (PR #153), plus redacting String().
Request-body tests now assert the exact wire JSON instead of decoding
into the same struct. Adds redacting String()/GoString() + leak test.
Approval is now submitted at most once per polling loop, with sleeps
between re-polls (async registration no longer hard-fails). The pending
approval is selected by our signer locator instead of pending[0], so
multi-approver wallets work. HTTPS validation runs even with a custom
HTTP client. Ports the two Rust regression tests; adds redaction.
Availability now requires status Active, scheme EdDSA, and curve
ed25519 (parity with Rust check_availability); ports the five Rust
availability tests and adds redacting String()/GoString() + leak test.
… check

The shared HTTP client now refuses every redirect (TS parity): the
custom CheckRedirect had removed Go's 10-hop cap, and headers like
X-Vault-Token survive cross-host redirects. Vault, Turnkey, and
Openfort gain redacting String()/GoString() + leak tests. Para
validates HTTPS even when a custom HTTP client is supplied.
memory::tests::parity_vector_dump now asserts the same golden vectors
as go/core/parity_test.go (verified on sdk-v2/v3/v4); the Go test's
dead placeholder-skip branch is gone.
…ME gaps

go-ci.yml gates build/vet/race-tests/golangci-lint on go/ changes.
The justfile no longer masks real golangci-lint failures as 'not
installed'. Malformed keypair-file contents map to InvalidPrivateKey
(read failures stay IOError). README states the Utila and Privy
authorization-context gaps and documents the Go zeroization limitation.
@dev-jodee
dev-jodee marked this pull request as ready for review July 23, 2026 15:13
@dev-jodee dev-jodee changed the title feat(go): remote signer backends to twelve-backend parity (stacked on #164) feat(go): remote signer backends in GO (stacked on #164) Jul 23, 2026
claude and others added 4 commits July 23, 2026 15:24
… redaction tests

awskms.signBytes guarded only CodeConfigError from the transport while
every other backend preserves any *core.SignerError code. The redaction
tests' deliberate %s-verb coverage gets a justified nolint instead of
being rewritten to String().

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT
Port of the Rust utila module: RS256 service-account JWT auth,
transaction initiation + polling, signature extraction verified against
the requested message bytes. All 13 Rust tests ported plus redaction
and error-path coverage; unsigned transactions are padded with
placeholder signatures so the posted payload is byte-identical to
Rust/TS.
Quorum wallets: P-256 authorization keys (PKCS#8, wallet-auth:/
wallet-api: forms), canonical-JSON payload identical to the Privy SDK,
privy-authorization-signature and privy-request-expiry headers, plus
precomputed signatures and external sign functions. Stdlib crypto only;
error taxonomy follows Rust (InvalidPrivateKey, parser details never
echoed).
'just go-test' now matches the go-ci race-enabled run, the utila
redaction test carries the same justified nolint as its siblings, and
CLAUDE.md's project overview reflects the three-language,
thirteen-backend state.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT
@amilz amilz changed the title feat(go): remote signer backends in GO (stacked on #164) feat(go): remote signer backends to thirteen-backend parity (stacked on #164) Jul 23, 2026
15 modules: core, testutils, and one per signer, wired with in-repo
replace directives (the cargo path-dep pattern; requires get real
versions at first tag, core/testutils before signers). Consumers now
inherit only their backend's dependency graph — the go 1.25.8 toolchain
floor forced by google.golang.org/api is confined to gcpkms; every
other module sits at go 1.25 with a pure solana-go graph outside
awskms.

justfile go recipes and go-ci.yml iterate over every go.mod (build,
vet, golangci-lint, race tests per module).

amilz commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator Author

@greptile-apps review — bypassing the file limit; the latest push only touched justfile (go-test now runs -race to match CI), CLAUDE.md (three-language / thirteen-backend overview), and a //nolint in the utila redaction test.


Generated by Claude Code

dev-jodee and others added 3 commits July 23, 2026 11:57
curve.ScalarBaseMult is deprecated (staticcheck SA1019, caught by the
new Go CI); ecdh.NewPrivateKey also subsumes the manual scalar range
check.
solana-go's MarshalBinary already emits a zero placeholder signature
per required signer (identical to Rust Transaction::new_unsigned and
the TS kit encoding), so the padSignatures helper was a no-op — removed
from utila. The new crossmint test asserts the posted bytes are
count || zero-placeholders || message so a solana-go regression cannot
silently change the wire format.
Aligns with crossmint/para/utila, which validate the scheme regardless of
whether a custom HTTPClient is supplied; tests moved to httptest.NewTLSServer
and the rejection test now covers both client modes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012X3zut1xuLEBvfpGGJfoTT

amilz commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator Author

@dev-jodee two notes on the latest rounds:

  • Openfort's HTTPS base-URL check is now enforced unconditionally (b84fae5), aligning it with crossmint/para/utila per Greptile's last observation; its tests moved to httptest.NewTLSServer to match the pattern you established.
  • Greptile's remaining suggestion is in .github/workflows/go-ci.yml: the golangci-lint version is pinned (v2.12.2) but the install script is fetched from the mutable /HEAD/install.sh URL. This session's token can't modify workflow files, so leaving it to you — pinning the script to the release tag (.../v2.12.2/install.sh) or switching to the official golangci/golangci-lint-action closes it.

Generated by Claude Code

resolve-signers gates each signer module behind the same
CI_SIGNER_<X>_ENABLED repository variables; go-test fans out as a
per-module matrix; go-format and go-lint mirror rust-format/rust-lint.
No integration job yet — Rust/TS CI only run live-credential
integration tests (vault is justfile-local in all three languages) and
Go live tests are still on the deferred list.
Ports all eleven Rust tests/test_<backend>_integration.rs files to Go
(-tags=integration): sign-message with local Ed25519 verification,
sign-transaction with base64 decode + message roundtrip, availability.
crossmint/utila fetch a real blockhash (testutils.GetLatestBlockhash)
and sign a minimal empty-instruction transaction, as in Rust. The Rust
suite additionally simulates in LiteSVM; no Go bindings exist, so
verification stays cryptographic (noted per file).

go-ci.yml gains go-integration-test: fork-guarded, Doppler OIDC
secrets, AWS/GCP credential steps per module, matrix over the same
live-credential backends the TS CI runs (utila and vault remain
justfile-local, as in Rust/TS).

amilz commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator Author

@greptile-apps review — bypassing the file limit again; since the last full review the branch gained the turnkey crypto/ecdh public-key derivation, the crossmint unsigned-wire-format test pin, and the openfort unconditional HTTPS base-URL check (b84fae5).


Generated by Claude Code

@dev-jodee
dev-jodee requested review from gitteri and lgalabru July 23, 2026 19:29

@dev-jodee dev-jodee left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants