feat(events): add signed event firmware OTA endpoint - #110
Conversation
📝 WalkthroughWalkthroughAdds event firmware OTA contract data, strict validation, Ed25519 signing, an edition-based HTTP endpoint, environment configuration, tests, and CI execution for the new test script. ChangesEvent firmware OTA
Estimated code review effort: 3 (Moderate) | ~25 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
tests/eventFirmwareOTA.test.ts (1)
55-65: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winAssert the exact payload bytes and returned key ID.
This test checks decoded JSON equality and signature validity, but a regression that changes serialization or drops the key ID would still pass. Assert both protocol fields explicitly.
Proposed test additions
const payload = Buffer.from(envelope.payload, "base64"); +assert.equal(envelope.keyId, "event-release-2026"); +assert.equal(payload.toString("utf8"), JSON.stringify(contract)); assert.deepEqual(JSON.parse(payload.toString()), contract);🤖 Prompt for 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. In `@tests/eventFirmwareOTA.test.ts` around lines 55 - 65, Update the test around verifySignature to assert that the decoded envelope payload bytes exactly match the expected serialized contract, rather than only comparing parsed JSON, and assert the returned key ID explicitly instead of checking only a boolean signature result. Preserve the existing base64 decoding and signature verification inputs.package.json (1)
11-12: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winMake test discovery shell-independent.
The unquoted
tests/**/*.test.tspattern can be expanded differently by the shell and may omit direct test files when nested test directories are added. Prefertsx --testor quote the glob.tsxdelegates to Node’s test runner, whose documentation recommends quoting command-line globs;tsx --testalso auto-discovers TypeScript test files. (tsx.is)🤖 Prompt for 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. In `@package.json` around lines 11 - 12, Update the package.json test script to make test discovery shell-independent by relying on tsx --test auto-discovery or by quoting the tests/**/*.test.ts glob. Preserve execution of both direct and nested TypeScript test files.
🤖 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 `@src/lib/eventFirmwareOTA.ts`:
- Around line 195-197: Update the dataset-loading validation around
validateEventFirmwareOTAContract in the cached.contracts loop to track contract
editions and reject duplicate editions, including duplicate valid DEFCON
contracts, before endpoint selection can use the data. Preserve validation of
each contract while raising an error for any repeated edition.
- Around line 159-172: Update the timestamp validation in the validity-window
logic around ISO8601_RE and Date.parse to reject normalized calendar dates:
after parsing each timestamp, compare new Date(value).toISOString() with its
original value, and call fail when either comparison differs. Preserve the
existing finite-value and expiresAt-after-issuedAt checks.
In `@src/routes/eventFirmwareOTA.ts`:
- Around line 19-26: Update the catch handling in the eventFirmwareOTA route
around signEventFirmwareOTAContract to return HTTP 503 instead of 502 for local
signing configuration, key-type validation, or signing failures. Preserve the
existing error logging and JSON success response.
---
Nitpick comments:
In `@package.json`:
- Around line 11-12: Update the package.json test script to make test discovery
shell-independent by relying on tsx --test auto-discovery or by quoting the
tests/**/*.test.ts glob. Preserve execution of both direct and nested TypeScript
test files.
In `@tests/eventFirmwareOTA.test.ts`:
- Around line 55-65: Update the test around verifySignature to assert that the
decoded envelope payload bytes exactly match the expected serialized contract,
rather than only comparing parsed JSON, and assert the returned key ID
explicitly instead of checking only a boolean signature result. Preserve the
existing base64 decoding and signature verification inputs.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: c5b677df-1f16-40f7-b299-24e0db4b2765
📒 Files selected for processing (9)
.env.example.github/workflows/ci.ymldata/eventFirmwareOTA.jsonpackage.jsonsrc/index.tssrc/lib/eventFirmwareOTA.tssrc/routes/eventFirmwareOTA.tssrc/routes/index.tstests/eventFirmwareOTA.test.ts
|
@coderabbitai review |
✅ Action performedReview finished.
|
Status
Warning
Currently untested with a physical event-firmware OTA round trip. This endpoint is fail-closed and returns
503until Meshtastic configures a project-owned Ed25519 signing key. The listed DEF CON target must complete hardware validation before that secret is enabled.Summary
GET /resource/eventFirmware/:edition/otafor per-edition signed OTA contracts.keyId, base64 payload, and base64 signature.404for unknown editions,502for invalid release data, and503when signing infrastructure is unavailable.Why
The display manifest is not an authorization boundary for executable firmware. Apple and future clients need an independently signed contract that selects one exact device artifact, verifies it before OTA, and carries an explicit standard-firmware return image.
Validation
pnpm test: 10 tests passedpnpm build: passedpnpm biome cion every changed source/config file: passedjq empty data/eventFirmwareOTA.json: passedqualityandbuild: passedThe repository-wide Biome run still reports two pre-existing warnings in
src/lib/mqtt.tsandsrc/services/gateway.ts; this PR does not touch them.Dependencies
Deployment Notes
Before enabling this endpoint in production:
EVENT_FIRMWARE_SIGNING_KEY_IDandEVENT_FIRMWARE_SIGNING_PRIVATE_KEY_PEM.nRF artifacts are intentionally absent. The current Apple app cannot prove the installed nRF bootloader version, so those devices must continue to use the web flasher.