Skip to main content

Overview

GenosDB’s security architecture provides robust authentication, data integrity, and access control within a distributed, peer-to-peer (P2P) environment. The Security Manager (SM) module transforms GenosDB into a secure, zero-trust platform by integrating cryptographic identity, role-based permissions, and end-to-end encryption directly into the data pipeline.
The Security Manager is optional and enabled during database initialization with the sm configuration option.

Enabling the Security Manager

import { gdb } from 'genosdb'

const db = await gdb('my-secure-db', {
  rtc: true,
  sm: {
    superAdmins: ['0x1234...', '0x5678...']  // Ethereum addresses
  }
})

Core Security Components

1. Cryptographic Identity

Every user in GenosDB is identified by an Ethereum wallet with a cryptographic key pair:
  • Public Address: Unique user identifier visible to all peers
  • Private Key: Securely stored, used to sign all operations
  • Sovereignty: Users own their digital identity without central authority

WebAuthn Protection

Private keys are encrypted using secrets derived from biometric authentication or hardware security keys (FIDO2).

Mnemonic Recovery

BIP39 mnemonic phrases enable account creation and backup for recovery across devices.

2. Role-Based Access Control (RBAC)

RBAC defines a hierarchy of roles with specific permissions, enforced via cryptographic signatures:

Default Role Hierarchy

1

guest

Permissions: read, syncBasic read-only access to synchronized data.
2

user

Permissions: write, link, syncInherits: guestCan create and modify their own data.
3

manager

Permissions: publishInherits: userCan publish content visible to all users.
4

admin

Permissions: deleteInherits: managerCan delete any content.
5

superadmin

Permissions: assignRole, deleteAnyInherits: adminCan assign roles and has unrestricted access.

Custom Roles

You can define custom roles during initialization:
const db = await gdb('my-app', {
  rtc: true,
  sm: {
    superAdmins: ['0x1234...'],
    customRoles: {
      editor: {
        can: ['write', 'publish'],
        inherits: ['guest']
      },
      moderator: {
        can: ['delete'],
        inherits: ['user']
      }
    }
  }
})

3. In-Graph Role Storage

User roles are stored as nodes within the GenosDB graph itself:
  • Distributed: Roles are synchronized across all peers via P2P
  • Publicly Readable: Any peer can query user roles for verification
  • Format: Stored in user:[eth_address] nodes
// Assign a role (requires superadmin permission)
await db.sm.assignRole('0xUserAddress...', 'admin')

// Query a user's role
const userRole = await db.sm.getUserRole('0xUserAddress...')
console.log(userRole)  // 'admin'
Only users with the assignRole permission (typically superadmins) can modify user roles.

4. Cryptographic Operation Signing

Every database operation in a secure GenosDB instance is cryptographically signed:

Outgoing Operations

1

User performs operation

await db.put({ name: 'Alice' }, 'user1')
2

SM signs the operation

The operation is signed with the user’s private key before broadcast.
3

Signature embedded

The signature and public address are included in the P2P message.

Incoming Operations

The SM middleware on each peer verifies every incoming operation:
1

Verify Signature

Confirm the cryptographic signature matches the operation content and sender’s public address.
2

Resolve Permissions

Look up the sender’s role in the local graph (user:[eth_address] node).
3

Authorize Action

Check if the resolved role has permission for the requested action.
4

Apply or Reject

Valid operations are applied to the graph; invalid operations are silently discarded.
// Example: User with 'guest' role attempts to write
// SM middleware will reject the operation because 'guest' lacks 'write' permission
This creates a zero-trust environment where every peer independently enforces security rules.

WebAuthn Authentication

GenosDB supports passwordless authentication using the WebAuthn standard:

Registration Flow

// 1. Start new user registration (generates mnemonic)
const { mnemonic, address } = await db.sm.startNewUserRegistration()

console.log('Save this mnemonic securely:', mnemonic)
console.log('Your address:', address)

// 2. Protect the identity with WebAuthn (biometrics/security key)
const protected = await db.sm.protectCurrentIdentityWithWebAuthn(
  '[email protected]'  // Username/identifier
)

if (protected.success) {
  console.log('Identity protected with WebAuthn')
}

Login Flow

// Login using WebAuthn (no password required)
const result = await db.sm.loginCurrentUserWithWebAuthn()

if (result.success) {
  console.log('Logged in as:', result.address)
} else {
  console.error('Login failed:', result.error)
}

Mnemonic Recovery

// Recover account on a new device
const mnemonic = 'word1 word2 word3 ...'  // User's backup phrase
const result = await db.sm.loginOrRecoverUserWithMnemonic(mnemonic)

if (result.success) {
  console.log('Account recovered:', result.address)
  
  // Re-protect with WebAuthn on the new device
  await db.sm.protectCurrentIdentityWithWebAuthn('[email protected]')
}
Mnemonics provide full account access. Users must store them securely, preferably offline.

Access Control Lists (ACLs)

ACLs extend RBAC with fine-grained, per-node permissions:

Enabling ACLs

const db = await gdb('my-app', {
  rtc: true,
  sm: {
    superAdmins: ['0x1234...'],
    acls: true  // Enable ACL module
  }
})

Creating Nodes with ACLs

// Create a node with initial ACL permissions
const nodeId = await db.sm.acls.set(
  { title: 'Private Document', content: '...' },  // Node value
  {
    '0xUserA...': ['read', 'write'],  // UserA can read and write
    '0xUserB...': ['read']            // UserB can only read
  }
)

Granting and Revoking Permissions

// Grant write permission to a user
await db.sm.acls.grant(
  nodeId,           // Node ID
  '0xUserC...',     // User address
  ['read', 'write'] // Permissions
)

// Revoke write permission
await db.sm.acls.revoke(
  nodeId,
  '0xUserC...',
  ['write']  // Revoke only write, keep read
)

Permission Types

read

View node data

write

Modify node data

delete

Remove the node

Ownership Model

The creator of a node automatically becomes the owner with full permissions:
// User creates a node - becomes owner automatically
const nodeId = await db.put({ type: 'note', text: 'My note' })

// Owner can grant permissions to others
await db.sm.acls.grant(nodeId, '0xOtherUser...', ['read'])
ACL checks are performed in addition to RBAC. A user must have both the role permission and the ACL permission for an operation to succeed.

End-to-End Encryption

The SM module provides transparent, user-controlled encryption:

Encrypted Storage

// Store encrypted data (only current user can decrypt)
await db.sm.put({
  secret: 'Sensitive information',
  apiKey: 'sk_1234...'
})

Encrypted Retrieval

// Retrieve and automatically decrypt (if user is the owner)
const { result } = await db.sm.get(nodeId)

if (result.decrypted) {
  console.log('Decrypted data:', result.value)
} else {
  console.log('Cannot decrypt (not the owner)')
}

How It Works

1

Encryption

Data is encrypted using a key derived from the user’s private key.
2

Secure Payload

The encrypted ciphertext is wrapped in a _gdbSecurePayloadV1 object with metadata:
{
  _payload: 'encrypted_ciphertext',  // Encrypted data
  _meta: {
    owner: '0xUserAddress...'  // Owner's public address
  }
}
3

Conditional Decryption

When retrieved, the SM checks if the current user’s address matches the owner. If yes, it decrypts automatically.
Encrypted data is only accessible to the owner. There is no “shared encryption” - use ACLs for collaborative access to unencrypted data.

Distributed Trust Model

GenosDB’s security model eliminates central authority through three principles:

1. Cryptographic Identity

Each user is identified by a unique cryptographic keypair, not by a username/password managed by a server.

2. Verifiable Actions

Every operation is digitally signed, ensuring:
  • Authenticity: Proof of who performed the action
  • Integrity: Proof the action wasn’t tampered with
  • Non-repudiation: The signer cannot deny performing the action

3. Shared Constitution

Security rules (roles, permissions) are:
  • Embedded in the software itself
  • Distributed as graph data
  • Enforced locally by every peer
  • Agreed upon through eventual consistency

Solving the Bootstrap Problem

How does a new user join without a central authority to verify them?
1

Zero-Trust Welcome Exception

A new user is allowed one write operation to create their profile node.
2

Default Guest Role

After the initial write, the user is treated as a guest with limited permissions.
3

Role Assignment

A superadmin explicitly grants the user a higher role if appropriate.
// New user creates their profile (allowed once)
await db.put({ name: 'Alice', bio: 'New user' }, 'alice-profile')

// Subsequent writes require proper role assignment
// Superadmin assigns role
await db.sm.assignRole('0xAliceAddress...', 'user')
This prevents privilege escalation attacks while allowing legitimate new users to join.

Security in Full-State Sync

During full-state synchronization, additional validation occurs:
  • Origin Pre-validation: Permission checks before operations modify the sender’s local database
  • Node Verification on Sync: Permissions of lastModifiedBy user are verified for nodes newer than local versions
  • (Optional) Trust in Sync Sender: Acceptance of full graphs can be restricted to high-trust roles (e.g., admin)

Session Management

Logout

// Clear current user session
await db.sm.clearSecurity()
console.log('User logged out')

Check Current User

// Get current authenticated user
const currentUser = db.sm.getCurrentUser()

if (currentUser) {
  console.log('Logged in as:', currentUser.address)
} else {
  console.log('No user logged in')
}

Verifier-Only Mode

A GenosDB instance without an active user session can still verify operations:
const db = await gdb('public-db', {
  rtc: true,
  sm: { superAdmins: ['0x1234...'] }
})

// No user logged in, but SM still enforces security rules
// Incoming operations are verified and applied based on sender's role

Complete Security Example

import { gdb } from 'genosdb'

// Initialize secure database
const db = await gdb('secure-app', {
  rtc: true,
  sm: {
    superAdmins: ['0xSuperAdmin...'],
    customRoles: {
      editor: { can: ['write', 'publish'], inherits: ['guest'] }
    },
    acls: true
  }
})

// === Registration ===
const { mnemonic, address } = await db.sm.startNewUserRegistration()
console.log('Backup this mnemonic:', mnemonic)

// Protect with WebAuthn
await db.sm.protectCurrentIdentityWithWebAuthn('[email protected]')

// === Superadmin assigns role ===
await db.sm.assignRole(address, 'editor')

// === Create encrypted personal data ===
await db.sm.put({ secret: 'My API key' })

// === Create shared data with ACLs ===
const docId = await db.sm.acls.set(
  { title: 'Team Document', content: '...' },
  {
    '0xTeamMember1...': ['read', 'write'],
    '0xTeamMember2...': ['read']
  }
)

// === Later: Login with WebAuthn ===
const loginResult = await db.sm.loginCurrentUserWithWebAuthn()
if (loginResult.success) {
  console.log('Logged in successfully')
}

// === Logout ===
await db.sm.clearSecurity()

Best Practices

Secure Mnemonic Storage

Never store mnemonics in code or version control. Use secure, offline storage.

Minimal Superadmins

Limit the number of superadmin addresses to reduce attack surface.

Principle of Least Privilege

Assign users the minimum role necessary for their tasks.

Use ACLs for Sensitive Data

Combine RBAC with ACLs for fine-grained control over sensitive nodes.

Security Considerations

Client-Side Security: GenosDB’s security runs in the browser. While cryptographic operations are robust, users with modified/malicious clients can bypass local checks. The P2P verification layer ensures network integrity, but cannot prevent a malicious user from corrupting their own local state.
Mnemonic Compromise: If a user’s mnemonic phrase is compromised, an attacker gains full access to that identity. There is no “password reset” - the user must create a new identity and have a superadmin assign roles.
WebAuthn provides strong protection against phishing and credential stuffing attacks, making it the recommended authentication method for production applications.

CRUD Operations

Learn how put, get, and remove work with security

P2P Sync

Understand how signed operations are synchronized

Chat Example

See RBAC in action in a real-time chat application

SM API Reference

Complete SM API documentation

Build docs developers (and LLMs) love