From 0fdedb7247f6d7f63c81d6e9588d0555f7fd6c19 Mon Sep 17 00:00:00 2001 From: ZacharyZhang Date: Sat, 28 Feb 2026 21:23:20 -0500 Subject: [PATCH] Update module path to github.com/Elydora-Infrastructure/Elydora-Go-SDK - Update go.mod module path - Update all import references - Update README install and import examples Co-Authored-By: Claude Opus 4.6 --- .gitignore | 7 +++++++ README.md | 6 +++--- agents.go | 8 ++++---- audit.go | 36 +----------------------------------- auth.go | 6 +++--- client.go | 8 ++++---- cmd/elydora/main.go | 2 +- crypto.go | 38 -------------------------------------- epochs.go | 4 ++-- exports.go | 6 +++--- go.mod | 2 +- jwks.go | 2 +- operations.go | 12 ++++++++---- 13 files changed, 38 insertions(+), 99 deletions(-) diff --git a/.gitignore b/.gitignore index 8224eea..4c91543 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,10 @@ go.work.sum # OS .DS_Store Thumbs.db + +# Environment and secrets +.env +.env.* +.env.local +*.pem +*.key diff --git a/README.md b/README.md index b188820..a86cd28 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Official Go SDK for the [Elydora](https://elydora.com) tamper-evident audit plat ## Installation ```bash -go get github.com/elydora/sdk-go +go get github.com/Elydora-Infrastructure/Elydora-Go-SDK ``` Requires Go 1.21+. Zero third-party dependencies (stdlib only). @@ -19,7 +19,7 @@ import ( "fmt" "log" - elydora "github.com/elydora/sdk-go" + elydora "github.com/Elydora-Infrastructure/Elydora-Go-SDK" ) func main() { @@ -64,7 +64,7 @@ func main() { The SDK includes a CLI for installing audit hooks into AI coding agents. ```bash -go install github.com/elydora/sdk-go/cmd/elydora@latest +go install github.com/Elydora-Infrastructure/Elydora-Go-SDK/cmd/elydora@latest elydora install \ --agent claudecode \ diff --git a/agents.go b/agents.go index bf9a623..4345b29 100644 --- a/agents.go +++ b/agents.go @@ -5,7 +5,7 @@ import "fmt" // RegisterAgent registers a new AI agent within the organization. func (c *Client) RegisterAgent(req *RegisterAgentRequest) (*RegisterAgentResponse, error) { var result RegisterAgentResponse - if err := c.doPost("/agents", req, &result); err != nil { + if err := c.doPost("/v1/agents/register", req, &result); err != nil { return nil, err } return &result, nil @@ -14,7 +14,7 @@ func (c *Client) RegisterAgent(req *RegisterAgentRequest) (*RegisterAgentRespons // GetAgent retrieves an agent by ID. func (c *Client) GetAgent(agentID string) (*GetAgentResponse, error) { var result GetAgentResponse - if err := c.doGet(fmt.Sprintf("/agents/%s", agentID), &result); err != nil { + if err := c.doGet(fmt.Sprintf("/v1/agents/%s", agentID), &result); err != nil { return nil, err } return &result, nil @@ -22,14 +22,14 @@ func (c *Client) GetAgent(agentID string) (*GetAgentResponse, error) { // FreezeAgent freezes an agent, preventing it from submitting operations. func (c *Client) FreezeAgent(agentID, reason string) error { - return c.doPost(fmt.Sprintf("/agents/%s/freeze", agentID), &FreezeAgentRequest{ + return c.doPost(fmt.Sprintf("/v1/agents/%s/freeze", agentID), &FreezeAgentRequest{ Reason: reason, }, nil) } // RevokeKey revokes a specific key for an agent. func (c *Client) RevokeKey(agentID, kid, reason string) error { - return c.doPost(fmt.Sprintf("/agents/%s/revoke-key", agentID), &RevokeAgentRequest{ + return c.doPost(fmt.Sprintf("/v1/agents/%s/revoke", agentID), &RevokeAgentRequest{ KID: kid, Reason: reason, }, nil) diff --git a/audit.go b/audit.go index 3ec25e0..f5b7ddc 100644 --- a/audit.go +++ b/audit.go @@ -1,43 +1,9 @@ package elydora -import ( - "fmt" - "net/url" - "strconv" -) - // QueryAudit queries the audit log with the given parameters. func (c *Client) QueryAudit(params *AuditQueryRequest) (*AuditQueryResponse, error) { - q := url.Values{} - if params.OrgID != "" { - q.Set("org_id", params.OrgID) - } - if params.AgentID != "" { - q.Set("agent_id", params.AgentID) - } - if params.OperationType != "" { - q.Set("operation_type", params.OperationType) - } - if params.StartTime != nil { - q.Set("start_time", strconv.FormatInt(*params.StartTime, 10)) - } - if params.EndTime != nil { - q.Set("end_time", strconv.FormatInt(*params.EndTime, 10)) - } - if params.Cursor != "" { - q.Set("cursor", params.Cursor) - } - if params.Limit != nil { - q.Set("limit", strconv.Itoa(*params.Limit)) - } - - path := "/audit" - if encoded := q.Encode(); encoded != "" { - path = fmt.Sprintf("/audit?%s", encoded) - } - var result AuditQueryResponse - if err := c.doGet(path, &result); err != nil { + if err := c.doPost("/v1/audit/query", params, &result); err != nil { return nil, err } return &result, nil diff --git a/auth.go b/auth.go index 3e73800..137e427 100644 --- a/auth.go +++ b/auth.go @@ -43,7 +43,7 @@ func Register(baseURL, email, password string, opts ...RegisterOption) (*AuthReg } var result AuthRegisterResponse - if err := authPost(baseURL, "/auth/register", req, &result); err != nil { + if err := authPost(baseURL, "/v1/auth/register", req, &result); err != nil { return nil, err } return &result, nil @@ -62,7 +62,7 @@ func Login(baseURL, email, password string) (*AuthLoginResponse, error) { } var result AuthLoginResponse - if err := authPost(baseURL, "/auth/login", req, &result); err != nil { + if err := authPost(baseURL, "/v1/auth/login", req, &result); err != nil { return nil, err } return &result, nil @@ -91,7 +91,7 @@ func authPost(baseURL, path string, body interface{}, result interface{}) error } defer resp.Body.Close() - respBody, err := io.ReadAll(resp.Body) + respBody, err := io.ReadAll(io.LimitReader(resp.Body, 10<<20)) if err != nil { return fmt.Errorf("elydora: read response body: %w", err) } diff --git a/client.go b/client.go index 625e093..e51cb15 100644 --- a/client.go +++ b/client.go @@ -116,7 +116,7 @@ func (c *Client) doRequest(method, path string, body interface{}, result interfa continue } - respBody, err := io.ReadAll(resp.Body) + respBody, err := io.ReadAll(io.LimitReader(resp.Body, 10<<20)) resp.Body.Close() if err != nil { lastErr = fmt.Errorf("elydora: read response body: %w", err) @@ -172,7 +172,7 @@ func (c *Client) doPost(path string, body interface{}, result interface{}) error return c.doRequest(http.MethodPost, path, body, result) } -// doPut performs a PUT request. -func (c *Client) doPut(path string, body interface{}, result interface{}) error { - return c.doRequest(http.MethodPut, path, body, result) +// SetToken sets the JWT token used for authenticated API requests. +func (c *Client) SetToken(token string) { + c.token = token } diff --git a/cmd/elydora/main.go b/cmd/elydora/main.go index 84a3721..1d34afc 100644 --- a/cmd/elydora/main.go +++ b/cmd/elydora/main.go @@ -8,7 +8,7 @@ import ( "sort" "strings" - "github.com/elydora/sdk-go/cmd/elydora/plugins" + "github.com/Elydora-Infrastructure/Elydora-Go-SDK/cmd/elydora/plugins" ) const version = "1.0.0" diff --git a/crypto.go b/crypto.go index 54f3623..f7ae7aa 100644 --- a/crypto.go +++ b/crypto.go @@ -32,13 +32,6 @@ func computePayloadHash(payload interface{}) (string, error) { return sha256BytesBase64url([]byte(canonical)), nil } -// computeChainHash computes the chain hash for an operation. -// Formula: SHA-256(prev_chain_hash + "|" + payload_hash + "|" + operation_id + "|" + issued_at) -func computeChainHash(prevChainHash, payloadHash, operationID string, issuedAt int64) string { - input := prevChainHash + "|" + payloadHash + "|" + operationID + "|" + fmt.Sprintf("%d", issuedAt) - return sha256Base64url(input) -} - // signEd25519 signs data with an Ed25519 private key seed (base64url-encoded 32 bytes). // Returns the signature as base64url. func signEd25519(privateKeyBase64url string, data []byte) (string, error) { @@ -54,37 +47,6 @@ func signEd25519(privateKeyBase64url string, data []byte) (string, error) { return base64urlEncode(sig), nil } -// verifyEd25519 verifies an Ed25519 signature. -func verifyEd25519(publicKeyBase64url string, signatureBase64url string, data []byte) (bool, error) { - pubBytes, err := base64urlDecode(publicKeyBase64url) - if err != nil { - return false, fmt.Errorf("decode public key: %w", err) - } - if len(pubBytes) != ed25519.PublicKeySize { - return false, fmt.Errorf("public key must be %d bytes, got %d", ed25519.PublicKeySize, len(pubBytes)) - } - sigBytes, err := base64urlDecode(signatureBase64url) - if err != nil { - return false, fmt.Errorf("decode signature: %w", err) - } - return ed25519.Verify(ed25519.PublicKey(pubBytes), data, sigBytes), nil -} - -// derivePublicKey derives the Ed25519 public key from a private key seed (base64url). -// Returns the public key as base64url. -func derivePublicKey(privateKeyBase64url string) (string, error) { - seed, err := base64urlDecode(privateKeyBase64url) - if err != nil { - return "", fmt.Errorf("decode private key: %w", err) - } - if len(seed) != ed25519.SeedSize { - return "", fmt.Errorf("private key seed must be %d bytes, got %d", ed25519.SeedSize, len(seed)) - } - key := ed25519.NewKeyFromSeed(seed) - pub := key.Public().(ed25519.PublicKey) - return base64urlEncode(pub), nil -} - // --------------------------------------------------------------------------- // JCS Canonicalization (RFC 8785) // --------------------------------------------------------------------------- diff --git a/epochs.go b/epochs.go index bf5f549..d49ec26 100644 --- a/epochs.go +++ b/epochs.go @@ -5,7 +5,7 @@ import "fmt" // ListEpochs lists all epochs for the organization. func (c *Client) ListEpochs() (*ListEpochsResponse, error) { var result ListEpochsResponse - if err := c.doGet("/epochs", &result); err != nil { + if err := c.doGet("/v1/epochs", &result); err != nil { return nil, err } return &result, nil @@ -14,7 +14,7 @@ func (c *Client) ListEpochs() (*ListEpochsResponse, error) { // GetEpoch retrieves a specific epoch by ID. func (c *Client) GetEpoch(epochID string) (*GetEpochResponse, error) { var result GetEpochResponse - if err := c.doGet(fmt.Sprintf("/epochs/%s", epochID), &result); err != nil { + if err := c.doGet(fmt.Sprintf("/v1/epochs/%s", epochID), &result); err != nil { return nil, err } return &result, nil diff --git a/exports.go b/exports.go index ff3412a..e5f8f77 100644 --- a/exports.go +++ b/exports.go @@ -5,7 +5,7 @@ import "fmt" // CreateExport creates a new compliance export job. func (c *Client) CreateExport(params *CreateExportRequest) (*CreateExportResponse, error) { var result CreateExportResponse - if err := c.doPost("/exports", params, &result); err != nil { + if err := c.doPost("/v1/exports", params, &result); err != nil { return nil, err } return &result, nil @@ -14,7 +14,7 @@ func (c *Client) CreateExport(params *CreateExportRequest) (*CreateExportRespons // ListExports lists all exports for the organization. func (c *Client) ListExports() (*ListExportsResponse, error) { var result ListExportsResponse - if err := c.doGet("/exports", &result); err != nil { + if err := c.doGet("/v1/exports", &result); err != nil { return nil, err } return &result, nil @@ -23,7 +23,7 @@ func (c *Client) ListExports() (*ListExportsResponse, error) { // GetExport retrieves a specific export by ID. func (c *Client) GetExport(exportID string) (*GetExportResponse, error) { var result GetExportResponse - if err := c.doGet(fmt.Sprintf("/exports/%s", exportID), &result); err != nil { + if err := c.doGet(fmt.Sprintf("/v1/exports/%s", exportID), &result); err != nil { return nil, err } return &result, nil diff --git a/go.mod b/go.mod index a967b0f..d136823 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ -module github.com/elydora/sdk-go +module github.com/Elydora-Infrastructure/Elydora-Go-SDK go 1.21 diff --git a/jwks.go b/jwks.go index 0b0facd..3283467 100644 --- a/jwks.go +++ b/jwks.go @@ -3,7 +3,7 @@ package elydora // GetJWKS retrieves the JSON Web Key Set from the Elydora API. func (c *Client) GetJWKS() (*JWKSResponse, error) { var result JWKSResponse - if err := c.doGet("/.well-known/jwks.json", &result); err != nil { + if err := c.doGet("/.well-known/elydora/jwks.json", &result); err != nil { return nil, err } return &result, nil diff --git a/operations.go b/operations.go index 176f050..3620760 100644 --- a/operations.go +++ b/operations.go @@ -2,6 +2,10 @@ package elydora import "fmt" +// GenesisChainHash is the initial chain hash for an agent's first operation. +// It is the base64url encoding of 32 zero bytes, matching the backend. +const GenesisChainHash = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + // CreateOperation builds a signed EOR from the given parameters. // It generates a UUIDv7 operation ID, a nonce, computes the payload hash and chain hash, // and signs the entire record with the client's private key. @@ -29,7 +33,7 @@ func (c *Client) CreateOperation(params *CreateOperationParams) (*EOR, error) { prevChainHash := params.PrevChainHash if prevChainHash == "" { - prevChainHash = "GENESIS" + prevChainHash = GenesisChainHash } kid := params.KID @@ -66,7 +70,7 @@ func (c *Client) CreateOperation(params *CreateOperationParams) (*EOR, error) { // SubmitOperation submits a signed EOR to the Elydora API. func (c *Client) SubmitOperation(eor *EOR) (*SubmitOperationResponse, error) { var result SubmitOperationResponse - if err := c.doPost("/operations", eor, &result); err != nil { + if err := c.doPost("/v1/operations", eor, &result); err != nil { return nil, err } return &result, nil @@ -75,7 +79,7 @@ func (c *Client) SubmitOperation(eor *EOR) (*SubmitOperationResponse, error) { // GetOperation retrieves an operation by ID. func (c *Client) GetOperation(operationID string) (*GetOperationResponse, error) { var result GetOperationResponse - if err := c.doGet(fmt.Sprintf("/operations/%s", operationID), &result); err != nil { + if err := c.doGet(fmt.Sprintf("/v1/operations/%s", operationID), &result); err != nil { return nil, err } return &result, nil @@ -84,7 +88,7 @@ func (c *Client) GetOperation(operationID string) (*GetOperationResponse, error) // VerifyOperation verifies the integrity of an operation. func (c *Client) VerifyOperation(operationID string) (*VerifyOperationResponse, error) { var result VerifyOperationResponse - if err := c.doGet(fmt.Sprintf("/operations/%s/verify", operationID), &result); err != nil { + if err := c.doPost(fmt.Sprintf("/v1/operations/%s/verify", operationID), nil, &result); err != nil { return nil, err } return &result, nil