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:
ZacharyZhang-NYandClaude Opus 4.6 committed 2026-03-02 13:41:42 -05:00
1 parent 15547a8c35
commit e390e68594
207 files changed
+32790 -63

No files matched your search

+90
View File
@@ -0,0 +1,90 @@
/**
* Operation routes — submit, retrieve, and verify signed operation records.
*/
import { Hono } from 'hono';
import type { Env, AppVariables } from '../types.js';
import type { EOR } from '../shared/index.js';
import { authMiddleware } from '../middleware/auth.js';
import { requireRole } from '../middleware/rbac.js';
import { AppError } from '../middleware/error-handler.js';
import * as operationService from '../services/operation-service.js';
const operations = new Hono<{ Bindings: Env; Variables: AppVariables }>();
// ---------------------------------------------------------------------------
// POST /v1/operations — Submit a signed EOR
// ---------------------------------------------------------------------------
// Operation submission uses the EOR's embedded signature for authentication
// rather than a Bearer JWT. The agent authenticates via its Ed25519 signature.
// We still apply auth middleware to get the org context.
operations.post(
'/',
authMiddleware,
requireRole('integration_engineer'),
async (c) => {
const eorBody = await c.req.json<EOR>();
const orgId = c.get('org_id');
const eor = { ...eorBody, org_id: orgId };
if (!eor || !eor.operation_id) {
throw new AppError(400, 'VALIDATION_ERROR', { key: 'operation.invalidBody' });
}
const result = await operationService.submitOperation(
c.env.ELYDORA_DB,
c.env.ELYDORA_EVIDENCE,
c.env.ELYDORA_CACHE,
c.env.ELYDORA_QUEUE,
eor,
c.env.ELYDORA_SIGNING_KEY,
);
c.header('X-Elydora-Protocol-Version', c.env.PROTOCOL_VERSION);
return c.json(result, 202);
},
);
// ---------------------------------------------------------------------------
// GET /v1/operations/:operation_id — Retrieve an operation
// ---------------------------------------------------------------------------
operations.get(
'/:operation_id',
authMiddleware,
requireRole('readonly_investigator'),
async (c) => {
const operationId = c.req.param('operation_id');
const orgId = c.get('org_id');
const result = await operationService.getOperation(c.env.ELYDORA_DB, c.env.ELYDORA_EVIDENCE, operationId, orgId);
c.header('X-Elydora-Protocol-Version', c.env.PROTOCOL_VERSION);
return c.json(result, 200);
},
);
// ---------------------------------------------------------------------------
// POST /v1/operations/:operation_id/verify — Verify operation integrity
// ---------------------------------------------------------------------------
operations.post(
'/:operation_id/verify',
authMiddleware,
requireRole('readonly_investigator'),
async (c) => {
const operationId = c.req.param('operation_id');
const orgId = c.get('org_id');
const result = await operationService.verifyOperation(
c.env.ELYDORA_DB,
c.env.ELYDORA_EVIDENCE,
operationId,
orgId,
);
c.header('X-Elydora-Protocol-Version', c.env.PROTOCOL_VERSION);
return c.json(result, 200);
},
);
export { operations };