The official Go SDK for the Kessel inventory and authorization services. This SDK provides a type-safe gRPC client for managing resources, checking permissions, and interacting with RBAC workspaces.
- gRPC client support -- High-performance gRPC communication via the unified
KesselInventoryService - Type-safe API -- Generated from protobuf definitions at buf.build/project-kessel/inventory-api
- Fluent ClientBuilder -- Construct clients with a chainable builder pattern supporting insecure, TLS, and OAuth2 modes
- RBAC utilities -- REST workspace client and helper functions for RBAC resource/subject references
- OIDC discovery -- Built-in OAuth2 client credentials flow with automatic token caching
go get github.com/project-kessel/kessel-sdk-gopackage main
import (
"context"
"fmt"
"log"
"github.com/project-kessel/kessel-sdk-go/kessel/inventory/v1beta2"
)
func main() {
ctx := context.Background()
inventoryClient, conn, err := v1beta2.NewClientBuilder("localhost:9000").
Insecure().
Build()
if err != nil {
log.Fatal("Failed to create gRPC client:", err)
}
defer conn.Close()
response, err := inventoryClient.Check(ctx, &v1beta2.CheckRequest{
Object: &v1beta2.ResourceReference{
ResourceType: "host",
ResourceId: "server-123",
Reporter: &v1beta2.ReporterReference{Type: "HBI"},
},
Relation: "member",
Subject: &v1beta2.SubjectReference{
Resource: &v1beta2.ResourceReference{
ResourceType: "user",
ResourceId: "alice",
},
},
})
if err != nil {
log.Fatal("Check failed:", err)
}
fmt.Printf("Check result: %v\n", response.Allowed)
}inventoryClient, conn, err := v1beta2.NewClientBuilder(endpoint).
OAuth2ClientAuthenticated(&oauthCredentials, nil).
Build()Or bring your own PerRPCCredentials:
inventoryClient, conn, err := v1beta2.NewClientBuilder(endpoint).
Authenticated(kesselgrpc.OAuth2CallCredentials(&oauthCredentials), nil).
Build()See the examples section for complete working code.
| Method | Transport | Auth | Use case |
|---|---|---|---|
.Insecure() |
Plaintext | None | Local development |
.Unauthenticated(tlsCreds) |
TLS | None | TLS without auth |
.Authenticated(perRPC, tlsCreds) |
TLS | Custom PerRPCCredentials | Bring-your-own auth |
.OAuth2ClientAuthenticated(creds, tlsCreds) |
TLS | Built-in OAuth2 | Client credentials flow |
Pass nil for tlsCreds to use the default TLS configuration.
Every client built with ClientBuilder.Build() uses a 45-second keepalive interval, a 10-second acknowledgment timeout, and permits keepalive pings when no RPC is active. No keepalive call is needed for these defaults. The v1beta2 builder exposes typed functional options for overrides; each option changes only its specified value, so omitted values retain their current setting and an explicit false is honored:
inventoryClient, conn, err := v1beta2.NewClientBuilder(endpoint).
Keepalive(
v1beta2.WithKeepaliveInterval(60*time.Second),
v1beta2.WithKeepaliveTimeout(15*time.Second),
v1beta2.WithKeepalivePermitWithoutCalls(false),
).
Insecure().
Build()Keepalive durations must be positive; Build() returns an error for zero or negative values. grpc-go clamps configured intervals below 10 seconds to 10 seconds. Keepalive is transport-level ping behavior, not an application health check, retry mechanism, or guarantee against server or load-balancer idle timeouts. Servers and gateways must permit the configured ping cadence, including pings while idle, or may close the connection with a GOAWAY carrying too_many_pings. See the configuration-only keepalive example; it builds clients with both defaults and overrides without making an RPC.
The SDK uses standard gRPC status codes:
response, err := inventoryClient.Check(ctx, checkRequest)
if err != nil {
if st, ok := status.FromError(err); ok {
switch st.Code() {
case codes.Unavailable:
log.Fatal("Service unavailable:", err)
case codes.PermissionDenied:
log.Fatal("Permission denied:", err)
default:
log.Fatal("gRPC error:", err)
}
} else {
log.Fatal("Unknown error:", err)
}
}The ListWorkspaces helper automatically paginates through all workspaces
a subject can access. Continuation tokens are handled internally.
import (
v1beta2 "github.com/project-kessel/kessel-sdk-go/kessel/inventory/v1beta2"
v2 "github.com/project-kessel/kessel-sdk-go/kessel/rbac/v2"
)
// Lazy iteration (constant memory)
for resp, err := range v2.ListWorkspaces(ctx, client, subject, "viewer", "") {
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.Object.GetResourceId())
}
// Materialise into a slice
var all []*v1beta2.StreamedListObjectsResponse
for resp, err := range v2.ListWorkspaces(ctx, client, subject, "viewer", "") {
if err != nil {
log.Fatal(err)
}
all = append(all, resp)
}See examples/rbac/list_workspaces.go for a complete working example.
kessel/
auth/ # OAuth2 client credentials, OIDC discovery, AuthRequest interface
config/ # CompatibilityConfig with functional options (legacy)
grpc/ # OAuth2 PerRPCCredentials wrapper for gRPC
inventory/
internal/builder/ # Generic ClientBuilder[C] (Go generics)
v1/ # Generated: health service only (stable)
v1beta1/ # Generated: legacy per-resource-type services
v1beta2/ # Generated: unified API + hand-written client_builder.go
rbac/v2/ # Hand-written: REST workspace client + v1beta2 utility constructors
examples/
grpc/ # gRPC client examples
rbac/ # RBAC workspace examples
console/ # Console identity examples
.github/workflows/ # CI: lint, build-test, buf-generate
Generated vs. hand-written code: All *.pb.go and *_grpc.pb.go files under kessel/inventory/ are generated by buf generate and must not be edited. Hand-written logic lives in kessel/auth/, kessel/config/, kessel/grpc/, kessel/inventory/internal/builder/, kessel/inventory/v1beta2/client_builder.go, kessel/rbac/v2/, and examples/.
Always use v1beta2 for new code. It provides the unified KesselInventoryService with Check, CheckBulk, ReportResource, DeleteResource, and more. The v1beta1 package is legacy and v1 contains only health endpoints.
- Go 1.25 or later
- Docker or Podman (for linting)
- buf (for protobuf code generation)
# Install dependencies
go mod download
# Run tests
make test
# Run tests with coverage report
make test-coverage
# Run linting (via Docker/Podman)
make lint
# Build all example binaries
make build
# Format code
make fmt
# Tidy modules
make mod-tidy
# Regenerate protobuf files from buf.build
make generate| Target | Description |
|---|---|
make test |
Run all tests (go test -v ./kessel/...) |
make test-coverage |
Run tests and generate coverage.html |
make lint |
Run golangci-lint via Docker/Podman |
make build |
Compile example binaries into bin/ |
make generate |
Regenerate protobuf files with buf generate |
make fmt |
Format Go code |
make mod-tidy |
Run go mod tidy |
make clean |
Remove build artifacts |
make help |
Display all available targets |
All examples are standalone package main binaries. Copy the .env.sample file to .env and fill in your values before running.
| Example | File | Description |
|---|---|---|
| Insecure client | examples/grpc/insecure.go |
Connect without TLS for local development and perform a Check |
| Authenticated client | examples/grpc/authenticated.go |
Connect with OIDC discovery and custom PerRPCCredentials via .Authenticated() |
| OAuth2 client | examples/grpc/oauth2client_authenticated.go |
Connect with built-in OAuth2 flow via .OAuth2ClientAuthenticated() |
| Report resource | examples/grpc/report_resource.go |
Report a resource with metadata, common, and reporter representations |
| Delete resource | examples/grpc/delete_resource.go |
Delete a resource by reference |
| Bulk check | examples/grpc/check_bulk.go |
Check multiple permission tuples in a single CheckBulk call |
| Keepalive | examples/grpc/keepalive.go |
Build clients with default and overridden gRPC keepalive settings; no RPC is sent |
| Example | File | Description |
|---|---|---|
| Fetch workspace | examples/rbac/fetch_workspace.go |
Fetch default and root workspaces via the REST API |
| List workspaces | examples/rbac/list_workspaces.go |
List workspaces using gRPC with range-over-func iteration |
# Build all examples
make build
# Run an example
./bin/insecure-example
./bin/authenticated-example
./bin/oauth2client-authenticated-example
./bin/report-resource-example
./bin/delete-resource-example
./bin/check_bulk_example
./bin/keepalive-example
./bin/fetch_workspace
./bin/list_workspaces| Document | Description |
|---|---|
AGENTS.md |
Onboarding guide for AI agents -- architecture, conventions, and pitfalls |
kessel/auth/GUIDELINES.md |
OAuth2 client credentials, token caching, OIDC discovery |
kessel/rbac/v2/GUIDELINES.md |
REST workspace client, gRPC iterator, utility constructors |
kessel/inventory/internal/builder/GUIDELINES.md |
Generic ClientBuilder, auth modes, three-value return |
examples/GUIDELINES.md |
Example binary conventions, env config, error handling |
This section provides step-by-step instructions for maintainers to release a new version of the Kessel SDK for Go.
This project follows Semantic Versioning 2.0.0. Version numbers use the format MAJOR.MINOR.PATCH:
- MAJOR: Increment for incompatible API changes
- MINOR: Increment for backward-compatible functionality additions
- PATCH: Increment for backward-compatible bug fixes
Note: SDK versions across different languages (Ruby, Python, Go, etc.) do not need to be synchronized. Each language SDK can evolve independently based on its specific requirements and release schedule.
- Write access to the GitHub repository
- Ensure quality checks are passing
- Go 1.25 or higher
- buf for protobuf/gRPC code generation:
# On macOS brew install bufbuild/buf/buf # On Linux curl -sSL "https://github.com/bufbuild/buf/releases/latest/download/buf-$(uname -s)-$(uname -m)" -o "/usr/local/bin/buf" && chmod +x "/usr/local/bin/buf"
- Determine the version
Check existing tags (e.g. on GitHub or locally after git fetch --tags), choose the next version using semantic versioning (see Version Management above), then set VERSION for the steps below:
export VERSION=X.Y.Z
echo "Releasing version: v${VERSION}"- Update Dependencies (if needed)
# Regenerate gRPC code if there are updates to the Kessel Inventory API
make generate- Run Quality Checks
# Run linting
make lint
# Run tests
make test
# Build examples
make build- Commit and push (if needed)
If make generate or other changes produced diffs, commit and push them before tagging:
git add .
git commit -m "chore: regenerate protobuf code"
git push origin main- Tag the Release
git tag -a v${VERSION} -m "Release version ${VERSION}"
git push origin v${VERSION}- Create GitHub Release
gh release create v${VERSION} --title "v${VERSION}" --generate-notesOr manually:
- Go to the GitHub Releases page
- Click "Create a new release"
- Select the tag you just created
- Publish the release
After the tag is published, users can install that version with:
go get github.com/project-kessel/kessel-sdk-go@v${VERSION}This project is licensed under the Apache License 2.0 - see the LICENSE file for details.