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,19 @@
|
||||
import type { ErrorCode } from '../types/enums.js';
|
||||
|
||||
/** Map of all Elydora error codes to default human-readable messages */
|
||||
export const ERROR_CODES: Readonly<Record<ErrorCode, string>> = {
|
||||
INVALID_SIGNATURE: 'The operation signature is invalid.',
|
||||
UNKNOWN_AGENT: 'The specified agent does not exist.',
|
||||
KEY_REVOKED: 'The signing key has been revoked.',
|
||||
AGENT_FROZEN: 'The agent is frozen and cannot submit operations.',
|
||||
TTL_EXPIRED: 'The operation TTL has expired.',
|
||||
REPLAY_DETECTED: 'A duplicate nonce was detected (replay attack).',
|
||||
PREV_HASH_MISMATCH: 'The previous chain hash does not match.',
|
||||
PAYLOAD_TOO_LARGE: 'The operation payload exceeds the maximum allowed size.',
|
||||
RATE_LIMITED: 'Too many requests. Please retry later.',
|
||||
INTERNAL_ERROR: 'An internal server error occurred.',
|
||||
UNAUTHORIZED: 'Authentication is required.',
|
||||
FORBIDDEN: 'You do not have permission to perform this action.',
|
||||
NOT_FOUND: 'The requested resource was not found.',
|
||||
VALIDATION_ERROR: 'The request failed validation.',
|
||||
} as const;
|
||||
@@ -0,0 +1,13 @@
|
||||
export { ERROR_CODES } from './errors.js';
|
||||
export {
|
||||
MAX_PAYLOAD_SIZE,
|
||||
MAX_TTL_MS,
|
||||
MIN_TTL_MS,
|
||||
MAX_NONCE_LENGTH,
|
||||
STARTER_MAX_AGENTS,
|
||||
DEFAULT_RETENTION_DAYS,
|
||||
DEFAULT_EPOCH_INTERVAL_MS,
|
||||
MAX_QUERY_LIMIT,
|
||||
DEFAULT_QUERY_LIMIT,
|
||||
DEFAULT_JWT_TTL_SECONDS,
|
||||
} from './limits.js';
|
||||
@@ -0,0 +1,29 @@
|
||||
/** Maximum payload size in bytes (256 KB) */
|
||||
export const MAX_PAYLOAD_SIZE = 256 * 1024;
|
||||
|
||||
/** Maximum TTL in milliseconds (5 minutes) */
|
||||
export const MAX_TTL_MS = 300_000;
|
||||
|
||||
/** Minimum TTL in milliseconds (1 second) */
|
||||
export const MIN_TTL_MS = 1_000;
|
||||
|
||||
/** Maximum nonce length in characters */
|
||||
export const MAX_NONCE_LENGTH = 64;
|
||||
|
||||
/** Maximum number of agents on the Starter plan */
|
||||
export const STARTER_MAX_AGENTS = 10;
|
||||
|
||||
/** Default data retention period in days */
|
||||
export const DEFAULT_RETENTION_DAYS = 30;
|
||||
|
||||
/** Default epoch interval in milliseconds (5 minutes) */
|
||||
export const DEFAULT_EPOCH_INTERVAL_MS = 300_000;
|
||||
|
||||
/** Maximum number of results per query */
|
||||
export const MAX_QUERY_LIMIT = 1000;
|
||||
|
||||
/** Default number of results per query */
|
||||
export const DEFAULT_QUERY_LIMIT = 100;
|
||||
|
||||
/** Default JWT token lifetime in seconds (24 hours) */
|
||||
export const DEFAULT_JWT_TTL_SECONDS = 86400;
|
||||
@@ -0,0 +1,66 @@
|
||||
export type {
|
||||
AgentStatus,
|
||||
KeyStatus,
|
||||
ExportStatus,
|
||||
AdminAction,
|
||||
RbacRole,
|
||||
ErrorCode,
|
||||
EOR,
|
||||
ECH,
|
||||
EAR,
|
||||
EER,
|
||||
Agent,
|
||||
AgentKey,
|
||||
Operation,
|
||||
Receipt,
|
||||
Epoch,
|
||||
AdminEvent,
|
||||
Export,
|
||||
Organization,
|
||||
User,
|
||||
RegisterAgentRequest,
|
||||
RegisterAgentResponse,
|
||||
GetAgentResponse,
|
||||
ListAgentsResponse,
|
||||
FreezeAgentRequest,
|
||||
UnfreezeAgentRequest,
|
||||
RevokeAgentRequest,
|
||||
UpdateAgentRequest,
|
||||
SubmitOperationRequest,
|
||||
SubmitOperationResponse,
|
||||
GetOperationResponse,
|
||||
VerifyOperationResponse,
|
||||
AuditQueryRequest,
|
||||
AuditQueryResponse,
|
||||
GetEpochResponse,
|
||||
ListEpochsResponse,
|
||||
CreateExportRequest,
|
||||
CreateExportResponse,
|
||||
GetExportResponse,
|
||||
ListExportsResponse,
|
||||
AuthRegisterRequest,
|
||||
AuthRegisterResponse,
|
||||
AuthLoginRequest,
|
||||
AuthLoginResponse,
|
||||
AuthMeResponse,
|
||||
AuthRefreshResponse,
|
||||
IssueTokenRequest,
|
||||
IssueTokenResponse,
|
||||
JWK,
|
||||
JWKSResponse,
|
||||
ErrorResponse,
|
||||
} from './types/index.js';
|
||||
|
||||
export {
|
||||
ERROR_CODES,
|
||||
MAX_PAYLOAD_SIZE,
|
||||
MAX_TTL_MS,
|
||||
MIN_TTL_MS,
|
||||
MAX_NONCE_LENGTH,
|
||||
STARTER_MAX_AGENTS,
|
||||
DEFAULT_RETENTION_DAYS,
|
||||
DEFAULT_EPOCH_INTERVAL_MS,
|
||||
MAX_QUERY_LIMIT,
|
||||
DEFAULT_QUERY_LIMIT,
|
||||
DEFAULT_JWT_TTL_SECONDS,
|
||||
} from './constants/index.js';
|
||||
@@ -0,0 +1,213 @@
|
||||
import type { Agent, AgentKey, Epoch, Export, Operation, Organization, Receipt, User } from './entities.js';
|
||||
import type { ErrorCode } from './enums.js';
|
||||
import type { EAR, EOR } from './protocol.js';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Agent endpoints
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface RegisterAgentRequest {
|
||||
readonly agent_id: string;
|
||||
readonly display_name?: string;
|
||||
readonly responsible_entity?: string;
|
||||
readonly integration_type?: string;
|
||||
readonly keys: ReadonlyArray<{
|
||||
readonly kid: string;
|
||||
readonly public_key: string;
|
||||
readonly algorithm: 'ed25519';
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface RegisterAgentResponse {
|
||||
readonly agent: Agent;
|
||||
readonly keys: AgentKey[];
|
||||
}
|
||||
|
||||
export interface GetAgentResponse {
|
||||
readonly agent: Agent;
|
||||
readonly keys: AgentKey[];
|
||||
}
|
||||
|
||||
export interface ListAgentsResponse {
|
||||
readonly agents: Agent[];
|
||||
}
|
||||
|
||||
export interface FreezeAgentRequest {
|
||||
readonly reason: string;
|
||||
}
|
||||
|
||||
export interface UnfreezeAgentRequest {
|
||||
readonly reason: string;
|
||||
}
|
||||
|
||||
export interface RevokeAgentRequest {
|
||||
readonly kid: string;
|
||||
readonly reason: string;
|
||||
}
|
||||
|
||||
export interface UpdateAgentRequest {
|
||||
readonly integration_type: string;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Operation endpoints
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export type SubmitOperationRequest = EOR;
|
||||
|
||||
export interface SubmitOperationResponse {
|
||||
readonly receipt: EAR;
|
||||
}
|
||||
|
||||
export interface GetOperationResponse {
|
||||
readonly operation: Operation;
|
||||
readonly receipt?: Receipt;
|
||||
readonly payload?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface VerifyOperationResponse {
|
||||
readonly valid: boolean;
|
||||
readonly checks: {
|
||||
readonly signature: boolean;
|
||||
readonly chain: boolean;
|
||||
readonly receipt: boolean;
|
||||
readonly merkle?: boolean;
|
||||
};
|
||||
readonly errors?: string[];
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Audit query endpoints
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface AuditQueryRequest {
|
||||
readonly org_id?: string;
|
||||
readonly agent_id?: string;
|
||||
readonly operation_type?: string;
|
||||
readonly start_time?: number;
|
||||
readonly end_time?: number;
|
||||
readonly cursor?: string;
|
||||
readonly limit?: number;
|
||||
}
|
||||
|
||||
export interface AuditQueryResponse {
|
||||
readonly operations: Operation[];
|
||||
readonly cursor?: string;
|
||||
readonly total_count: number;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Epoch endpoints
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface GetEpochResponse {
|
||||
readonly epoch: Epoch;
|
||||
readonly anchor?: {
|
||||
readonly tsa_token?: string;
|
||||
readonly tsa_url?: string;
|
||||
readonly anchored_at?: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ListEpochsResponse {
|
||||
readonly epochs: Epoch[];
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Export endpoints
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface CreateExportRequest {
|
||||
readonly start_time: number;
|
||||
readonly end_time: number;
|
||||
readonly agent_id?: string;
|
||||
readonly operation_type?: string;
|
||||
readonly format: 'json' | 'pdf';
|
||||
}
|
||||
|
||||
export interface CreateExportResponse {
|
||||
readonly export: Export;
|
||||
}
|
||||
|
||||
export interface GetExportResponse {
|
||||
readonly export: Export;
|
||||
readonly download_url?: string;
|
||||
}
|
||||
|
||||
export interface ListExportsResponse {
|
||||
readonly exports: Export[];
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// JWKS endpoint
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface JWK {
|
||||
readonly kty: string;
|
||||
readonly crv?: string;
|
||||
readonly x?: string;
|
||||
readonly kid: string;
|
||||
readonly use: string;
|
||||
readonly alg: string;
|
||||
}
|
||||
|
||||
export interface JWKSResponse {
|
||||
readonly keys: JWK[];
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Auth endpoints
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface AuthRegisterRequest {
|
||||
readonly email: string;
|
||||
readonly password: string;
|
||||
readonly display_name?: string;
|
||||
readonly org_name?: string;
|
||||
}
|
||||
|
||||
export interface AuthRegisterResponse {
|
||||
readonly user: User;
|
||||
readonly organization: Organization;
|
||||
readonly token: string;
|
||||
}
|
||||
|
||||
export interface AuthLoginRequest {
|
||||
readonly email: string;
|
||||
readonly password: string;
|
||||
}
|
||||
|
||||
export interface AuthLoginResponse {
|
||||
readonly user: User;
|
||||
readonly token: string;
|
||||
}
|
||||
|
||||
export interface AuthMeResponse {
|
||||
readonly user: User;
|
||||
}
|
||||
|
||||
export interface AuthRefreshResponse {
|
||||
readonly token: string;
|
||||
}
|
||||
|
||||
export interface IssueTokenRequest {
|
||||
readonly ttl_seconds?: number | null; // null = never expire
|
||||
}
|
||||
|
||||
export interface IssueTokenResponse {
|
||||
readonly token: string;
|
||||
readonly expires_at: number | null; // null = never expire
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Error response
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface ErrorResponse {
|
||||
readonly error: {
|
||||
readonly code: ErrorCode;
|
||||
readonly message: string;
|
||||
readonly request_id: string;
|
||||
readonly details?: Record<string, unknown>;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
import type { AgentStatus, ExportStatus, KeyStatus, RbacRole } from './enums.js';
|
||||
|
||||
/** Registered AI agent within an organization */
|
||||
export interface Agent {
|
||||
readonly agent_id: string;
|
||||
readonly org_id: string;
|
||||
readonly display_name: string;
|
||||
readonly responsible_entity: string;
|
||||
readonly integration_type: string;
|
||||
readonly status: AgentStatus;
|
||||
readonly created_at: number;
|
||||
readonly updated_at: number;
|
||||
}
|
||||
|
||||
/** Public key associated with an agent for signing operations */
|
||||
export interface AgentKey {
|
||||
readonly kid: string;
|
||||
readonly agent_id: string;
|
||||
/** Base64-encoded public key (stored as BLOB in D1) */
|
||||
readonly public_key: string;
|
||||
readonly algorithm: 'ed25519';
|
||||
readonly status: KeyStatus;
|
||||
readonly created_at: number;
|
||||
readonly retired_at: number | null;
|
||||
}
|
||||
|
||||
/** Persisted operation record in D1 */
|
||||
export interface Operation {
|
||||
readonly operation_id: string;
|
||||
readonly org_id: string;
|
||||
readonly agent_id: string;
|
||||
readonly seq_no: number;
|
||||
readonly operation_type: string;
|
||||
readonly issued_at: number;
|
||||
readonly ttl_ms: number;
|
||||
readonly nonce: string;
|
||||
readonly subject: string;
|
||||
readonly action: string;
|
||||
readonly payload_hash: string;
|
||||
readonly prev_chain_hash: string;
|
||||
readonly chain_hash: string;
|
||||
readonly agent_pubkey_kid: string;
|
||||
readonly signature: string;
|
||||
readonly r2_payload_key: string | null;
|
||||
readonly created_at: number;
|
||||
}
|
||||
|
||||
/** Receipt stored in R2, referenced from D1 */
|
||||
export interface Receipt {
|
||||
readonly receipt_id: string;
|
||||
readonly operation_id: string;
|
||||
readonly r2_receipt_key: string;
|
||||
readonly created_at: number;
|
||||
}
|
||||
|
||||
/** Periodic Merkle epoch rollup record */
|
||||
export interface Epoch {
|
||||
readonly epoch_id: string;
|
||||
readonly org_id: string;
|
||||
readonly start_time: number;
|
||||
readonly end_time: number;
|
||||
readonly root_hash: string;
|
||||
readonly leaf_count: number;
|
||||
readonly r2_epoch_key: string;
|
||||
readonly created_at: number;
|
||||
}
|
||||
|
||||
/** Admin audit event log entry */
|
||||
export interface AdminEvent {
|
||||
readonly event_id: string;
|
||||
readonly org_id: string;
|
||||
readonly actor: string;
|
||||
readonly action: string;
|
||||
readonly target_type: string;
|
||||
readonly target_id: string;
|
||||
readonly details: string | null;
|
||||
readonly created_at: number;
|
||||
}
|
||||
|
||||
/** Organization */
|
||||
export interface Organization {
|
||||
readonly org_id: string;
|
||||
readonly name: string;
|
||||
readonly created_at: number;
|
||||
readonly updated_at: number;
|
||||
}
|
||||
|
||||
/** Console user within an organization */
|
||||
export interface User {
|
||||
readonly user_id: string;
|
||||
readonly org_id: string;
|
||||
readonly email: string;
|
||||
readonly display_name: string;
|
||||
readonly role: RbacRole;
|
||||
readonly status: 'active' | 'suspended';
|
||||
readonly created_at: number;
|
||||
readonly updated_at: number;
|
||||
}
|
||||
|
||||
/** Compliance export job */
|
||||
export interface Export {
|
||||
readonly export_id: string;
|
||||
readonly org_id: string;
|
||||
readonly status: ExportStatus;
|
||||
readonly query_params: string;
|
||||
readonly r2_export_key: string | null;
|
||||
readonly created_at: number;
|
||||
readonly completed_at: number | null;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/** Agent lifecycle status */
|
||||
export type AgentStatus = 'active' | 'frozen' | 'revoked';
|
||||
|
||||
/** Agent key lifecycle status */
|
||||
export type KeyStatus = 'active' | 'retired' | 'revoked';
|
||||
|
||||
/** Export job status */
|
||||
export type ExportStatus = 'queued' | 'running' | 'done' | 'failed';
|
||||
|
||||
/** Administrative action types for audit logging */
|
||||
export type AdminAction =
|
||||
| 'agent.register'
|
||||
| 'agent.update'
|
||||
| 'agent.freeze'
|
||||
| 'agent.unfreeze'
|
||||
| 'agent.revoke'
|
||||
| 'agent.delete'
|
||||
| 'key.revoke'
|
||||
| 'export.create';
|
||||
|
||||
/** RBAC roles for console access */
|
||||
export type RbacRole =
|
||||
| 'org_owner'
|
||||
| 'security_admin'
|
||||
| 'compliance_auditor'
|
||||
| 'readonly_investigator'
|
||||
| 'integration_engineer';
|
||||
|
||||
/** Error codes returned by the API */
|
||||
export type ErrorCode =
|
||||
| 'INVALID_SIGNATURE'
|
||||
| 'UNKNOWN_AGENT'
|
||||
| 'KEY_REVOKED'
|
||||
| 'AGENT_FROZEN'
|
||||
| 'TTL_EXPIRED'
|
||||
| 'REPLAY_DETECTED'
|
||||
| 'PREV_HASH_MISMATCH'
|
||||
| 'PAYLOAD_TOO_LARGE'
|
||||
| 'RATE_LIMITED'
|
||||
| 'INTERNAL_ERROR'
|
||||
| 'UNAUTHORIZED'
|
||||
| 'FORBIDDEN'
|
||||
| 'NOT_FOUND'
|
||||
| 'VALIDATION_ERROR';
|
||||
@@ -0,0 +1,61 @@
|
||||
export type {
|
||||
AgentStatus,
|
||||
KeyStatus,
|
||||
ExportStatus,
|
||||
AdminAction,
|
||||
RbacRole,
|
||||
ErrorCode,
|
||||
} from './enums.js';
|
||||
|
||||
export type {
|
||||
EOR,
|
||||
ECH,
|
||||
EAR,
|
||||
EER,
|
||||
} from './protocol.js';
|
||||
|
||||
export type {
|
||||
Agent,
|
||||
AgentKey,
|
||||
Operation,
|
||||
Receipt,
|
||||
Epoch,
|
||||
AdminEvent,
|
||||
Export,
|
||||
Organization,
|
||||
User,
|
||||
} from './entities.js';
|
||||
|
||||
export type {
|
||||
RegisterAgentRequest,
|
||||
RegisterAgentResponse,
|
||||
GetAgentResponse,
|
||||
ListAgentsResponse,
|
||||
FreezeAgentRequest,
|
||||
UnfreezeAgentRequest,
|
||||
RevokeAgentRequest,
|
||||
UpdateAgentRequest,
|
||||
SubmitOperationRequest,
|
||||
SubmitOperationResponse,
|
||||
GetOperationResponse,
|
||||
VerifyOperationResponse,
|
||||
AuditQueryRequest,
|
||||
AuditQueryResponse,
|
||||
GetEpochResponse,
|
||||
ListEpochsResponse,
|
||||
CreateExportRequest,
|
||||
CreateExportResponse,
|
||||
GetExportResponse,
|
||||
ListExportsResponse,
|
||||
AuthRegisterRequest,
|
||||
AuthRegisterResponse,
|
||||
AuthLoginRequest,
|
||||
AuthLoginResponse,
|
||||
AuthMeResponse,
|
||||
AuthRefreshResponse,
|
||||
IssueTokenRequest,
|
||||
IssueTokenResponse,
|
||||
JWK,
|
||||
JWKSResponse,
|
||||
ErrorResponse,
|
||||
} from './api.js';
|
||||
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* Elydora Operation Record (EOR)
|
||||
*
|
||||
* The fundamental unit of auditable activity in the Elydora protocol.
|
||||
* Signed by the agent's Ed25519 key and chained via prev_chain_hash.
|
||||
*/
|
||||
export interface EOR {
|
||||
/** Protocol version, always "1.0" */
|
||||
readonly op_version: '1.0';
|
||||
/** Unique operation identifier (UUIDv7) */
|
||||
readonly operation_id: string;
|
||||
/** Organization identifier */
|
||||
readonly org_id: string;
|
||||
/** Agent that issued this operation */
|
||||
readonly agent_id: string;
|
||||
/** Timestamp when issued (Unix milliseconds) */
|
||||
readonly issued_at: number;
|
||||
/** Time-to-live in milliseconds */
|
||||
readonly ttl_ms: number;
|
||||
/** Replay-prevention nonce (base64url) */
|
||||
readonly nonce: string;
|
||||
/** Classification of the operation */
|
||||
readonly operation_type: string;
|
||||
/** Subject of the operation */
|
||||
readonly subject: Record<string, unknown>;
|
||||
/** Action performed */
|
||||
readonly action: Record<string, unknown>;
|
||||
/** Operation payload */
|
||||
readonly payload: Record<string, unknown> | string | null;
|
||||
/** SHA-256 hash of the payload (base64url) */
|
||||
readonly payload_hash: string;
|
||||
/** Hash of the previous operation in the agent's chain (base64url) */
|
||||
readonly prev_chain_hash: string;
|
||||
/** Key ID of the agent's signing key */
|
||||
readonly agent_pubkey_kid: string;
|
||||
/** Ed25519 signature over the canonical EOR (base64url) */
|
||||
readonly signature: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Elydora Chain Hash (ECH)
|
||||
*
|
||||
* Represents the chain hash computation linking operations together.
|
||||
*/
|
||||
export interface ECH {
|
||||
/** Previous chain hash (base64url) */
|
||||
readonly prev_ech: string;
|
||||
/** SHA-256 hash of the operation payload (base64url) */
|
||||
readonly payload_hash: string;
|
||||
/** Operation identifier (UUIDv7) */
|
||||
readonly operation_id: string;
|
||||
/** Timestamp when issued (Unix milliseconds) */
|
||||
readonly issued_at: number;
|
||||
/** Resulting chain hash (base64url) */
|
||||
readonly chain_hash: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Elydora Acknowledgment Receipt (EAR)
|
||||
*
|
||||
* Server-issued receipt confirming acceptance of an operation.
|
||||
*/
|
||||
export interface EAR {
|
||||
/** Receipt version */
|
||||
readonly receipt_version: string;
|
||||
/** Unique receipt identifier */
|
||||
readonly receipt_id: string;
|
||||
/** Operation this receipt acknowledges */
|
||||
readonly operation_id: string;
|
||||
/** Organization identifier */
|
||||
readonly org_id: string;
|
||||
/** Agent that submitted the operation */
|
||||
readonly agent_id: string;
|
||||
/** Timestamp when the server received the operation (Unix ms) */
|
||||
readonly server_received_at: number;
|
||||
/** Sequence number assigned to the operation */
|
||||
readonly seq_no: number;
|
||||
/** Chain hash at time of receipt */
|
||||
readonly chain_hash: string;
|
||||
/** Queue message ID for async processing */
|
||||
readonly queue_message_id: string;
|
||||
/** Hash of this receipt */
|
||||
readonly receipt_hash: string;
|
||||
/** Elydora server key ID used for signing */
|
||||
readonly elydora_kid: string;
|
||||
/** Elydora server signature over the receipt */
|
||||
readonly elydora_signature: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Elydora Epoch Record (EER)
|
||||
*
|
||||
* Periodic Merkle-tree rollup anchoring operations to a root hash.
|
||||
*/
|
||||
export interface EER {
|
||||
/** Unique epoch identifier */
|
||||
readonly epoch_id: string;
|
||||
/** Organization identifier */
|
||||
readonly org_id: string;
|
||||
/** Epoch start time (Unix ms) */
|
||||
readonly start_time: number;
|
||||
/** Epoch end time (Unix ms) */
|
||||
readonly end_time: number;
|
||||
/** Number of leaf operations in this epoch */
|
||||
readonly leaf_count: number;
|
||||
/** Merkle root hash */
|
||||
readonly root_hash: string;
|
||||
/** Hash algorithm used (e.g. "sha256") */
|
||||
readonly hash_alg: string;
|
||||
/** Elydora server signature over the epoch record */
|
||||
readonly signature_by_elydora: string;
|
||||
}
|
||||
Reference in new issue
Block a user