README
¶
sdk-go
Go SDK for the Genesis Mesh Network Authority HTTP API.
Go ≥ 1.22 required. Zero runtime dependencies (stdlib only + github.com/google/uuid).
Scope
This SDK (1.4) covers the Network Authority's trust API: the sub-clients
below (agreements, boundary decisions, trust evidence, attestations,
selective disclosure, consensus and data usage), offline verification of
their signed records, and signed admin calls to any other route. It has no
governed lifecycle API: no evidence store client or evidence outbox, none
of the 1.3.0 changes outside the controlled path (observations, break-glass
records, the record outbox), and none of the 1.4.0 remediation and review
APIs (remediation records, the due queue, reviews). Those live in the
TypeScript SDK and the
Rust SDK. The embedded field
registry lists their records, but this SDK does not verify evidence exports.
A boundary policy with the 1.4.0 sections (remediation, review_required,
emergency) verifies here like any other.
Install
go get github.com/GenesisMeshLabs/sdk-go@latest
Quick start
package main
import (
"context"
"os"
"github.com/GenesisMeshLabs/sdk-go/genesismesh"
)
func main() {
client, err := genesismesh.NewClient(genesismesh.ClientOptions{
BaseURL: "http://127.0.0.1:9443",
SigningKey: os.Getenv("OPERATOR_KEY"), // base64-encoded 32-byte Ed25519 seed
KeyID: "operator-local", // must match the NA's registered key
})
if err != nil {
panic(err)
}
decision, err := client.Boundary.Decide(context.Background(), map[string]interface{}{
"requesting_agent_id": "agent-a",
"capability": "transactions.read",
})
if err != nil {
panic(err)
}
_ = decision
}
Local Network Authority
To develop against a governed Network Authority on your machine (policies
required, a privileged key for setup and a standard key for your controller),
see Develop Against a Local Network Authority.
It needs genesis-mesh 1.1.0 or later from PyPI.
Sub-clients
Agreement
// Create a capability offer (admin — requires signing key)
offer, err := client.Agreement.Offer(ctx, genesismesh.CapabilityOffer{
OfferorSovereignID: "ALPHA-NA",
ResponderSovereignID: "BETA-NA",
Capabilities: []string{"read:data", "write:log"},
Roles: []string{"role:client"},
ValidityHours: 8760,
})
// Counter an offer
counter, err := client.Agreement.Counter(ctx, map[string]interface{}{
"offer": offer,
"capabilities": []string{"read:data"},
"validity_hours": 4380,
})
// Accept an offer (requires the NA to hold a recognition treaty for the responder)
agreement, err := client.Agreement.Accept(ctx, map[string]interface{}{"offer": offer})
// Verify agreement signatures (no auth required)
result, err := client.Agreement.Verify(ctx, map[string]interface{}{"agreement": agreement})
Boundary
// Issue a boundary decision (admin)
decision, err := client.Boundary.Decide(ctx, map[string]interface{}{
"agreement": agreement,
"requested_capability": "read:data",
})
// Verify a boundary decision (no auth required)
v, err := client.Boundary.Verify(ctx, map[string]interface{}{"decision": decision})
Evidence
// Build signed trust evidence (admin)
// verdict must be one of: "allow" | "block" | "escalate" | "warn"
evidence, err := client.Evidence.Build(ctx, genesismesh.TrustDecision{
SourceSovereignID: "ALPHA",
TargetSovereignID: "BETA",
Verdict: "allow",
Reason: "long-standing member",
})
Attestation
// Issue a membership attestation (admin)
// roles must use a recognized prefix: role:anchor | role:bridge | role:client | role:operator | role:service:<name>
att, err := client.Attestation.Issue(ctx, genesismesh.MembershipAttestation{
SubjectID: "node-xyz",
Roles: []string{"role:client"},
ValidityHours: 8760,
})
// Revoke an attestation (admin)
err = client.Attestation.Revoke(ctx, att.AttestationID, map[string]string{"reason": "key compromised"})
// Set recognition policy (admin)
err = client.Attestation.SavePolicy(ctx, genesismesh.RecognitionPolicy{
LocalSovereignID: "MY-NA",
RecognizedIssuers: []genesismesh.RecognizedIssuer{},
})
Disclosure
// Commit to a set of capabilities (admin)
commitment, err := client.Disclosure.Commit(ctx, genesismesh.CapabilityCommitment{
Capabilities: []string{"read:data", "write:log"},
})
// Generate a Merkle membership proof (no auth required)
proof, err := client.Disclosure.Prove(ctx, genesismesh.CapabilityMembershipProof{
Capability: "read:data",
ProverSovereignID: "BETA",
})
// Issue a one-time nullifier (admin)
nullifier, err := client.Disclosure.Nullifier(ctx, map[string]interface{}{"proof": proof})
// Verify the proof (no auth required)
dv, err := client.Disclosure.Verify(ctx, map[string]interface{}{"proof": proof})
Consensus
Validators vote on a justification proof: the justification_proof returned
with a decision by POST /admin/boundary/evaluate (see Raw admin calls). Pass
votes and proofs back unchanged; every field is covered by a signature.
// Cast a validator vote, signed by the NA as validator (admin)
vote, err := client.Consensus.Vote(ctx, map[string]interface{}{
"justification_proof": justificationProof,
"vote": true,
"reason": "evidence satisfactory",
})
// Assemble a K-of-N consensus proof (admin)
cp, err := client.Consensus.Proof(ctx, map[string]interface{}{
"justification_proof": justificationProof,
"votes": []genesismesh.ConsensusVote{*vote},
"required_threshold": 1,
"validator_sovereign_ids": []string{vote.ValidatorSovereignID},
})
// Verify against the validators' keys (no auth required)
cv, err := client.Consensus.Verify(ctx, map[string]interface{}{
"proof": cp,
"validator_public_keys": map[string]string{vote.ValidatorSovereignID: validatorPublicKey},
})
// cv.Valid, cv.Reason ("valid", "threshold_not_met", "invalid_vote_signature", ...)
DataUsage
// Create a data license policy (admin)
pol, err := client.DataUsage.CreatePolicy(ctx, genesismesh.DataLicensePolicy{
LicenseeSovereignID: "BETA",
AllowedSourceIDs: []string{"src-a"},
AllowedAccessTypes: []string{"read", "aggregate"},
ValidFrom: "2026-01-01T00:00:00Z",
ValidUntil: "2026-12-31T00:00:00Z",
})
// Create a data access intent (admin)
// source_type: "personal" | "proprietary" | "public" | "synthetic"
intent, err := client.DataUsage.CreateIntent(ctx, genesismesh.DataAccessIntent{
Sources: []genesismesh.DataSourceDescriptor{{
SourceID: "src-a",
SourceType: "public",
OwnerSovereignID: "MY-NA",
}},
AccessTypes: []string{"read"},
})
// Get the active policy (no auth required)
activePol, err := client.DataUsage.GetPolicy(ctx)
// Verify intent against policy (no auth required)
dv, err := client.DataUsage.Verify(ctx, map[string]interface{}{"intent": intent, "policy": pol})
Offline verification
From 0.61.0 the SDK verifies Network Authority records locally, using canonical JSON and Ed25519 only, without calling the NA. The reason codes are the Python reference's. Pass the JSON as received.
a, err := genesismesh.VerifyAgreement(agreementJSON, []string{offererKey}, []string{responderKey}, "")
// a.Accepted, a.Reason: "accepted", "invalid_offerer_signature", "graph_digest_mismatch", ...
d, err := genesismesh.VerifyBoundaryDecision(decisionJSON, genesismesh.DecisionVerifyOptions{
OperatorPublicKeys: []string{naPublicKey},
ExpectedPolicies: [][]byte{policyJSON}, // the decision must bind exactly these versions
ExpectedAttestation: attestationJSON, // optional
})
// d.Accepted (verified), d.Authorized (ALLOW or DENY), d.Reason
ok, err := genesismesh.VerifyDataLicensePolicySignature(policyJSON, []string{licensorKey})
v, err := genesismesh.VerifyDataAccessIntent(intentJSON, policyJSON, []string{agentKey}, time.Now())
// v.Valid, v.ViolationReason, v.Violations
An accepted DENY has Accepted true and Authorized false: the decision
verified, and it denies. Revocation is not checked offline.
CanonicalJSON, PolicyDigest, AttestationDigest and PolicySetDigest
reproduce the reference forms. The verifiers pass the shared interop
conformance vectors (genesismesh/testdata/conformance/interop.json), and the
core's cross-language scenario runs them against a live NA.
Raw admin calls
For NA routes not yet covered by a sub-client (e.g. /admin/recognition-treaties),
use BuildAdminHeaders directly:
import (
"bytes"
"encoding/json"
"net/http"
"github.com/GenesisMeshLabs/sdk-go/genesismesh"
)
priv, _, _ := genesismesh.LoadPrivateKey(os.Getenv("OPERATOR_KEY"))
body := map[string]interface{}{
"subject_sovereign_id": "BETA-NA",
"subject_public_keys": []string{"<base64-ed25519-pubkey>"},
"scope": map[string]interface{}{"allowed_roles": []string{"role:client"}},
"validity_hours": 24,
}
headers, err := genesismesh.BuildAdminHeaders(genesismesh.AdminRequest{
Method: "POST", Path: "/admin/recognition-treaties",
Audience: "<NA public key>", // network_authority.public_key from the NA's /sovereign.json
Body: body,
}, "operator-local", priv)
b, _ := json.Marshal(body)
req, _ := http.NewRequest("POST", baseURL+"/admin/recognition-treaties", bytes.NewReader(b))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Admin-Key-Id", headers.KeyID)
req.Header.Set("X-Admin-Signature", headers.Signature)
req.Header.Set("X-Admin-Timestamp", headers.Timestamp)
req.Header.Set("X-Admin-Nonce", headers.Nonce)
Error handling
import "errors"
_, err := client.Agreement.Offer(ctx, genesismesh.CapabilityOffer{})
switch {
case err == nil:
// success
default:
var unauthorized *genesismesh.UnauthorizedError
var rateLimit *genesismesh.RateLimitError
var validation *genesismesh.ValidationError
var network *genesismesh.NetworkError
switch {
case errors.As(err, &unauthorized):
// bad signing key or stale timestamp
case errors.As(err, &rateLimit):
// back off and retry
case errors.As(err, &validation):
// inspect err.Code and err.Message
case errors.As(err, &network):
// connection refused or timeout — inspect err.Cause
}
}
Admin authentication
Admin routes are authenticated with four HTTP headers built from an Ed25519 operator key:
| Header | Description |
|---|---|
X-Admin-Key-Id |
Key identifier registered with the NA |
X-Admin-Signature |
Ed25519 over the canonical admin payload: {v: 2, method, path, query, audience, body, key_id, timestamp, nonce} |
X-Admin-Timestamp |
ISO 8601 UTC timestamp (must be within NA's nonce window) |
X-Admin-Nonce |
UUID v4 replay-protection token (single use) |
Signature version 2 (1.0.2) binds each signature to the HTTP method, the request
path, the query parameters and the target NA's public key (Audience). The
client reads it (network_authority.public_key) once from the NA's public
/sovereign.json, or
uses ClientOptions.Audience. AdminSigningPayload returns the signed bytes.
The SDK handles all of this automatically when SigningKey is provided.
Build and test
go build ./...
go test -race ./...
go vet ./...
License
MIT
Directories
¶
| Path | Synopsis |
|---|---|
|
Package genesismesh provides a typed client for the Genesis Mesh Network Authority HTTP API.
|
Package genesismesh provides a typed client for the Genesis Mesh Network Authority HTTP API. |