14 KiB
Elydora Go SDK
Official Go SDK for the Elydora tamper-evident audit platform. Build cryptographically verifiable audit trails for AI agent operations.
Installation
go get github.com/Elydora-Infrastructure/Elydora-Go-SDK
Requires Go 1.21+. The CLI uses focused TOML and JSONC parsers to preserve user-owned agent configuration.
Quick Start
package main
import (
"fmt"
"log"
elydora "github.com/Elydora-Infrastructure/Elydora-Go-SDK"
)
func main() {
// Authenticate
auth, err := elydora.Login("https://api.elydora.com", "user@example.com", "password")
if err != nil {
log.Fatal(err)
}
// Create client
client, err := elydora.NewClient(&elydora.Config{
OrgID: auth.User.OrgID,
AgentID: "my-agent-id",
PrivateKey: "<base64url-encoded-ed25519-seed>",
Token: auth.Token,
})
if err != nil {
log.Fatal(err)
}
// Create and submit an operation
eor, err := client.CreateOperation(&elydora.CreateOperationParams{
OperationType: "data.access",
Subject: map[string]interface{}{"user_id": "u-123"},
Action: map[string]interface{}{"type": "read"},
Payload: map[string]interface{}{"record_id": "rec-456"},
})
if err != nil {
log.Fatal(err)
}
resp, err := client.SubmitOperation(eor)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Receipt: %s\n", resp.Receipt.ReceiptID)
}
CLI
The SDK includes a CLI for installing audit hooks into AI coding agents.
Agent IDs map to one physical directory directly under ~/.elydora; portable filename rules and physical directory/config checks apply before writes or recursive removal. Ambiguous uninstall discovery requires an explicit agent ID.
go install github.com/Elydora-Infrastructure/Elydora-Go-SDK/cmd/elydora@latest
elydora install \
--agent claudecode \
--org-id org-123 \
--agent-id agent-456 \
--private-key-file /secure/path/private.key \
--token-file /secure/path/api.token \
--kid agent-456-key-v1
Credential options may be omitted in an interactive terminal; the CLI then reads the private key and optional API token without terminal echo. Credential files must contain one UTF-8 line of at most 64 KiB. Unix credential files require owner-only permissions such as chmod 600. Provider settings, guard.js, config.json, private.key, and hook.js commit as one rollback-capable transaction, and the generated scripts validate protected files at execution time.
Claude Code installation writes exact matchless PreToolUse, PostToolUse, and PostToolUseFailure exec-form hooks to $CLAUDE_CONFIG_DIR/settings.json (~/.claude/settings.json by default). Elydora preserves unrelated user settings, keeps project, local, managed, plugin, skill, and agent sources unchanged, forwards native snake_case payloads, and uses exit code 2 for frozen or revoked agents. Installation validates the complete official hook schema and commits settings with all four runtime artifacts in one rollback-capable transaction. Run /hooks and claude doctor after installation to inspect the effective hook sources.
Codex installation writes exact PreToolUse and PostToolUse command groups to $CODEX_HOME/hooks.json (~/.codex/hooks.json by default) and preserves the complete native event payload. A configured CODEX_HOME follows Codex's existing-directory canonicalization rule. User TOML, project, plugin, and managed sources remain unchanged and continue loading additively. The hook file, generated runtimes, runtime config, and private key commit as one rollback-capable update. Run /hooks after installation and approve both Elydora definition hashes.
Cursor installation writes native global preToolUse, postToolUse, and postToolUseFailure handlers to ~/.cursor/hooks.json. Elydora preserves unrelated user hooks, leaves project and enterprise sources unchanged, emits valid JSON hook responses, fails closed when enforcement or audit execution cannot complete, and commits its 10-second hook contract with all managed runtime files as one rollback-capable transaction.
Gemini CLI installation writes exact matchless BeforeTool and AfterTool command handlers to $GEMINI_CLI_HOME/.gemini/settings.json (~/.gemini/settings.json by default). Elydora preserves JSONC comments, line endings, unrelated user hooks, and additive workspace, system, system-override, and extension sources. The user settings document and all four generated runtime artifacts commit in one rollback-capable transaction. Generated hooks retain Gemini's native snake_case payload, emit {} on successful or fail-open execution, surface runtime failures through stderr and error.log, and use exit code 2 for frozen or revoked agents. Installation honors hooksConfig controls and uses encoded PowerShell commands on Windows. Run /hooks list after installation to inspect the effective hook inventory.
GitHub Copilot CLI installation writes native user hooks to $COPILOT_HOME/hooks/elydora-audit.json with ~/.copilot/hooks/elydora-audit.json as the default. Elydora preserves user hooks, migrates exact Elydora-owned entries from project .github/hooks/hooks.json, quotes the resolved Node.js runtime for each shell, and propagates the freeze guard's exit code. Installation requires disableAllHooks to be false.
Cline 3.0.46 installation commits guard.js, config.json, private.key, hook.js, PreToolUse.mjs, and PostToolUse.mjs through one rollback-capable transaction. The native hooks live in $CLINE_DIR/hooks with ~/.cline/hooks as the default; the Documents and workspace roots remain read-only. The wrappers forward Cline's complete stdin payload byte-for-byte, use the active Node.js executable for generated runtimes, and emit pure JSON cancellation control for frozen or revoked agents. Status requires physical files, exact generated sources, strict runtime identity, and a canonical private key.
Kiro CLI installation covers both runtime contracts. Kiro CLI v2 uses the generated custom agent through kiro-cli --agent elydora-audit. Kiro CLI v3 loads the global standalone hooks when started with kiro-cli --v3.
Kimi installation follows home-directory evidence. Kimi Code uses $KIMI_CODE_HOME/config.toml with ~/.kimi-code/config.toml as the default, and legacy kimi-cli uses ~/.kimi/config.toml. Elydora installs exact PreToolUse, PostToolUse, and PostToolUseFailure hooks, preserves native snake_case payloads, and commits all selected TOML documents with the four runtime artifacts in one rollback-capable transaction. Windows commands use encoded PowerShell so paths containing spaces, apostrophes, percent signs, and environment-like text remain literal.
Grok Build installation writes native global PreToolUse, PostToolUse, and PostToolUseFailure hooks to $GROK_HOME/hooks/elydora-audit.json (default ~/.grok/hooks/elydora-audit.json). The hook file, generated runtimes, runtime config, and private key commit as one rollback-capable transaction. Managed commands preserve Grok's native camelCase JSON, return {"decision":"deny","reason":"..."} with exit code 2 for frozen or revoked agents, and use encoded PowerShell on Windows. Project hooks follow Grok's /hooks-trust workflow; Elydora leaves project, plugin, hooks-paths, Claude Code, and Cursor compatibility sources unchanged. Run grok inspect --json to inspect the effective hook inventory.
Auggie installation commits ~/.augment/settings.json, both platform wrappers, generated runtimes, runtime config, and private key as one rollback-capable transaction. The managed PreToolUse guard propagates exit code 2; PostToolUse preserves Auggie's complete native hook payload. System, workspace, local workspace, and alternate --augment-cache-dir settings remain unchanged. Run auggie tools list to validate the effective user configuration.
Factory Droid installation selects PreToolUse and PostToolUse independently across ~/.factory/hooks.json, the legacy ~/.factory/hooks/hooks.json, and ~/.factory/settings.json. Elydora preserves JSONC comments and formatting, commits runtime and hook changes as one transaction, and reports disabled hooks as unhealthy. Run /hooks in Droid after installation to review the effective hooks.
Qwen Code installation writes native user hooks to $QWEN_HOME/settings.json with ~/.qwen/settings.json as the default. Elydora follows Qwen's .env discovery order, preserves JSON-with-comments source formatting, keeps workspace settings read-only, and commits runtime and settings changes as one transaction. Run /hooks in Qwen Code after installation to review the effective hooks.
Commands
| Command | Description |
|---|---|
elydora install |
Install Elydora audit hook for a coding agent |
elydora uninstall |
Remove Elydora audit hook for a coding agent |
elydora status |
Show installation status for all agents |
elydora agents |
List supported coding agents |
Supported Agents
| Agent | Key |
|---|---|
| Augment Code CLI | augment |
| Claude Code | claudecode |
| OpenAI Codex | codex |
| Cline | cline |
| GitHub Copilot CLI | copilot |
| Cursor | cursor |
| Factory Droid | droid |
| Gemini CLI | gemini |
| Grok Build | grok |
| Kiro CLI | kirocli |
| Kiro IDE | kiroide |
| Kimi Code | kimi |
| Letta Code | letta |
| OpenCode | opencode |
| Qwen Code | qwen |
API Reference
Configuration
client, err := elydora.NewClient(&elydora.Config{
OrgID: "org-123", // Organization ID
AgentID: "agent-456", // Agent ID
PrivateKey: "<seed>", // Base64url-encoded Ed25519 seed
BaseURL: "https://...", // API base URL (default: https://api.elydora.com)
TTLMs: 30000, // Operation TTL in ms (default: 30000)
MaxRetries: 3, // Max retries on transient failures (default: 3)
Token: "<token>", // API token for authenticated requests
})
Client Methods
// Update the API token at runtime
client.SetToken("new-api-token")
Authentication
// Register a new user and organization
reg, err := elydora.Register(baseURL, email, password,
elydora.WithDisplayName("Alice"),
elydora.WithOrgName("Acme Corp"),
)
// Login and receive a session token
auth, err := elydora.Login(baseURL, email, password)
// Get current authenticated user profile
me, err := client.GetMe()
// Issue a new API token (with optional TTL)
tokenResp, err := client.IssueApiToken(&elydora.IssueApiTokenRequest{
TTLSeconds: &ttlSeconds,
})
Operations
// Create a signed EOR locally (no network call)
eor, err := client.CreateOperation(&elydora.CreateOperationParams{
OperationType: "inference",
Subject: map[string]interface{}{"model": "gpt-4"},
Action: map[string]interface{}{"type": "completion"},
Payload: map[string]interface{}{"prompt": "Hello"},
KID: "agent-456-key-v1",
})
// Submit to API
resp, err := client.SubmitOperation(eor)
// Retrieve an operation
op, err := client.GetOperation(operationID)
// Verify integrity
result, err := client.VerifyOperation(operationID)
Agent Management
// Register a new agent
agent, err := client.RegisterAgent(&elydora.RegisterAgentRequest{
AgentID: "my-agent",
DisplayName: "My Agent",
ResponsibleEntity: "team@example.com",
IntegrationType: elydora.IntegrationTypeSDK,
Keys: []elydora.RegisterAgentKeyInput{
{KID: "key-v1", PublicKey: "<base64url>", Algorithm: "ed25519"},
},
})
// Get agent details
details, err := client.GetAgent(agentID)
// Freeze an agent
err := client.FreezeAgent(agentID, "security review")
// Revoke a key
err := client.RevokeKey(agentID, kid, "key rotation")
// List all agents in the organization
agents, err := client.ListAgents()
// Unfreeze a previously frozen agent
err := client.UnfreezeAgent(agentID, "review complete")
// Delete an agent permanently
deleted, err := client.DeleteAgent(agentID)
Audit
results, err := client.QueryAudit(&elydora.AuditQueryRequest{
AgentID: "agent-123",
OperationType: "inference",
StartTime: &startTime,
EndTime: &endTime,
Limit: &limit,
})
Epochs
epochs, err := client.ListEpochs()
epoch, err := client.GetEpoch(epochID)
Exports
export, err := client.CreateExport(&elydora.CreateExportRequest{
StartTime: startTime,
EndTime: endTime,
Format: "json",
})
exports, err := client.ListExports()
detail, err := client.GetExport(exportID)
// Download export file data
data, err := client.DownloadExport(exportID)
JWKS
jwks, err := client.GetJWKS()
Health
// Check API health (no authentication required, does not need a client)
health, err := elydora.Health("https://api.elydora.com")
// health.Status, health.Version, health.ProtocolVersion, health.Timestamp
Constants
// Genesis chain hash — initial prev_chain_hash for an agent's first operation
elydora.GenesisChainHash // "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
Status Enums
| Type | Constants |
|---|---|
AgentStatus |
AgentStatusActive, AgentStatusFrozen, AgentStatusRevoked |
KeyStatus |
KeyStatusActive, KeyStatusRetired, KeyStatusRevoked |
ExportStatus |
ExportStatusQueued, ExportStatusRunning, ExportStatusDone, ExportStatusFailed |
ExportFormat |
ExportFormatJSON, ExportFormatPDF |
RbacRole |
RbacRoleOrgOwner, RbacRoleSecurityAdmin, RbacRoleComplianceAuditor, RbacRoleReadonlyInvestigator, RbacRoleIntegrationEngineer |
ErrorCode |
ErrorCodeInvalidSignature, ErrorCodeUnknownAgent, ErrorCodeKeyRevoked, ErrorCodeAgentFrozen, ErrorCodeTTLExpired, ErrorCodeReplayDetected, ErrorCodePrevHashMismatch, ErrorCodePayloadTooLarge, ErrorCodeRateLimited, ErrorCodeInternalError, ErrorCodeUnauthorized, ErrorCodeForbidden, ErrorCodeNotFound, ErrorCodeValidationError |
Error Handling
import "errors"
var apiErr *elydora.ElydoraError
if errors.As(err, &apiErr) {
fmt.Println(apiErr.Code) // e.g. "INVALID_SIGNATURE"
fmt.Println(apiErr.Message) // Human-readable message
fmt.Println(apiErr.StatusCode) // HTTP status code
fmt.Println(apiErr.RequestID) // Request ID for support
}
License
MIT