Initial commit: Elydora Open Source — self-hosted audit platform for AI agents
Full self-hosted port of the Elydora tamper-evident audit protocol: - Hono API server with PostgreSQL, Redis, MinIO adapters - Ed25519 signed operations, chain hashing, Merkle epoch rollups - PBKDF2 password hashing, HMAC-SHA256 JWT, 5-role RBAC - Next.js management console - Node.js, Python, and Go SDKs - Docker Compose for local deployment - Helm chart for Kubernetes - Comprehensive security hardening and audit fixes applied Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
15547a8c35
commit
e390e68594
207 files changed
+32790
-63
No files matched your search
@@ -0,0 +1,95 @@
|
||||
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.
|
||||
func (c *Client) CreateOperation(params *CreateOperationParams) (*EOR, error) {
|
||||
if params == nil {
|
||||
return nil, fmt.Errorf("elydora: params must not be nil")
|
||||
}
|
||||
|
||||
operationID, err := generateUUIDv7()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("elydora: generate operation id: %w", err)
|
||||
}
|
||||
|
||||
nonce, err := generateNonce()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("elydora: generate nonce: %w", err)
|
||||
}
|
||||
|
||||
issuedAt := nowUnixMs()
|
||||
|
||||
payloadHash, err := computePayloadHash(params.Payload)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("elydora: compute payload hash: %w", err)
|
||||
}
|
||||
|
||||
prevChainHash := params.PrevChainHash
|
||||
if prevChainHash == "" {
|
||||
prevChainHash = GenesisChainHash
|
||||
}
|
||||
|
||||
kid := params.KID
|
||||
if kid == "" && c.agentID != "" {
|
||||
kid = c.agentID + "-key-1"
|
||||
}
|
||||
|
||||
eor := &EOR{
|
||||
OpVersion: "1.0",
|
||||
OperationID: operationID,
|
||||
OrgID: c.orgID,
|
||||
AgentID: c.agentID,
|
||||
IssuedAt: issuedAt,
|
||||
TTLMs: int64(c.ttlMs),
|
||||
Nonce: nonce,
|
||||
OperationType: params.OperationType,
|
||||
Subject: params.Subject,
|
||||
Action: params.Action,
|
||||
Payload: params.Payload,
|
||||
PayloadHash: payloadHash,
|
||||
PrevChainHash: prevChainHash,
|
||||
AgentPubkeyKID: kid,
|
||||
}
|
||||
|
||||
signature, err := signEOR(eor, c.privateKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("elydora: sign eor: %w", err)
|
||||
}
|
||||
eor.Signature = signature
|
||||
|
||||
return eor, nil
|
||||
}
|
||||
|
||||
// SubmitOperation submits a signed EOR to the Elydora API.
|
||||
func (c *Client) SubmitOperation(eor *EOR) (*SubmitOperationResponse, error) {
|
||||
var result SubmitOperationResponse
|
||||
if err := c.doPost("/v1/operations", eor, &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// GetOperation retrieves an operation by ID.
|
||||
func (c *Client) GetOperation(operationID string) (*GetOperationResponse, error) {
|
||||
var result GetOperationResponse
|
||||
if err := c.doGet(fmt.Sprintf("/v1/operations/%s", operationID), &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// VerifyOperation verifies the integrity of an operation.
|
||||
func (c *Client) VerifyOperation(operationID string) (*VerifyOperationResponse, error) {
|
||||
var result VerifyOperationResponse
|
||||
if err := c.doPost(fmt.Sprintf("/v1/operations/%s/verify", operationID), nil, &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
Reference in new issue
Block a user