Setup: This file is the single, version-controlled source of agent instructions. Claude Code reads
CLAUDE.md, which is git-ignored on purpose — symlink it to this file after cloning. See section 8.
- Assigned Role: Technical assistant operating under the strict guidelines of a Cloud Solution Architect and Tech Lead PO.
- Tone and Style: Concise, direct, and rigorously professional.
- Strict Accuracy (Zero Hallucinations): If the source code, tests, or documentation lack specific details, explicitly state the missing information. Do not assume or invent paths, variables, or logic.
- Design Approach: Prioritize cloud-native architectural decisions, distributed resilience, low-latency edge processing, and adherence to ETSI/5GAA industry standards.
InstantX (InstantX) is an LF Edge / Vodafone Business edge-cloud platform for real-time, location-addressed data exchange, focusing on V2X (Vehicle-to-Everything) C-ITS messaging.
It is a deployment-and-integration repository: a docker-compose stack of off-the-shelf brokers and observability tools, glued together by first-party code (Python services + scripts + a NiFi flow).
- Core Mechanism: Messages are addressed by geohash so subscribers receive only data for their location and radius.
- Transport & Routing: MQTT is the edge transport; Kafka is the internal backbone; NiFi is the transformation/integration layer.
- Primary Directories:
deployment/(infrastructure and code),docs/(conceptual reference).
Understanding the system requires tracing a message end-to-end:
- Ingress (Event Publisher): A Flask API (
deployment/eventPublisher/EventPublisher.py). Receives a V2X JSON body, UPER-encodes it viaasn1tools, and produces it to Kafka topicv2x.denm.public. The geohash is exploded into an MQTT-style key (v2x/<sub_service>/<group>/g<level>/<g/e/o/h/a/s/h>) and set as the Kafka message key. - Transport Bridge (Kafka Connect): Custom MQTT Source/Sink connectors synchronize messages bidirectionally between MQTT and Kafka without transforming the payload. They translate the MQTT geohash topic structure to the flat Kafka topic name, preserving the geohash path as the Kafka key.
- Transformation (Apache NiFi): Consumes from external systems (e.g., AMQP/RabbitMQ), transforms, and re-publishes. Key logic is in
deployment/nifi/nifi-scripts/src/encoder_decoder.py(reads XML on stdin, normalizes types, UPER-encodes, writes hex to stdout). - Egress (MQTT broker - HiveMQ CE): Subscribers use geohash wildcards on the topic tree to receive local messages.
- MQTT topic:
{service}/{subService}/{subServiceGroup}/g{level}/{geohash char-by-char}(e.g.,v2x/denm/public/g8/7/y/0/1/9/1/k/4). - Kafka topic: Dotted, geohash-free (e.g.,
v2x.denm.public). The full geohash topic path travels exclusively as the Kafka key.
Messages follow ETSI C-ITS standards encoded with UPER (Unaligned Packed Encoding Rules) from ASN.1 schemas.
- Multi-part Encoding Warning: A full
DenmEtsimessage is NOT encoded in one call in NiFi.encoder_decoder.pyencodes three parts separately (GeoNetworking header, BTP-B header, inner DENM), computes thepayloadLength, and concatenates them. The Event Publisher uses a simpler single-call path; do not assume they encode identically.
All commands run from deployment/ unless noted.
docker-compose up -d
docker-compose up --build -d
docker-compose down
Managed via Poetry in deployment/nifi/nifi-scripts:
poetry install
poetry run pytest
cd deployment/eventPublisher
pip install -r requirements.txt
python EventPublisher.py
When modifying code or configurations, enforce the following constraints:
- Duplicated ASN.1 Schemas: Schemas exist in both
deployment/eventPublisher/asn/anddeployment/nifi/asn/. If you modify a schema, update both locations. - Test Environment Paths:
test_main_function_with_valid_inputin the NiFi tests resolvesDATA_FOLDERrelative to the test file (../../asn). Keep it relative — do not reintroduce machine-specific absolute paths. - NiFi Flow Bootstrapping: The flow is bootstrapped by
nifi-setupvianifi-init.sh, pullingflow.jsonfrom the Registry. UI edits do not update the committedflow.json. - Vendored Binaries: Custom NARs and connector JARs are committed as binaries. Their source code lives in sibling repositories (
instantx-connectors,instantx-metrics). - AMQP & Networks: External AMQP (e.g., RabbitMQ) is wired via NiFi Parameter Context. Connect external brokers to the
deployment_nifi_networkDocker network. - Zookeeper vs KRaft: Kafka runs in KRaft mode. The existing Zookeeper service in
docker-composeis strictly for NiFi's cluster coordination; do not conflate them.
- Workflow: Fork → feature branch → PR against
main. - Versioning: Semantic Versioning (SemVer). Record user-facing changes in
CHANGELOG.md(Keep a Changelog format) andRELEASE.md. - Standards: Maintain clean commit histories, strict license headers (First-party code is MIT), and adhere to
CONTRIBUTING.md.
-
Single source of truth:
AGENTS.md(this file) is the canonical, committed agent guide. Do not maintain a separateCLAUDE.mdwith its own content — it drifts. -
Why
CLAUDE.mdis git-ignored: Claude Code looks forCLAUDE.md, but committing it would duplicateAGENTS.md..gitignoreexcludesCLAUDE.md(andCLAUDE.local.md); each developer links it toAGENTS.mdlocally so Claude Code reads the same instructions every other agent uses. -
One-time setup (run from repo root after cloning):
macOS / Linux:
ln -s AGENTS.md CLAUDE.md
Windows — PowerShell (Developer Mode on, or run as Administrator):
New-Item -ItemType SymbolicLink -Path CLAUDE.md -Target AGENTS.md
Windows — cmd.exe (run as Administrator):
mklink CLAUDE.md AGENTS.md -
Result: Edit
AGENTS.mdonly;CLAUDE.mdfollows automatically. The symlink is local-only and never committed (it matches the.gitignoreentry). -
CLAUDE.local.md: Reserved for per-developer overrides that must never be shared — also git-ignored. Do not put project-wide guidance there.