Network Tap — zeq-observer-tap.py
The Network Tap form factor of the Observer Agent observes the host itself. While Web JS, Python, and Embedded C agents observe the application running on top of an OS, the Tap agent observes the OS — interface state, listening ports, established connections, bytes-deltas per connection.
It is 12 KB, has one dependency (psutil), and runs as a long-
lived daemon. Every observation it produces is privacy-first: IP
addresses are SHA-256-hashed at the source so the row stored on the
chain carries forensic posture without ever revealing who talked to
whom.
Install + run
curl -O https://zeqapi.com/zeq-observer-tap.py
pip install psutil
python zeq-observer-tap.py \
--slug zeq07792026349 \
--key zsm_live_2c5e12b5b3f1ad99… \
--encrypt
Or as a systemd unit:
[Unit]
Description=Zeq Network Tap Observer
After=network-online.target
[Service]
ExecStart=/usr/bin/python /opt/zeq/zeq-observer-tap.py \
--slug %ZEQ_SLUG% --key %ZEQ_SM_KEY% --encrypt
Restart=on-failure
User=zeq-observer
[Install]
WantedBy=multi-user.target
The daemon is fire-and-forget; under normal operation it produces a steady cadence of typed rows with low cardinality, so the entangled state stays readable.
What it observes
The Tap agent emits five typed observations. None of them carry plaintext IPs, hostnames, or process arguments — only structural posture and SHA-256 digests.
type=interface.change
Fires when an interface comes up, goes down, or changes its IPv4/IPv6 configuration. The SOC 2 CC 7.2 anomaly-detection control reads this row directly.
{
"type": "interface.change",
"payload": {
"observation": "interface-up",
"state_hash": "<sha256 of {iface, mtu, addrs}>",
"meta": { "iface": "eth0", "mtu": 1500, "addr_count": 2 }
}
}
type=ports.snapshot
Every 8 zeqonds, a snapshot of every listening socket. The audit-log row carries the count, the SHA-256 of the sorted port list, and the top three ports by activity. Auditors for NIST SP 800-53 AU-12 get exactly the boundary surface they ask for, with no plaintext leak of which ports are open.
type=connection.established
Fires when psutil.net_connections() shows a state transition
SYN_SENT → ESTABLISHED or a fresh ESTABLISHED not previously
seen. Body:
{
"type": "connection.established",
"payload": {
"observation": "outbound-tcp",
"state_hash": "<sha256 of {local_port, hash(remote_ip), remote_port}>",
"meta": {
"local_port": 54321,
"remote_hash": "5b8f2ca8…", // SHA-256 of remote IP
"remote_port": 443,
"process_hash": "ad1f9c…" // SHA-256 of (pid, exe)
}
}
}
The entangled state row tells an auditor that the host opened a TLS connection to a stable remote-hash on port 443. It does not say which IP. Anyone with the original IP can re-hash and check membership; the chain itself does not leak the network graph.
type=bytes.delta
Every 16 zeqonds, the bytes_sent / bytes_recv delta per interface.
Lets a SOC 2 reviewer correlate exfil-shaped curves to specific
zeqonds.
type=heartbeat
Same shape as every other form factor. Carries the daemon's outbox depth, last event zeqond, and the five HF signals.
Privacy model — three guarantees
- No plaintext IPs leave the host. Every observation that
references a network peer carries
sha256(ip)only. The salt defaults to the state-machine machine, so two different chains hashing the same IP produce different digests — the chains do not correlate. - No process arguments. Process identity is
sha256(pid + exe_path). A malicious row reader cannot learn what command line the daemon saw. - No payload data. The Tap agent observes connection state, not content. It never reads packet bodies, never inspects request URLs, never logs hostnames.
These three are why the Tap agent satisfies GDPR Art. 30 data minimisation out of the box — the digest fields can be stored indefinitely without classifying the entangled state row as personal data.
Use cases — three regulatory wins
SOC 2 — CC 7.2 anomaly detection
Every interface change, port snapshot, and connection establishment becomes a hash-linked row. The entangled state is a tamper-evident anomaly-detection log. SOC 2 auditors get a single artefact (an HZC archive) and can replay any time window offline.
NIST SP 800-53 — AU-12 audit generation
The agent's typed rows are precisely the events AU-12 requires. The ZeqCompliance v1 envelope returned by the server-side compute call carries the AU-12 boolean directly.
FedRAMP Moderate boundary monitoring
Drop the Tap agent on every authorised host. Every one of them posts into the same state machine. The resulting chain is the FedRAMP boundary-monitoring evidence file — privacy-preserving (no PII), tamper- evident (R1 + R2 + R3), portable across substrates.
Resource footprint
The daemon runs in a single process, ~30 MB RSS, no child threads
beyond the heartbeat ticker shared with zeq-observer-client.py.
On a 16-vCPU server with 200 active connections the daemon emits
roughly 60 typed rows per minute under steady-state. The entangled state
absorbs that easily; the bandwidth cost is ~5 KB/min.
File map
apps/zeq-dev/public/zeq-observer-tap.py— the daemonapps/zeq-dev/public/zeq-observer-client.py— sharedZeqObserverclassshared/api-core/src/routes/chain.ts— receivershared/api-core/src/lib/compliance.ts— SOC 2 / NIST AU-12 booleans