Skip to content

Jolt-Database/Jolt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Jolt

A high-performance, in-memory publish/subscribe message broker over plain TCP, with an extremely simple JSON-based protocol.

Inspired by Redis Pub/Sub and NATS core, but focused on:

  • In-memory only (no persistence)
  • Single node, single binary
  • Thousands of concurrent TCP connections
  • Minimal NDJSON protocol
  • Optional authentication and authorization

Features

  • NDJSON protocol: one JSON object per line, UTF-8.
  • Operations: auth, sub, unsub, pub, ping.
  • In-memory topics: no persistence, low-latency broadcast to subscribers.
  • Optional security:
    • Username + password authentication.
    • Strong salted, iterative password hashing (HMAC-SHA256).
    • Constant-time password comparison.
    • Per-user permissions: publish:<topic>, subscribe:<topic>, admin.
  • Config-driven:
    • Bind address and port.
    • Security on/off.
    • Initial admin and user accounts.
  • Cross-platform:
    • Windows (x64)
    • Linux (x64)
    • macOS (x64 / ARM64)

Architecture

High-level design

  • Server: a TCP listener (net.Listen) that accepts clients and spawns a goroutine per connection.
  • Protocol: clients send newline-delimited JSON (NDJSON); server responds similarly.
  • Topic registry: an in-memory map topic -> set of subscribers.
  • Security manager: user registry, password hashing, permission checks.

Components

  • cmd/broker/main.go
    • Entry point, loads configuration, initializes security, starts server.
  • internal/config
    • Loads and validates JSON config.
  • internal/security
    • Password hashing and checking.
    • User registry with in-memory permissions.
  • internal/protocol
    • Types and helpers for client requests and server responses.
  • internal/server
    • Core TCP server and connection handling.
    • Topic subscriptions and message routing.

Supported platforms

  • Go 1.20+ (standard library only)
  • Operating systems:
    • Windows (x64)
    • Linux (x64)
    • macOS (x64 / ARM64)

No OS-specific syscalls are used. The server relies solely on net and other portable APIs.


Security Model

Security is configurable and off by default.

When security is disabled

  • All clients are treated as anonymous.
  • No authentication is required.
  • All operations are allowed:
    • Any client can publish to any topic.
    • Any client can subscribe to any topic.
  • Permission checks effectively become no-ops.

When security is enabled

  • Each client must authenticate before performing any operation:
    • auth must be called first with user and pass.
  • Passwords:
    • Never stored in plaintext in memory.
    • Hashed using random salts and iterative HMAC-SHA256.
    • Verified using constant-time comparison.
  • Users have explicit permissions such as:
    • publish:chat.room1
    • subscribe:chat.room1
    • publish:chat.* (wildcard suffix)
    • subscribe:chat.* (wildcard suffix)
    • admin
  • If a client tries to perform an operation without permission:
    • The operation is rejected.
    • The server returns {"ok":false,"error":"permission_denied"}.

Users and Roles

  • Unlimited number of users supported.
  • One built-in administrator user defined in configuration.
  • Only the administrator (or any user with admin permission) can:
    • Create users.
    • Delete users.
    • Change user passwords.
    • Grant or revoke permissions.

Note: For simplicity, administrative operations (create/delete users etc.) are currently implemented via the in-memory security manager API. Exposing these safely over the public network protocol can be added on top (e.g. {"op":"admin.create_user", ...}), but must be done carefully to preserve strong security guarantees.


Configuration

Configuration is provided as a JSON file.

Example: security disabled (default behavior)

{
  "network": {
    "bind": "0.0.0.0",
    "port": 8080
  },
  "security": {
    "enabled": false,
    "admin_user": {
      "username": "",
      "password": "",
      "permissions": []
    },
    "users": []
  }
}

Example: security enabled

{
  "network": {
    "bind": "0.0.0.0",
    "port": 8080
  },
  "security": {
    "enabled": true,
    "admin_user": {
      "username": "admin",
      "password": "strong-admin-password",
      "permissions": ["admin"]
    },
    "users": [
      {
        "username": "publisher1",
        "password": "secret1",
        "permissions": ["publish:chat.room1"]
      },
      {
        "username": "subscriber1",
        "password": "secret2",
        "permissions": ["subscribe:chat.room1"]
      },
      {
        "username": "chatuser",
        "password": "secret3",
        "permissions": [
          "publish:chat.*",
          "subscribe:chat.*"
        ]
      }
    ]
  }
}

Fields

  • network.bind – IP address to bind to, e.g. "0.0.0.0" or "127.0.0.1".
  • network.port – TCP port number, e.g. 8080.
  • security.enabled – boolean:
    • false – no authentication or authorization.
    • true – fully enforced authentication and permissions.
  • security.admin_user:
    • username – admin username (must be non-empty if security enabled).
    • password – admin password in plaintext (hashed in memory).
    • permissions – typically includes "admin".
  • security.users – array of standard users:
    • username – user name.
    • password – user password in plaintext (hashed in memory).
    • permissions – array of permission strings.

Important: The config file may contain plaintext passwords. Protect this file using OS-level permissions and environment constraints.


Protocol Specification

All messages are UTF-8 JSON objects, one per line, delimited by \n. No pretty-printing; no extra whitespace required.

Client operations

Authenticate (when security is enabled)

{"op":"auth","user":"username","pass":"password"}
  • Must be sent before any sub, unsub, or pub operations.
  • When security is disabled:
    • This operation always succeeds and has no effect.

Subscribe

{"op":"sub","topic":"chat.room1"}
  • Subscribes the current connection to a topic.
  • The server will deliver messages published to this topic to this connection.

Unsubscribe

{"op":"unsub","topic":"chat.room1"}
  • Cancels a subscription for this topic for the current connection.

Publish

{"op":"pub","topic":"chat.room1","data":"hello"}
  • Publishes a message to a topic.
  • The server broadcasts { "topic": "...", "data": "..." } to all authorized subscribers of that topic.

Ping

{"op":"ping"}
  • Health check / keep-alive.
  • The server responds with {"ok":true}.

Server responses

Generic success:

{"ok":true}

Error with reason:

{"ok":false,"error":"reason"}

Common error reasons:

  • invalid_json
  • unknown_op
  • missing_credentials
  • auth_failed
  • missing_topic
  • permission_denied

Message delivery

When a message is published to topic "chat.room1":

{"topic":"chat.room1","data":"hello"}

This object is sent to every connection that:

  • Is subscribed to "chat.room1", and
  • Has permission to subscribe to that topic (if security is enabled).

Authentication Flow

Without security

  1. Client connects via TCP.
  2. Client can immediately send sub, pub, ping messages.
  3. auth is optional and does nothing but return {"ok":true}.

With security enabled

  1. Client connects via TCP.

  2. Client sends:

    {"op":"auth","user":"username","pass":"password"}
  3. Server:

    • Looks up the user.
    • Verifies password using:
      • Per-user random salt.
      • Iterative HMAC-SHA256.
      • Constant-time comparison.
  4. On success:

    • Server responds {"ok":true}.
    • Server associates the connection with that user.
  5. On failure:

    • Server responds {"ok":false,"error":"auth_failed"}.
    • Connection remains unauthenticated and may not perform other operations.

Permission System

Permissions are strings:

  • Operation-specific: publish:<topic>, subscribe:<topic>.
  • Admin: admin.
  • Topics can use wildcard suffix: chat.*.

Examples

  • Allow a user to publish to exactly chat.room1:

    • publish:chat.room1
  • Allow a user to subscribe to any chat room under chat.*:

    • subscribe:chat.*
  • Administrator user:

    • admin

Checks

  • For an operation op on topic topic, the server checks:
    • op + ":" + topic (exact match), or
    • op + ":" + prefix + ".*" where topic equals prefix or begins with prefix + ".", or
    • admin permission.

Behavior on Denial

  • If a client attempts sub or pub without permission, the server responds:

    {"ok":false,"error":"permission_denied"}

Build and Run Instructions

Prerequisites

  • Go 1.20+ installed.
  • A configuration file (e.g. config.json).

Build

go build ./cmd/broker

This produces a binary (e.g. broker on Unix-like systems or broker.exe on Windows).

Run (insecure mode)

Using a config with "security": { "enabled": false, ... }:

./broker -config=config.json

Example config.json:

{
  "network": {
    "bind": "0.0.0.0",
    "port": 8080
  },
  "security": {
    "enabled": false,
    "admin_user": {
      "username": "",
      "password": "",
      "permissions": []
    },
    "users": []
  }
}

Run (secure mode)

./broker -config=secure-config.json

Example secure-config.json is shown above in the Security enabled section.


Usage Examples

Below examples assume the server is running on localhost:8080.

You can use nc (netcat), telnet, or a small custom client.

Insecure setup (security disabled)

  1. Start server with security off.

  2. Connect with netcat:

    nc 127.0.0.1 8080
  3. In terminal A, subscribe:

    {"op":"sub","topic":"chat.room1"}

    Server responds:

    {"ok":true}
  4. In terminal B, publish:

    nc 127.0.0.1 8080

    Then send:

    {"op":"pub","topic":"chat.room1","data":"hello world"}

    Server responds to publisher:

    {"ok":true}

    Subscriber (terminal A) receives:

    {"topic":"chat.room1","data":"hello world"}

Secure setup (authentication required)

Given secure-config.json with:

  • User chatuser, password secret3, permissions:
    • publish:chat.*
    • subscribe:chat.*
  1. Start server:

    ./broker -config=secure-config.json
  2. Subscriber connection:

    nc 127.0.0.1 8080

    Authenticate:

    {"op":"auth","user":"chatuser","pass":"secret3"}

    Response:

    {"ok":true}

    Subscribe:

    {"op":"sub","topic":"chat.room1"}

    Response:

    {"ok":true}
  3. Publisher connection:

    nc 127.0.0.1 8080

    Authenticate:

    {"op":"auth","user":"chatuser","pass":"secret3"}

    Response:

    {"ok":true}

    Publish:

    {"op":"pub","topic":"chat.room1","data":"hello secure world"}

    Publisher gets:

    {"ok":true}

    Subscriber gets:

    {"topic":"chat.room1","data":"hello secure world"}

Creating Users and Assigning Permissions

Administrative operations are currently designed to be invoked from within the server process using the security.Manager API.

A typical future extension would be to add admin protocol operations such as:

  • {"op":"admin.create_user", ...}
  • {"op":"admin.delete_user", ...}
  • {"op":"admin.set_password", ...}
  • {"op":"admin.set_permissions", ...}

These would require that the calling connection be associated with a user having admin permission. The internal security.Manager already supports:

  • CreateUser(username, password, perms)
  • DeleteUser(username)
  • SetUserPassword(username, newPassword)
  • SetUserPermissions(username, perms)

If you would like a fully wired admin protocol interface, it can be added on top of the existing security manager with minimal changes.


Example Clients

Minimal Go client snippet

conn, err := net.Dial("tcp", "127.0.0.1:8080")
if err != nil {
    log.Fatal(err)
}
defer conn.Close()

w := bufio.NewWriter(conn)
r := bufio.NewReader(conn)

// Optional: auth
fmt.Fprintln(w, `{"op":"auth","user":"chatuser","pass":"secret3"}`)
w.Flush()
line, _ := r.ReadString('\n')
fmt.Println("auth response:", line)

// Subscribe
fmt.Fprintln(w, `{"op":"sub","topic":"chat.room1"}`)
w.Flush()

line, _ = r.ReadString('\n')
fmt.Println("sub response:", line)

// Read messages
for {
    msg, err := r.ReadString('\n')
    if err != nil {
        break
    }
    fmt.Println("msg:", msg)
}

Notes on Performance and Concurrency

  • Memory-only:
    • No disk I/O or persistence paths.
    • Topics and user registry live fully in memory.
  • Concurrency model:
    • One goroutine per client connection.
    • A single sync.RWMutex protects the topic registry:
      • Readers for publishing (copy subscriber set).
      • Writers for subscribe/unsubscribe operations.
    • Security manager uses its own sync.RWMutex for user data.
  • Minimized allocations:
    • Permission checks operate on simple strings.
    • Topic subscriber sets are map[*Client]struct{} for efficient presence checks.
  • Security checks:
    • Per-message permission check is just a few string comparisons.
    • Heavy cryptography only happens during authentication (password hashing).
    • Password verification uses constant-time comparison for hashes.

Error Handling

  • Malformed JSON:
    • Server replies with {"ok":false,"error":"invalid_json"} and may close the connection.
  • Unknown operations:
    • Server replies with {"ok":false,"error":"unknown_op"}.
  • Unauthorized or forbidden actions:
    • Server replies with {"ok":false,"error":"permission_denied"}.
  • Missing required fields (e.g. topic):
    • Server replies with {"ok":false,"error":"missing_topic"} or similar.

The server is designed so that malformed or malicious client input does not cause a crash. Each client is handled in isolation, and errors are logged and returned as structured responses.


Future Extensions

Without violating the current goals and non-goals, you can extend:

  • Admin protocol:
    • Safe, authenticated operations to manage users and permissions.
  • Channel-based per-client writer:
    • To guarantee ordered, non-interleaved message delivery even under extreme concurrency.
  • Metrics / observability:
    • Simple counters for topics, connections, and error rates.

No changes to the core protocol are required for basic usage as described.


About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages