Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
e73248e
feat(sdk-go): add secure Go SDK
fuller Aug 28, 2026
3a0ef63
fix(sdk-go): address security review findings
fuller Aug 28, 2026
4f9a8a9
ci(sdk-go): use resolvable checkout pin
fuller Aug 28, 2026
3802310
fix(sdk-go): fail closed on unauthenticated private WebSocket
fuller Aug 28, 2026
759897c
ci(sdk-go): use patched Go toolchain for scans
fuller Aug 28, 2026
070eac5
fix(sdk-go): bound decimal scale to close alignScale DoS vector
fuller Aug 28, 2026
b10eb04
fix(sdk-go): fix short-position liquidation floor and rebate fees
fuller Aug 28, 2026
bc848db
fix(sdk-go): detect nil TokenFunc in Bearer.Validate
fuller Aug 28, 2026
58f8a5e
docs(sdk-go): clarify Send()'s intentionally brief conn lock scope
fuller Aug 28, 2026
803cdcb
fix(sdk-go): make reconciler duplicate-order matching deterministic
fuller Aug 28, 2026
d86a37d
fix(sdk-go): accept float64 order IDs in validOrderID
fuller Aug 28, 2026
1583d85
fix(sdk-go): treat empty HTTP method as safe-to-retry GET
fuller Aug 28, 2026
e70cc51
fix(sdk-go): fully redact short/medium-length API keys
fuller Aug 28, 2026
9f74f8b
fix(sdk-go): close remaining security gaps
fuller Aug 28, 2026
1108151
feat(go-sdk): add PKCE OAuth support
fuller Aug 28, 2026
d047593
fix(sdk-go): harden OAuth and transport security
fuller Aug 28, 2026
5b919d7
fix(sdk-go): escape OAuth callback responses
fuller Aug 29, 2026
5d76a22
feat(sdk-go): port Go SDK to developer-platform
fuller Aug 29, 2026
8f59aa4
fix(sdk-go): close cross-SDK review gaps
fuller Aug 29, 2026
10a8ad9
test(sdk-typescript): refresh generated API snapshot
fuller Aug 29, 2026
05bba2b
fix(sdk-go): address outstanding review blockers
fuller Aug 29, 2026
001d0af
fix(sdk): address review compatibility findings
fuller Aug 29, 2026
da6ae70
fix(sdk-go): address authentication review findings
fuller Aug 29, 2026
a96a27f
fix(sdk-go): harden request lifecycle edge cases
fuller Aug 29, 2026
7222436
fix(sdk-typescript): stabilize websocket enum generation
fuller Aug 29, 2026
a4659b2
test(sdk-typescript): avoid generated enum suffix coupling
fuller Aug 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@

# Published TypeScript SDK source, packaging, and release metadata.
/packages/sdk-typescript/** @fuller @ximt

# Published Go SDK source, module metadata, and release workflow.
/packages/sdk-go/** @fuller @ximt
183 changes: 183 additions & 0 deletions .github/workflows/release-go-sdk.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
name: Release Go SDK

on:
push:
tags:
- "packages/sdk-go/v*"
- "packages/sdk-go/websocket/gorilla/v*"

permissions:
contents: read

concurrency:
group: release-go-sdk-${{ github.ref_name }}
cancel-in-progress: false

jobs:
minimum-go:
runs-on: ubuntu-24.04
timeout-minutes: 15
defaults:
run:
working-directory: packages/sdk-go

steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false

- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: "1.23.x"
cache: false

- name: Test with minimum supported Go
env:
GOTOOLCHAIN: local
run: go test ./...

release:
runs-on: ubuntu-24.04
timeout-minutes: 45
env:
# Do not allow an implicit toolchain download during a release.
GOTOOLCHAIN: local
defaults:
run:
working-directory: packages/sdk-go

steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
persist-credentials: false

- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
# The generator module pins the minimum Go toolchain required by the
# vulnerability-fixed code generator; the SDK itself supports Go 1.23.
go-version-file: packages/sdk-go/scripts/go.mod
cache: true
cache-dependency-path: |
packages/sdk-go/go.mod
packages/sdk-go/go.sum
packages/sdk-go/websocket/gorilla/go.mod
packages/sdk-go/websocket/gorilla/go.sum
packages/sdk-go/scripts/go.mod
packages/sdk-go/scripts/go.sum
packages/sdk-go/cmd/demo/go.mod
packages/sdk-go/cmd/demo/go.sum

- name: Verify release tag
id: release
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG_CREATED: ${{ github.event.created }}
RELEASE_TAG_FORCED: ${{ github.event.forced }}
run: |
set -euo pipefail

tag="$GITHUB_REF_NAME"
test "$RELEASE_TAG_CREATED" = "true"
test "$RELEASE_TAG_FORCED" = "false"

case "$tag" in
packages/sdk-go/v*)
module="github.com/gemini/developer-platform/packages/sdk-go"
;;
packages/sdk-go/websocket/gorilla/v*)
module="github.com/gemini/developer-platform/packages/sdk-go/websocket/gorilla"
;;
*)
echo "unsupported Go SDK release tag: $tag" >&2
exit 1
;;
esac

version="${tag##*/}"
if [[ ! "$version" =~ ^v(0|1)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ ]]; then
echo "release tag must use a v0 or v1 semantic version: $tag" >&2
exit 1
fi

# Release tags must be immutable annotated tags. GitHub's tag API
# verifies the signature using the repository's configured signing
# identities; lightweight or unverified tags cannot release.
test "$(git cat-file -t "$tag")" = "tag"
tag_object="$(git rev-parse "$tag^{tag}")"
if ! gh api "repos/${GITHUB_REPOSITORY}/git/tags/${tag_object}" \
-H "X-GitHub-Api-Version: 2022-11-28" | \
jq -e '.verification.verified == true and .verification.reason == "valid"' >/dev/null; then
echo "release tag signature is not verified by GitHub: $tag" >&2
exit 1
fi

tagged_commit="$(git rev-parse "$tag^{commit}")"
test "$tagged_commit" = "$GITHUB_SHA"

{
echo "module=$module"
echo "version=$version"
} >> "$GITHUB_OUTPUT"

- name: Verify release commit is on main
run: git merge-base --is-ancestor "$GITHUB_SHA" origin/main

- name: Verify module dependencies
run: |
set -euo pipefail
go mod verify
(cd websocket/gorilla && go mod verify)
(cd scripts && go mod verify)
(cd cmd/demo && go mod verify)

- run: make test
- run: make race
- run: make vet
- name: Verify 32-bit wire integer decoding
run: GOARCH=386 go test ./generated/clearing
- run: make generate-check
- run: make release-smoke

- name: Install pinned security analyzers
env:
GOBIN: ${{ runner.temp }}/go-bin
run: |
set -euo pipefail
# Use immutable module revisions rather than mutable release tags.
go install golang.org/x/vuln/cmd/govulncheck@d1f380186385b4f64e00313f31743df8e4b89a77 # v1.1.4
go install github.com/securego/gosec/v2/cmd/gosec@c9453023c4e81ebdb6dde29e22d9cd5e2285fb16 # v2.22.8
go install honnef.co/go/tools/cmd/staticcheck@b8ec13ce4d00445d75da053c47498e6f9ec5d7d6 # 2025.1.1
echo "$GOBIN" >> "$GITHUB_PATH"

- name: Run security analyzers
run: make security

- name: Verify module is available from the public Go proxy
env:
SDK_MODULE: ${{ steps.release.outputs.module }}
SDK_VERSION: ${{ steps.release.outputs.version }}
run: |
set -euo pipefail

# A newly pushed tag can take a short time to become visible through
# proxy.golang.org. Poll the proxy rather than silently falling back
# to a direct VCS fetch; this verifies the public consumer path.
for attempt in 1 2 3 4 5 6; do
if output="$(
GOPROXY=https://proxy.golang.org \
GOSUMDB=sum.golang.org \
GOTOOLCHAIN=local \
go list -m "$SDK_MODULE@$SDK_VERSION" 2>&1
)"; then
echo "$output"
exit 0
fi
echo "Go proxy attempt $attempt failed: $output" >&2
if [ "$attempt" -lt 6 ]; then
sleep 10
fi
done

echo "module was not available from proxy.golang.org: $SDK_MODULE@$SDK_VERSION" >&2
exit 1
90 changes: 90 additions & 0 deletions .github/workflows/validate-go-sdk.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: Validate Go SDK

on:
pull_request:
paths:
- "packages/sdk-go/**"
- ".github/workflows/validate-go-sdk.yml"
- ".github/workflows/release-go-sdk.yml"

permissions:
contents: read

jobs:
minimum-go:
runs-on: ubuntu-24.04
timeout-minutes: 15
defaults:
run:
working-directory: packages/sdk-go

steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false

- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: "1.23.x"
cache: false

- name: Test with minimum supported Go
env:
GOTOOLCHAIN: local
run: go test ./...

validate:
runs-on: ubuntu-24.04
timeout-minutes: 45
defaults:
run:
working-directory: packages/sdk-go

steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false

- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
# The generator module pins the minimum Go toolchain required by the
# vulnerability-fixed code generator; the SDK itself supports Go 1.23.
go-version-file: packages/sdk-go/scripts/go.mod
cache: true
cache-dependency-path: |
packages/sdk-go/go.mod
packages/sdk-go/go.sum
packages/sdk-go/websocket/gorilla/go.mod
packages/sdk-go/websocket/gorilla/go.sum
packages/sdk-go/scripts/go.mod
packages/sdk-go/scripts/go.sum
packages/sdk-go/cmd/demo/go.mod
packages/sdk-go/cmd/demo/go.sum

- name: Verify module dependencies
run: |
go mod verify
(cd websocket/gorilla && go mod verify)
(cd scripts && go mod verify)
(cd cmd/demo && go mod verify)

- run: make test
- run: make race
- run: make vet
- name: Verify 32-bit wire integer decoding
run: GOARCH=386 go test ./generated/clearing
- run: make generate-check
- run: make release-smoke

- name: Install pinned security analyzers
env:
GOBIN: ${{ runner.temp }}/go-bin
run: |
# Use immutable module revisions rather than mutable release tags.
go install golang.org/x/vuln/cmd/govulncheck@d1f380186385b4f64e00313f31743df8e4b89a77 # v1.1.4
go install github.com/securego/gosec/v2/cmd/gosec@c9453023c4e81ebdb6dde29e22d9cd5e2285fb16 # v2.22.8
go install honnef.co/go/tools/cmd/staticcheck@b8ec13ce4d00445d75da053c47498e6f9ec5d7d6 # 2025.1.1
echo "$GOBIN" >> "$GITHUB_PATH"

- name: Run security analyzers
run: make security
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ A suite of developer tools for integrating with the [Gemini](https://www.gemini.
| Package | Description |
|---------|-------------|
| [`packages/mcp-server`](packages/mcp-server/) | MCP server exposing Gemini API as tools for AI assistants |
| [`packages/sdk-go`](packages/sdk-go/) | Official Go SDK for the Gemini REST and WebSocket APIs |
| [`samples/`](samples/) | REST and WebSocket examples in TypeScript, Python, and Go |
| [`skills/`](skills/) | Claude Code skills (e.g., terminal candlestick charts) |

Expand Down
57 changes: 57 additions & 0 deletions packages/sdk-go/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
.PHONY: all test race bench fuzz vet security fmt generate generate-check integration release-smoke

all: fmt vet race bench

test:
go test -v ./...
cd websocket/gorilla && go test -v ./...
cd scripts && go test -v ./...
cd cmd/demo && go test -v ./...

race:
go test -race -v ./...
cd websocket/gorilla && go test -race -v ./...
cd scripts && go test -race -v ./...
cd cmd/demo && go test -race -v ./...

bench:
go test -bench=. -benchmem ./websocket/orderbook

fuzz:
go test -fuzz=FuzzHMAC_BuildPayload -fuzztime=5s ./auth
go test -fuzz=FuzzWebSocket_FrameParsing -fuzztime=5s ./websocket

vet:
go vet ./...
cd websocket/gorilla && go vet ./...
cd scripts && go vet ./...
cd cmd/demo && go vet ./...

security:
govulncheck ./...
# Nested modules are scanned explicitly below; excluding them here avoids
# treating their imports as packages in the parent module.
gosec -exclude-generated -exclude-dir=cmd/demo -exclude-dir=scripts -exclude-dir=websocket/gorilla ./...
staticcheck ./...
cd websocket/gorilla && govulncheck ./... && gosec -exclude-generated ./... && staticcheck ./...
cd scripts && govulncheck ./... && gosec -exclude-generated ./... && staticcheck ./...
cd cmd/demo && govulncheck ./... && gosec -exclude-generated ./... && staticcheck ./...

fmt:
gofmt -s -w .
cd websocket/gorilla && gofmt -s -w .
cd scripts && gofmt -s -w .
cd cmd/demo && gofmt -s -w .

generate:
cd scripts && go run generate.go

generate-check: generate
git diff --exit-code generated/

integration:
@test -n "$$GEMINI_OAUTH_ACCESS_TOKEN" || (echo "GEMINI_OAUTH_ACCESS_TOKEN is required"; exit 1)
cd websocket/gorilla && go test -tags=integration ./...

release-smoke:
bash ./scripts/release_smoke.sh
Loading
Loading