gcp-core
| Kind | ffi-zig |
|---|---|
| Capabilities | net ffi |
| Categories | cloud web |
| Keywords | gcp google-cloud cloud authentication |
GCP core library - authentication, project config, and shared utilities
Files
| File | Description |
|---|---|
.editorconfig | Editor formatting configuration |
.gitignore | Git ignore rules for build artifacts and dependencies |
.tool-versions | asdf tool versions (Zig, Kit) |
LICENSE | MIT license file |
README.md | This file |
docs/.keep | Keeps the generated documentation directory in the package |
examples/basic.kit | Basic authentication and Cloud Storage request example |
examples/with-token.kit | Example: using an explicit access token |
kit.toml | Package manifest with metadata, capabilities, and tasks |
src/gcp.kit | GCP authentication, token management, request helpers, and OAuth scopes |
tests/gcp-core.test.kit | Tests for GCP core behavior |
tests/types.test.kit | Tests for exported GCP types |
zig/gcp_rsa.zig | Zig FFI implementation for RS256 service-account JWT signing |
zig/kit_ffi.zig | Kit FFI support helpers for Zig externs |
Dependencies
No Kit package dependencies.
This package uses Zig FFI and links against OpenSSL libcrypto for RS256 service-account JWT signing.
Installation
kit add gitlab.com/kit-lang/packages/kit-gcp-core.gitUsage
import Kit.GcpCore as GCP
main = fn =>
match GCP.client-from-env
| Err e ->
println "Authentication failed: ${e}"
| Ok client ->
println "Project ID: ${client.project-id}"
url = "https://storage.googleapis.com/storage/v1/b?project=${client.project-id}"
match GCP.get client url
| Ok response ->
if response.status == 200 then
println response.body
else
println "HTTP ${Int.to-string response.status}: ${response.body}"
| Err e ->
println "Request failed: ${e}"
mainclient-from-env checks the GCP metadata server first, then falls back to environment-based credentials. For service-account credentials, set GOOGLE_APPLICATION_CREDENTIALS to a service account JSON file.
Development
Running Examples
Run examples with the interpreter:
kit run examples/basic.kitRun the explicit token example:
GCP_PROJECT_ID=your-project-id GCP_ACCESS_TOKEN="$(gcloud auth print-access-token)" kit run examples/with-token.kitCompile examples to a native binary:
kit build examples/basic.kit && ./basicRunning Tests
Run the test suite:
kit testRun the test suite with coverage:
kit test --coverageRunning kit dev
Run the standard development workflow (format, check, test):
kit devThis will:
- Format and check source files in
src/ - Run tests in
tests/with coverage
Running Parity Checks
Run interpreter/native parity checks for examples:
kit parity --failures-onlyGenerating Documentation
Generate API documentation from doc comments:
kit docNote: Kit sources with doc comments (##) will generate HTML documents in docs/*.html
Cleaning Build Artifacts
Remove generated files, caches, and build artifacts:
kit task cleanNote: Defined in kit.toml.
Local Installation
To install this package locally for development:
kit installThis installs the package to ~/.kit/packages/@kit/gcp-core/, making it available for import as Kit.GcpCore in other projects.
License
This package is released under the MIT License - see LICENSE for details.
Exported Functions & Types
GCPError
GCP error type with specific variants for different failure modes.
Variants
GCPAuthError {message}GCPCredentialError {message}GCPNotFoundError {message, resource}GCPPermissionDeniedError {message, resource}GCPRateLimitError {message, retry-after-ms}GCPQuotaExceededError {message, quota-metric}GCPInvalidRequestError {message, field}GCPConflictError {message, resource}GCPPreconditionFailedError {message}GCPServerError {message, status}GCPNetworkError {message}GCPTimeoutError {message}GCPGenericError {message, status}is-retryable?
Check if an error is retryable.
Returns true for transient errors that may succeed on retry: - Rate limit errors (with backoff) - Server errors (5xx) - Network errors - Timeout errors
GCPError -> Bool
error-from-status
Create appropriate error from HTTP status code.
Parameters:
Returns:
Int -> String -> String -> GCPError
with-retry
Retry a function with exponential backoff for retryable errors.
Executes the given function and retries if it fails with a retryable error. Uses exponential backoff starting at 100ms, doubling each retry up to max-delay-ms. For rate limit errors, uses the retry-after-ms hint if available.
Parameters:
Returns:
(() -> Result a GCPError) -> Int -> Result a GCPError
# Retry up to 3 times
match GCP.with-retry (fn() => GCP.get client url) 3
| Ok response -> println "Success!"
| Err e -> println "Failed after retries: ${show e}"
with-retry-backoff
Retry with custom backoff configuration.
Parameters:
(() -> Result a GCPError) -> Int -> Int -> Int -> Result a GCPError
# Start with 500ms delay, max 30 seconds
GCP.with-retry-backoff (fn() => GCP.get client url) 5 500 30000
load-service-account
Load service account credentials from JSON key file content.
Parses a Google Cloud service account JSON key file and extracts the credentials needed for authentication. The JSON should be in the format downloaded from the GCP Console (IAM & Admin > Service Accounts).
Parameters:
Returns:
String -> Result ServiceAccount GCPError
json = File.read "service-account.json"
match load-service-account json
| Ok sa -> println "Loaded account: ${sa.client-email}"
| Err err -> println "Error: ${err}"
Errors:
- Returns Err if required fields (project_id, private_key, client_email, token_uri) are missing
load-service-account-file
Load service account from file path.
NonEmptyString -> Result ServiceAccount GCPError
load-service-account-from-env
Load from GOOGLE_APPLICATION_CREDENTIALS environment variable.
() -> Result ServiceAccount GCPError
get-project-id-from-env
Get project ID from environment variables.
Checks the following environment variables in order: 1. GOOGLE_CLOUD_PROJECT (standard for Google Cloud SDK) 2. CLOUDSDK_CORE_PROJECT (gcloud CLI config) 3. GCP_PROJECT (common alternative) 4. GCLOUD_PROJECT (legacy)
Returns:
() -> Option String
match GCP.get-project-id-from-env()
| Some project -> println "Project: ${project}"
| None -> println "No project ID set"
get-access-token
Get access token for a service account with specific scopes.
ServiceAccount -> [String] -> Result AccessToken GCPError
client-with-token
Create GCP client with explicit access token.
NonEmptyString -> NonEmptyString -> GcpClient
client-from-metadata
Create client from metadata server (GCE, Cloud Run, GKE).
() -> Result GcpClient GCPError
client-from-env
Create client from environment. If GOOGLE_APPLICATION_CREDENTIALS is set, use it directly (local development). Otherwise try metadata server first (GCE, Cloud Run, GKE), then fall back to env var.
() -> Result GcpClient GCPError
client-from-service-account
Create a GCP client from service account credentials with specified scopes.
This authenticates using the service account's private key to sign a JWT, then exchanges the JWT for an access token via the OAuth 2.0 token endpoint.
Parameters:
Returns:
ServiceAccount -> [String] -> Result GcpClient GCPError
json = File.read "service-account.json"
match load-service-account json
| Ok sa ->
match client-from-service-account sa [scope-storage-full]
| Ok client -> # Use client for storage operations
| Err e -> println "Auth failed: ${Show.show e}"
| Err e -> println "Load failed: ${Show.show e}"
is-token-expired?
Check if token is expired (with 5 minute buffer).
Returns true if the token will expire within 5 minutes, giving time to refresh before actual expiration.
Parameters:
Returns:
GcpClient -> Bool
if GCP.is-token-expired? client then
match GCP.refresh-token client
| Ok new-client -> # use new-client
| Err e -> println "Refresh failed: ${e}"
refresh-token
Refresh access token using the appropriate method.
Automatically detects how to refresh based on the client configuration: - If the client has service account credentials (private key), uses those to generate a new token with the cloud-platform scope. - Otherwise, attempts to use the metadata server (for GCE/Cloud Run/GKE).
Parameters:
Returns:
GcpClient -> Result GcpClient GCPError
if GCP.is-token-expired? client then
match GCP.refresh-token client
| Ok refreshed -> do-something refreshed
| Err e -> println "Refresh failed: ${e}"
refresh-token-with-scopes
Refresh access token with specific OAuth scopes.
Use this when you need specific scopes instead of the default cloud-platform scope.
Parameters:
Returns:
GcpClient -> [String] -> Result GcpClient GCPError
scopes = [GCP.scope-storage-full, GCP.scope-bigquery]
match GCP.refresh-token-with-scopes client scopes
| Ok refreshed -> do-something refreshed
| Err e -> println "Refresh failed: ${e}"
ensure-valid-token
Ensures the client has a valid (non-expired) token.
If the token is expired or about to expire, automatically refreshes it. If the token is still valid, returns the client unchanged.
This is useful as a wrapper before making API calls to ensure the token is always valid.
Parameters:
Returns:
GcpClient -> Result GcpClient GCPError
match GCP.ensure-valid-token client
| Ok valid-client ->
match GCP.get valid-client some-url
| Ok response -> # handle response
| Err e -> println "Request failed: ${e}"
| Err e -> println "Token refresh failed: ${e}"
ensure-valid-token-with-scopes
Ensures the client has a valid token with specific scopes.
Like ensure-valid-token, but allows specifying the scopes for refresh.
Parameters:
Returns:
GcpClient -> [String] -> Result GcpClient GCPError
get
Make authenticated GET request.
GcpClient -> NonEmptyString -> Result HTTP.Response HTTP.Error
post
Make authenticated POST request.
GcpClient -> NonEmptyString -> String -> Result HTTP.Response HTTP.Error
put
Make authenticated PUT request.
GcpClient -> NonEmptyString -> String -> Result HTTP.Response HTTP.Error
delete
Make authenticated DELETE request.
GcpClient -> NonEmptyString -> Result HTTP.Response HTTP.Error
request
Make authenticated request with custom headers.
GcpClient -> String -> NonEmptyString -> String -> [HTTP.Header] -> Result HTTP.Response HTTP.Error
scope-cloud-platform
Cloud Platform (broad access - use when you need multiple services).
String
scope-cloud-platform-readonly
String
scope-storage-read
Cloud Storage.
String
scope-storage-write
String
scope-storage-full
String
scope-bigquery
BigQuery.
String
scope-bigquery-readonly
String
scope-bigquery-insert
String
scope-compute
Compute Engine.
String
scope-compute-readonly
String
scope-pubsub
Pub/Sub.
String
scope-datastore
Firestore / Datastore.
String
scope-firestore
String
scope-sqlservice-admin
Cloud SQL.
String
scope-spanner-admin
Spanner.
String
scope-spanner-data
String
scope-secretmanager
Secret Manager.
String
scope-cloudfunctions
Cloud Functions.
String
scope-run
Cloud Run.
String
scope-run-admin
String
scope-tasks
Cloud Tasks.
String
scope-scheduler
Cloud Scheduler.
String
scope-iam
IAM.
String
scope-logging-read
Logging.
String
scope-logging-write
String
scope-logging-admin
String
scope-monitoring
Monitoring.
String
scope-monitoring-read
String
scope-monitoring-write
String
scope-cloudkms
Cloud KMS (Key Management Service).
String
scope-dns
Cloud DNS.
String
scope-dns-readonly
String
scope-containerregistry
Container Registry / Artifact Registry.
String
scope-artifactregistry
String
scope-container
Kubernetes Engine (GKE).
String
scope-aiplatform
Vertex AI / AI Platform.
String
scope-service-management
Service Management.
String
scope-service-management-readonly
String
scope-servicecontrol
Service Control.
String
scope-trace-append
Trace.
String
scope-trace-readonly
String
scope-source-read
Source Repositories.
String
scope-source-write
String
scope-sheets
Sheets (for data pipelines that use Sheets).
String
scope-sheets-readonly
String
scope-drive
Drive (for data pipelines that use Drive).
String
scope-drive-readonly
String
scope-drive-file
String
scope-gmail-send
Gmail (for automated email workflows).
String
scope-gmail-readonly
String
scope-calendar
Calendar.
String
scope-calendar-readonly
String
scope-userinfo-email
User info.
String
scope-userinfo-profile
String
scope-openid
String
url-encode
URL encode a string.
String -> String