← Home
ConnectX logo

ConnectX — Decentralized P2P Mesh Networking Framework

Early Development Open Source Java v0.6.3-SNAPSHOT

A decentralized P2P mesh network framework with end-to-end PGP encryption, blockchain-based event persistence, a fluent Java API, and CXApps: a human-facing application layer where identity, permissions, and logic live on the network.
Built for managed decentralized networks that take security seriously.

// Spin up a peer - 4 lines
ConnectX peer = new ConnectX("CX-PEER1", 49153, uuid, "Peer1");
peer.updateHTTPBridgePort(8081);
peer.setPublicBridgeAddress("cxHTTP1", "https://cx1.anvildevelopment.us/cx");
peer.connect(49153);

// Send a typed, signed message
peer.buildEvent(EventType.MESSAGE, new CXMessage("Hello network!"))
    .toPeer(targetID).signData().queue();

// Receive with verified sender identity
peer.addPlugin(new CXMessagePlugin() {
    public void onMessage(String senderID, CXMessage msg) {
        System.out.println(senderID + ": " + msg.text);
    }
});

Latest Build - 0.6.3-SNAPSHOT

Upgrade recommended. This build completes a scoped internal security audit and tightens administrative authorization across the c1 admin handlers, alongside dispatcher and codec work. See CXApp Dispatcher & Security Hardening for details.

ConnectX-0.6.3-20260925.215638-1.jar  ·  published 2026-09-25

Add to Your Project

Available via the Anvil Development Maven repository. Snapshots are enabled.

// Maven
<repository>
  <id>AnvilDevelopment</id>
  <url>https://repo.anvildevelopment.us/repository/maven-public/</url>
  <snapshots><enabled>true</enabled></snapshots>
</repository>

<dependency>
  <groupId>us.anvildevelopment</groupId>
  <artifactId>ConnectX</artifactId>
  <version>0.6.3-SNAPSHOT</version>
</dependency>
// Gradle
repositories {
  maven { url 'https://repo.anvildevelopment.us/repository/maven-public/' }
}

dependencies {
  implementation 'us.anvildevelopment:ConnectX:0.6.3-SNAPSHOT'
}

Prefer the JAR directly? See the download button above, or browse every published snapshot build in the repository.

What's Under the Hood

Fluent Event API

buildEvent().toPeer().signData().queue() - signing, routing, and queuing in a single chain. CXS for direct peer delivery, CXN for mesh broadcast. Failed CXS deliveries retry with exponential backoff and promote to CXN after threshold. toNetworkPeer() for explicit CXN routing.

PGP at Every Layer

Three-layer signing chain: transport hop signature (NetworkContainer), origin signature preserved through relays (NetworkEvent), and payload signing or E2E encryption (NetworkEvent.d). PGPainless default, fully pluggable via abstract CryptProvider.

HTTP Bridge

Jetty-based bridge punches through firewalls and NAT. No open port required on the connecting side. Bridge health is identity-checked before routing. Supports streamBridgeOnly for proxy-hidden nodes where exposing a direct IP defeats the point.

3-Chain Blockchain

Per-network blockchain: Admin (c1), Resources (c2), Events (c3). Hybrid consensus with EPOCH/NMI-trust and multi-peer voting for distributed agreement. Append-only - no committed state can be overwritten by any party.

Integration Keys (CXIK)

NMI issues Integration Keys to authorize network registration. CXIK binds node identity to network membership at the cryptographic level before participation is permitted. CXIKs can be revoked without disrupting the rest of the network.

Plugin System

CXPlugin / CXMessagePlugin intercept events by service name. Three data levels: raw NetworkEvent, full InputBundle with signed bytes and container, or deserialized typed object via DataLevel.OBJECT. Fully per-instance - multiple independent nodes in the same JVM.

CXApps

Human-facing app layer over the CX network. Server holds logic; client holds an HTML template. Field values travel over CX and are substituted locally - no raw HTML ever crosses the wire. Two render surfaces: CXNexus (JS disabled, secure) or Chrome extension (JS permitted, scripts bundled at install only). Session-isolated per tab.

Stream Sessions

Bidirectional encrypted channels via CXStreamPlugin. TCP mux via CXST header on the main P2P port, or WebSocket when an HTTP bridge is confirmed to route to the target. Receiver decides transport via identity-checked health probe. Initiator follows.

Typed Message Enforcement

MESSAGE payloads must be sent as CXMessage with .signData() or .encrypt(recipientID). Raw unsigned payloads are rejected at the receiver at the protocol level. Cannot be bypassed by a misbehaving peer.

LAN Discovery

Automatic peer discovery on startup via CXHELLO. Scans ports 49152-49162. Runs once on launch then on configurable backoff (30s / 60s / 10min steady-state). Values configurable via NodeConfig. Zero configuration for local mesh setup.

Human-Facing Applications on the Network

CXApps extend ConnectX beyond machine-to-machine messaging to serve users directly. A CXAppServer runs on the data-owning node. Fields annotated with @CXAppField and methods with @CXAppMethod are cached via reflection at registration. A CXAppClient runs on the user's local node and holds an HTML template. Field values travel over CX as signed events and are substituted into the template locally. No raw HTML ever crosses the wire. Field values from remote peers are HTML-escaped before substitution, so a compromised peer cannot inject markup or script.

Four operations are supported over the wire: READ (fetch current field values), WRITE (update a field), INVOKE (call a method), REFRESH (re-render with current permissions). All travel as APP_REQUEST / APP_RESPONSE events through the standard NodeMesh pipeline with full signing and verification at every hop. Field and method access is gated per-permission - REFRESH silently omits fields the caller lacks permission to read.

Two render surfaces, one security model. Apps with browserEnabled() returning false are restricted to CXNexus, which renders HTML with JavaScript disabled and runs the node in-process. This surface is for anything touching critical or authenticated data. Apps with browserEnabled() returning true (default) may render in Chrome via the extension. JavaScript is permitted, but scripts may only be loaded from files bundled at install time. Server-provided field values are never executed as script. The developer chooses the surface; the framework enforces the constraint.

Session isolation. Each browser tab receives an independent session token on first load. Multiple tabs for the same app are fully isolated even if they target different server peers. The internal loopback HTTP bridge is bound to 127.0.0.1 only with an additional isLoopback() check as defense-in-depth.

// Register server and client apps
connectX.registerApp(new MyAppServer());
connectX.registerApp(new MyAppClient());

// Start the loopback HTTP bridge for the Chrome extension
connectX.startAppServer(8079);

// Grant / revoke per-peer permissions
connectX.grantCXIDPermission(peerCXID, "admin", 100);
connectX.revokeCXIDPermission(peerCXID, "admin", 100);

Official CXApps published by Anvil Development are distributed on the CXApps page.

How ConnectX Differs from Existing Solutions

Most P2P frameworks make a choice: either prioritize anonymity, or prioritize developer ergonomics, or provide raw messaging primitives. ConnectX is built around a different requirement: managed organizational networks where administrators need real governance tooling, cryptographic accountability at every layer, auditable state, and a human-facing application surface, without depending on a central server.

vs. libp2p

libp2p is modular and well-suited for open decentralized systems. It has no built-in permission model, no governance layer, no event persistence, and no application layer. ConnectX adds per-network blockchains, weighted permission entries, NMI provisioning, CXIK-gated registration, and CXApps: a full human-facing application surface that libp2p has no equivalent for.

vs. ZeroMQ / Nanomsg

ZeroMQ is a messaging library: fast, transport-agnostic, no opinions on identity. There is no cryptographic identity, no peer authentication, no routing intelligence, and no application layer. ConnectX is not a messaging library. Every participant has a PGP identity, every message is signed, routing is governed by permission state, and CXApps lets you serve UI directly from node to node.

vs. Tor / I2P

Tor and I2P are built for anonymity: the threat model is hiding who is talking to whom. ConnectX's threat model is the opposite. Every participant is cryptographically identified, every action is attributable and auditable, and the NMI governance layer assumes you know exactly who is on the network. The two approaches serve fundamentally different use cases.

vs. Matrix / Synapse

Matrix federates between homeservers; clients trust their homeserver. ConnectX has no homeserver. Peers communicate directly, the blockchain is distributed across nodes, the NMI can be permanently removed via Zero Trust mode, and CXApps runs application logic on the node itself rather than on a server the user never controls. There is no trusted intermediary to compromise.

ConnectX is not a toolkit or a message bus. It is a complete governed network: PGP identity and cryptographic signing at every layer, weighted permission enforcement, blockchain-backed event persistence, stream sessions, and CXApps for human-facing UI served directly from node to node. Zero Trust mode permanently hands control to the network itself when you are ready.

Cryptographic Identity as the Trust Primitive

ConnectX makes cryptographic identity the sole basis for trust at the protocol level. Every message, event, and state transition is signed or encrypted by the originating peer before it touches the wire. This is not defense-in-depth. It is exploit-class elimination.

Traditional exploit vectors like use-after-free, buffer overflows, or data races that corrupt in-memory state cannot escalate into protocol-level attacks. If memory corruption mangles a message in transit, it does not become a privilege escalation. It becomes an invalid signature. The data is either authentically from who it claims to be from, or it gets rejected. There is no middle ground.

The protocol enforces this through a three-layer signature and encryption system: transport-level signing on every hop (NetworkContainer), message-level signing by the original sender (NetworkEvent), and payload-level encryption for application data. Any tampering at any layer breaks the signature chain and the data is dropped.

Security hardening is enforced at every import path. Nodes are not added to the mesh until after all signature checks pass - no provisional state is written to disk before verification. Keys are loaded into a cert cache only and rolled back on failure. Power-loss and file-corruption events generate a scoped recovery file; the affected path is locked from further writes until recovery is confirmed and the file is cleared.

Peer identities are cosigned at provisioning time: a node's identity is attested by the NMI's key, creating a verifiable chain from the network's root to every participant. Peers cannot impersonate each other even on the same network segment. The network remains truly decentralized - cosigning is attestation, not control. The underlying blockchain is append-only; no party, including the NMI, can write over or alter committed state. Every event is permanent once confirmed.

The entire attack surface collapses to one well-understood problem: key compromise. CXNet does not pretend to prevent that. No system can. What it does is eliminate every other path to network-level damage, then gives network owners the governance tools to manage that reality.

For real data networks, there is no way to determine whether an authenticated action was intended or not. If a node's key is compromised and the attacker sends valid signed messages, those are authentic as far as the network is concerned. Same way a stolen badge gets you through a door. The network cannot read minds. What it can guarantee is that nobody gets through the door without a badge, which is the part most systems actually fail at.

The same trust boundary every secure system relies on. CXNet just removes all the other ways to cheat.

Managed Decentralized Networks

ConnectX is built for networks that need real administration without a central server. The Network Master Identity (NMI) provisions nodes, assigns permissions through an embedded permissions framework, and issues Integration Keys (CXIK) to authorize network registration. CXIK binds a node's identity to its network membership at the cryptographic level before the node is permitted to participate. Nodes operate at equal authority within the permission model once admitted.

When the network is ready, the owner can activate Zero Trust mode. This is an irreversible decision that permanently locks the trust structure and removes even the NMI's ability to modify it. The network becomes fully decentralized by design, not by accident.

Networks can operate as open (anyone joins), whitelisted (registration required), or fully private (invitation-only, no public seed distribution). All configuration changes are recorded to the admin blockchain (c1), providing an immutable audit trail of every access policy change.

Typed, Signed Delivery

MESSAGE payloads are sent as CXMessage objects (text + timestamp, serialized as cxJSON1). Raw unsigned payloads are rejected at the receiver at the protocol level. There is no configuration option to disable this; a misbehaving peer cannot bypass it.

Delivery has two modes. Signed messages carry a cryptographic signature tied to the sender's PGP identity, so the recipient can verify exactly who sent it. E2E encrypted messages are encrypted to the recipient's key and signed by the sender. Both paths go through the same five-stage pipeline and produce the same guarantees about origin authenticity.

Plugin sender identity. The CXPlugin interface exposes handleEvent(Object data, String senderCxID) at all three data levels. The sender cxID is resolved from ne.p.oCXID (the origin field, which survives relay) with fallback to the direct container sender. Plugins that only implement the single-arg form are unaffected. CXMessagePlugin.onMessage(String senderID, CXMessage message) delivers both the typed object and the verified origin identity in a single callback.

The network join API lets nodes discover and join non-CXNET networks without NMI-level bootstrap. joinNetworkFromPeers(networkID) sends a SEED_REQUEST to EPOCH first (authoritative), then to all HV peers. Seed.fetchOfficial() tries the peer network first, then falls back to the HTTPS bootstrap file. The public API also exposes getNetworks() and getNetworkIDs() for runtime inspection of a node's current network membership.

Cosigned Network Blobs

A network's definition travels as a cosigned blob: an inner signature by the network's own NMI, wrapped in an outer cosignature from EPOCH. Because both layers verify independently, the blob proves itself. The identity of whichever peer happened to forward it carries no weight, so any peer holding a stored copy can serve a join, the network's own NMI included but not required.

That property is what makes seeding work without a central distributor. A responder attaches its stored cosigned.cxnb to the seed response, and the receiver verifies both signature layers and rejects any blob whose network ID is not the one it asked for before registering anything.

0.6.1 was a trust-chain hardening release. Verification of the inner and outer layers had been sharing a single key set, collapsing the plane separation the two layers exist to provide. In that state EPOCH could sign a seed for any network and have it accepted, and NETEPOCH held enough reach to re-declare itself as an independent network. The layers are now verified separately against their own key sets, with the subject network's backend set checked in depth.

Cosigned blobs also no longer override state already on disk. Historical data is authoritative over new network input, which is what the design always specified; the implementation had been reading identity and network membership out of inbound blobs even for networks it already held.

0.6.2 removed the peer-count vote from the join path. A network previously could not be joined unless three distinct peers answered the seed request, which meant a small network could never be joined at all: the tally sat below threshold indefinitely with no timeout. Since a cosigned blob is self-proving, a verified response is now applied on sight. Consensus is unchanged and still handles every response that fails verification or arrives without a blob. Nothing is trusted that was not trusted before; the vote is skipped only where the signature chain is the stronger guarantee.

EventType has declared ttlMs, maxPayloadBytes and maxRetries for some time, but the retry queue ignored them in favour of a flat 50-attempt ceiling with exponential backoff, so a request could be retransmitted for hours after it stopped being relevant. Retry bundles now resolve their type's real limits once at construction and expire on TTL as well as attempt count. A SEED_REQUEST honours its 60-second TTL and drops in about a minute, letting the join logic issue a fresh one instead of the mesh carrying a stale broadcast.

CXApp Dispatcher, Security Hardening & Administrative Authorization

Upgrade recommended. This 0.6.3-SNAPSHOT build completes a scoped internal security audit (39 files / 7,557 lines) and tightens administrative authorization across the c1 admin handlers, alongside the dispatcher and codec work below. See the download above.

Handler dispatch off the EventProcessor. CXAppServer.handle() previously ran inline on the single mesh thread, so a slow app handler could delay other event processing on the node. CXAppDispatcher adds a bounded pool with one lane per appID: apps run concurrently, while each app's own requests stay ordered. Parsing and app lookup stay on the EventProcessor; only the handler call moved.

Error codes and enumeration defence. Refusal responses have been consolidated to a single FORBIDDEN code rather than distinguishing unknown field, unreadable, unwritable, and denied cases, closing off a way to infer an app's structure by comparing replies. .debug re-opens detail without granting access.

Field value encoding. stringify used String.valueOf while coerce read cxJSON1, so a Map went out as {a=b} and came back as an unparseable success. The client had no cxJSON1 branch at all and silently applied null. Both are fixed and consolidated into CXAppCodec so they cannot drift apart again.

In-process calling API. CXApps could previously only be reached from a browser. ConnectX.sendAppRequest plus read/write/invoke/refresh now return CompletableFuture, completed on a dispatcher lane so caller callbacks never land on the EventProcessor. ttlMs added to both annotations.

Inherited members and arity. buildCache only saw the concrete class, so a shared base app's members were missed. It now walks the class hierarchy. INVOKE requires exact arity instead of null-padding.

Audit findings addressed

Also corrected: registerPeerHint now writes as intended (a validation check had been silently blocking it); confirmed escapeAttr correctly escapes quotes.

Administrative authorization

The six c1 admin handlers (GRANT_PERMISSION, BLOCK_NODE, UNBLOCK_NODE, REGISTER_NODE, and related paths) now go through an explicit authorization check before applying changes, closing a gap where these actions could previously be processed without one.

CXNetwork.checkAdministrativeAuthority now requires the target network's NMI, backend set, or the action's permission - never CXNET's. Zero Trust activation fully demotes the NMI. Permission already declared BlockNode/UnblockNode/RegisterNode, and enforcement is now wired up to match.

All six handlers now authorize strictly on verified origin (oCXID), removing a transmitter-based fallback that didn't require direct authorship of the event. ZERO_TRUST_ACTIVATION - an irreversible operation - now checks the correct authority field.

Verification. 43/43 tests across 3 CXApp classes, build succeeded. Bootstrap run clean (covers the Jackson allowlist narrowing, seed consensus, IOThread). Docs: CX-PROTOCOL.md CXApps section rewritten; CHANGELOG has 7 new sections.

Bidirectional Encrypted Channels

CXStreamPlugin provides full bidirectional stream sessions between peers. Open a session with openStream(targetCxID, localHost), accept with acceptStream(session), write with session.write(data), and close with session.close(cx). Sessions run over the same cryptographic pipeline as all other ConnectX traffic.

Transport is negotiated automatically. TCP mux is the default: stream frames are multiplexed on the existing P2P port via a CXST header, so no additional port is needed. When both peers have a working HTTP bridge, the receiver probes its own health endpoint and verifies the response identity matches its own node ID before advertising WebSocket. If the external URL routes to a different server, it falls back to TCP. The initiator follows whatever transport the receiver advertises in ACCEPT. NodeConfig.streamBridgeOnly = true disables TCP for nodes behind reverse proxies where exposing a direct IP defeats the point.

// Open a stream to a peer
CXStreamSession session = peer.openStream(targetCxID, "localhost");
session.write("payload".getBytes());
session.close(peer);

// Accept incoming streams
peer.addPlugin(new CXStreamPlugin() {
    public void onStream(CXStreamSession session) {
        peer.acceptStream(session);
        byte[] data = session.read();
    }
});

Network Topology

CXNET (Global Bootstrap Network) |-- CXNetwork (e.g. "TESTNET", "MyApp") |-- NMI Network Master Identity - creates/controls the network |-- Backend nodes - trusted infrastructure, priority routing |-- Peer nodes - regular participants Each node runs: |-- NodeMesh peer connections, event routing, PeerDirectory |-- CXNetwork(s) logical networks with independent blockchains |-- CryptProvider PGP key management and signing |-- HTTP Bridge Jetty servlet for internet-reachable peers |-- Plugin Registry application-level event handlers |-- App Registry CXApp server and client instances

Threading Model: Five-Stage Pipeline

ConnectX distributes I/O and cryptographic work across five dedicated stages. Ingress and egress each run independent thread pools so neither direction can stall the other. State transitions are serialized through a single-threaded processor. No locks required for correctness.

Stage 1 SocketWatcher 1 thread Accepts TCP connections, reads 8192-byte chunks, rejects blacklisted IPs, wraps data into NetworkInputIOJob, enqueues. Stage 2 IOThread Pool 4 threads Strip + verify NetworkContainer signature (Layer 1). Verify NetworkEvent signature (Layer 2). Duplicate detection, unknown-sender policy. Produce InputBundle. Stage 3 EventProcessor 1 thread Decryption, permission checks, event routing. Single-threaded by design: serializes all state transitions and eliminates race conditions without explicit locking. Stage 4 OutputProcessor Pool 4 threads Signs outbound events, transmits to connected nodes. Failed bundles move to retry queue. Offline nodes never block the output path. Stage 5 RetryProcessor 1 thread Exponential backoff retry. Falls back from CXS (direct) to CXN (mesh broadcast) with end-to-end encryption after repeated failure. Discovery events use signed-only CXN broadcast - not E2E - since they carry public keys.

CPU-heavy cryptographic operations scale across cores in stages 2 and 4. The single EventProcessor in stage 3 guarantees atomic state without synchronization overhead. No single slow operation blocks a parallel path.

Test Coverage

Baseline report from 2026-03-24. Coverage has grown since - stream sessions, CXApps (19 unit tests), CXIK, and a full JUnit 5 MultiPeerTest suite (E2E encryption, permission enforcement, spoofed-sender rejection, signed/unsigned delivery) were all added after this snapshot. Core networking, cryptography, and threading paths are fully exercised. Subsystems not yet implemented are at 0% by design.

62.5%
Class
46.6%
Method
44.3%
Line
Package Class Method Line Notes
network.threads100%100%80%Full pipeline thread coverage
network.events92%83%87%All typed event classes exercised
network.nodemesh92%72%57%Core mesh, peer directory, retry logic
crypt.pgpainless100%83%62%Sign, verify, encrypt paths covered
network (core)75%50%48%CXNetwork, InputBundle, CXPath
io83%56%47%Serialization and I/O paths
us.anvildevelopment.cxnet80%50%54%ConnectX API, EventBuilder
app0%0%0%CXApps - added after this snapshot
analytics0%0%0%Not yet tested
api0%0%0%Plugin interfaces, exercised indirectly
network.remotedirectory0%0%0%Not implemented
View Source on GitHub CXNexus Desktop GUI Official CXApps Join Discord