Documentation

System Architecture

Ekayana is a platform for storing, identifying and sharing research data. It is built from four subsystems.

  • Identity is the did:bio method, a W3C DID method anchored on Solana. Researchers are identified by their wallets. Datasets, papers and claims are identified by DIDs that those wallets own.
  • Storage is a private IPFS cluster, with every upload pinned on every peer on write. Payloads are sealed before they reach the cluster, so a CID addresses ciphertext.
  • Authorization is UCAN 1.0 delegations and invocations. Every grant is signed by a wallet. The service validates chains and does not sign on a user's behalf.
  • Processing is BioAgents, an ElizaOS deployment that indexes registered papers and maintains a knowledge graph, reached only through the API.

This page describes the components that implement these subsystems, the keys that control them, and the path of a request through the system. The other pages describe one component each.

Components

Three implement identity and follow one specification. Two implement authorization. The API and the browser application consume them.

IDENTITY - one specification, three cratesAUTHORIZATION - two cratesdid:bio method specW3C DID 1.0 conformantinstructions, layoutresolution, data modelbio-did-registrySolana program, devnetdid-bio-coremodel and resolutionix constantsresolvebio-did-resolvercommand line clientUCAN 1.0 with post quantumprincipals as ordinary algorithmspq-ucanUCAN 1.0 for Rustsigns, validatespq-spaceprincipals, KEM wrapdid:bio principalsCONSUMERSEkayana API (bio-did-seq)axum, Postgres, IPFS, ML-KEM vaultBrowser appthe wallet signs, a session key readsas a libraryresolve, verifytokens, content keysprepare / signEvery arrow points down. The crates know nothing about the platform, which is what makes them reusable outside it.
Dependencies between the repositories. The did:bio specification defines the registry program and did-bio-core. bio-did-resolver builds on both. pq-ucan implements UCAN 1.0 and pq-space adds did:bio principals and ML-KEM content key wrapping. The Ekayana API and the browser app consume them.
RepositoryVersionContents
bio-did-specv1.3The did:bio method definition, covering identifier syntax, the two subject forms, authorization through controllers and programs, the resolution algorithm, and security and privacy considerations
bio-did-registry0.2.0The Solana program that serves as the method's verifiable data registry, also usable as a library that exports the program's constants and builds its instructions
did-bio-core0.2.0Data model, strict account decoders, the resolution algorithm as a pure function, dereferencing and a quorum reader, with Ed25519, ES256K and ML-DSA-87 verification behind a feature
bio-did-resolver0.2.0Command line resolver and client for every registry instruction except update_service
pq-ucan0.1.2UCAN 1.0 delegation, invocation, the policy language and chain validation, with ML-DSA principals
pq-space0.1.2did:bio principals for pq-ucan, and ML-KEM-1024 content key wrapping carried inside the delegation

Dependencies between them are as follows.

  • bio-did-registry and did-bio-core implement the specification independently. Parity tests in did-bio-core and bio-did-resolver pin their constants, discriminators and derivations to each other.
  • pq-space depends on did-bio-core, so that a did:bio identity can sign and verify tokens in the same chain as did:key principals.
  • The API links bio-did-registry with the no-entrypoint feature. The instructions it plans for a wallet are encoded by the same code that decodes them on-chain.
  • The browser application links none of the crates. It signs bytes that the API prepares.

The runtime components are these.

ComponentStackRole
Ekayana APIRust, axum, PostgresAccounts, DID records, workflow planning, sealing and opening payloads, UCAN validation, BioAgents and Dataverse proxies
Browser applicationNext.js, @solana/kitWallet connection, transaction and delegation signing, a per session read key
RegistryPinocchio program on Solana devnetProgram H1gnV4GjNT3UV7AgGNUCkSaciuVVtM7hKb8JhPV3Xxy6, reproducible build
StoragePrivate IPFS cluster, Kubo peers behind IPFS ClusterSealed payloads and public metadata documents referenced from DID service entries, pinned on every peer
BioAgentsElizaOSKnowledge base, knowledge graph and structure plugins

Key custody

The service holds no key that can act on a researcher's behalf. The key holders and the operations each may perform are shown below.

WHO HOLDS WHICH KEYResearcher's walletHOLDSEd25519 keypair (Solana)SIGNS OR DOESregistry transactions, pays rentdelegations: shares, sessionRegistry (Solana)HOLDSDID accounts, under consensusSIGNS OR DOEScapabilityInvocation keys writeanyone reads, nothing is secretEkayana serviceHOLDSdid:bio + ML-DSA-87, one seedML-KEM-1024 secret keySIGNS OR DOESexecutor of every invocationseals and opens payloadsholds no user keyBrowser session keyHOLDSEd25519, WebCrypto, no exportSIGNS OR DOESread invocations for 24 hforgotten at sign outIPFSHOLDSsealed payloads, public docsSIGNS OR DOESa CID addresses ciphertextreplicas cannot read itsigns and pays transactions/file/read for 24 hdelegationsinvocationsreads onlysealed bytesNothing the service stores can sign as a researcher, and nothing IPFS stores can be read without the ML-KEM key.A breach of the service leaks ciphertext and public documents, not authority.
Who holds which key. The wallet signs registry transactions and delegations. The browser session key signs read invocations for 24 hours. The service is the executor and holds the ML-KEM key but no user key. The registry accepts writes only from capabilityInvocation keys. IPFS holds sealed payloads.
  • The wallet is an Ed25519 keypair held by the researcher. Its address on the configured cluster is the researcher's did:bio. It signs registry transactions and pays their rent, signs every delegation, whether a share or a session grant, and is the only key that can grant write or delete.
  • The browser session key is a nonextractable Ed25519 key created in WebCrypto at sign in. The wallet grants it /file/read for 24 hours through a powerline delegation. It signs read invocations and is discarded at sign out.
  • The service derives a did:bio and an ML-DSA-87 assertion key from one seed, SERVICE_SEED, and holds the ML-KEM-1024 decapsulation key, MLKEM_SECRET_KEY. It is the executor named by every invocation. It seals and opens payloads. It issues no delegations.
  • The registry holds DID documents under Solana consensus. Only a key listed with capabilityInvocation can change a document. The service reads at finalized commitment and never writes.
  • IPFS holds sealed payloads and public metadata documents. A CID addresses ciphertext, and replicas cannot read it.

A compromise of the service therefore exposes ciphertext and public documents rather than authority. Session tokens are opaque 256 bit bearer values stored as hashes and carry no claims.

Request flow

Each flow below crosses at least two subsystems and links to the page that specifies it.

  • Account and wallet. POST /api/signup creates an account and a session. POST /api/wallet/nonce and POST /api/wallet/verify run a Sign In With Solana challenge and record the wallet. From then on the account's DID is the wallet's. See Authentication.
  • DID creation. POST /api/did derives an owned subject from the wallet and a fresh nonce and stores the record. The DID resolves to notFound until it is anchored. See did:bio identifiers.
  • Anchoring. POST /api/workflows plans a transaction made of initialize_owned, the service entries and the controller, and quotes its rent and fee. The wallet signs and sends it. POST /api/workflows/{id}/confirm makes the API read the transaction and the account from the chain before it marks the record anchored. See Solana Registry Program.
  • Upload. POST /api/upload seals the payload under a fresh content key and pins the ciphertext. See Privacy Controls.
  • Sharing. POST /api/share/file/prepare returns the bytes of a delegation naming the CID, the recipient's DID, the actions and the expiry. The wallet signs them. POST /api/share/file assembles, verifies and records the token. See UCAN Authorization.
  • Reading. POST /api/ucan/invoke/prepare returns the bytes of a 60 second invocation. The session key signs them. GET /api/download/{cid} carries the token and the invocation in the x-ucan-token and x-ucan-invocation headers. The API validates the chain with itself as executor, then decrypts. See Sharing & Delegation.

Scope of the guarantees

  • Post quantum cryptography applies to specific layers. These are ML-DSA-87 assertion keys in DID documents, ML-DSA principals in UCAN chains, and ML-KEM-1024 content key wrapping. Registry transactions and wallet signatures are Ed25519. See Post Quantum Security.
  • Revocation is recorded by the service. pq-ucan validates chains, and the API checks its revoked_at column before it runs the validator.
  • None of the components has received an external audit. The registry runs on devnet.