feat(lora-ingest): ChirpStack MQTT subscriber + krobjob relay service#2
feat(lora-ingest): ChirpStack MQTT subscriber + krobjob relay service#2Runeov wants to merge 2 commits into
Conversation
New Node.js/TypeScript service in lora-ingest/: - Subscribes to ChirpStack application MQTT uplinks - Decrypts AES-256-GCM app-layer payload (matches lora_node.py encoder) - Routes fPort 1 (sale, 7B) and fPort 2 (heartbeat, 3B) - Signs relay POST with HMAC-SHA256 and forwards to krobjob ingest API TypeScript clean, mqtt@5, zero extra runtime dependencies. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughA new ChangesLoRa Ingest Service
Sequence Diagram(s)sequenceDiagram
participant ChirpStack as ChirpStack MQTT Broker
participant index as index.ts (MQTT client)
participant decoder as decoder.ts
participant relay as relay.ts
participant ingest as KROBJOB_INGEST_URL
ChirpStack->>index: MQTT uplink message (JSON with fPort, data)
index->>index: JSON parse + required-field guard
index->>decoder: decryptPayload(data: base64)
decoder-->>index: plaintext Buffer or null
index->>decoder: decodeEvent(fPort, plaintext)
decoder-->>index: DecodedEvent or null
index->>relay: relayWithRetry(DecodedEvent + rssi/snr/gatewayEui/timestamp)
relay->>relay: HMAC-SHA256 sign JSON body (BASEFLOW_HMAC_KEY)
relay->>ingest: POST /ingest with X-Baseflow-Signature
ingest-->>relay: HTTP response
relay-->>index: resolve or throw on non-OK
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@lora-ingest/src/decoder.ts`:
- Around line 30-45: The payload length validation in the fPort decoding logic
uses >= operators instead of exact equality checks, which allows
trailing/malformed data to pass validation. Replace the >= operators with ===
operators in both the fPort === 1 and fPort === 2 conditions to enforce strict
fixed-width validation. The sale event handler should check plaintext.length ===
7 (not >=), and the heartbeat event handler should check plaintext.length === 3
(not >=) to reject payloads with unexpected extra bytes.
- Line 3: The APP_ENC_KEY initialization needs to validate the APP_ENC_KEY_HEX
environment variable at startup to catch configuration errors early. Add
validation to check that the environment variable is present, contains valid
hexadecimal characters, and decodes to exactly 32 bytes. If any validation
fails, throw an error or exit the process immediately with a clear error
message. This should be done before or during the assignment to APP_ENC_KEY to
prevent silent decrypt failures downstream that would be difficult to diagnose.
In `@lora-ingest/src/index.ts`:
- Around line 47-57: The relay() function call in the try-catch block currently
logs failures and discards the event without retrying, causing permanent data
loss during transient HTTP failures. Replace the direct relay() call with a
retry wrapper function that implements bounded retry logic with exponential or
linear backoff between attempts, limiting retries to a reasonable number (e.g.,
3-5 attempts) with increasing delays between each attempt, and only log and
discard the event if all retry attempts are exhausted.
- Around line 5-8: The non-null assertions on CHIRPSTACK_MQTT_URL and
CHIRPSTACK_APPLICATION_ID environment variables mask missing configuration
errors. Before creating the MQTT client connection with mqtt.connect, add
explicit validation checks for both CHIRPSTACK_MQTT_URL and
CHIRPSTACK_APPLICATION_ID to ensure they exist, throwing a descriptive error if
either is undefined or empty. This validation should occur early in the
bootstrap sequence, before the mqtt.connect call is attempted, so configuration
issues are caught immediately rather than causing unexpected runtime behavior.
In `@lora-ingest/src/relay.ts`:
- Around line 4-6: Add validation logic immediately after the KROBJOB_INGEST_URL
and BASEFLOW_HMAC_KEY constant declarations to ensure both environment variables
are present and non-empty. Additionally, validate that KROBJOB_INGEST_URL is a
properly formatted URL by attempting to parse it with the URL constructor. If
either variable is missing, empty, or if URL parsing fails, throw an error with
a descriptive message to fail fast at module initialization rather than silently
failing during runtime relay operations.
- Around line 18-25: The fetch call to KROBJOB_INGEST_URL in the relay operation
lacks a request timeout, causing requests to hang for up to 300 seconds by
default which can lead to resource exhaustion during outages. Add an AbortSignal
with a 10-second timeout to the fetch options by including a signal property set
to AbortSignal.timeout(10_000) in the fetch configuration object alongside the
existing method, headers, and body properties.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 1c896a9a-3520-46e3-8eb9-8e269da073e0
⛔ Files ignored due to path filters (1)
lora-ingest/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (6)
lora-ingest/.env.examplelora-ingest/package.jsonlora-ingest/src/decoder.tslora-ingest/src/index.tslora-ingest/src/relay.tslora-ingest/tsconfig.json
decoder.ts: requireHexKey validates APP_ENC_KEY_HEX at boot (present, hex-only, exactly 32 bytes); payload length checks changed >= to === for strict fixed-width protocol enforcement. relay.ts: requireEnv + URL constructor validate KROBJOB_INGEST_URL and BASEFLOW_HMAC_KEY at startup; AbortSignal.timeout(10_000) prevents 300-second default hang on outbound fetch. index.ts: requireEnv validates CHIRPSTACK_MQTT_URL and CHIRPSTACK_APPLICATION_ID before connect; relayWithRetry wraps relay() with 3 attempts + exponential backoff (250ms, 500ms) to survive transient HTTP failures without permanent uplink loss. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Parking this — superseded, not merging. The N100/ChirpStack host this relay targeted is gone, and the LoRa layer was re-scoped (2026-06-17) from a bespoke LoRaWAN+ChirpStack telemetry pipeline to a Meshtastic coordination layer (compute centralized into one solar/compute hub). Branch |
Summary
Test plan
Dependencies
Generated with Claude Code
Summary by CodeRabbit