Adam Shiervani 988a07d418 Release dev → main (#60)
* feat(sync-releases): show artifact details, verify GPG, allow custom rollout (#58)

* feat(sync-releases): show artifact details, verify GPG, allow custom rollout

The previous production prompt was a single y/N with no artifact context, no
way to override the hardcoded 10% rollout, and no signature verification. An
operator confirming a release this way had to trust that the right files were
in S3 and that the .sig was issued by the OTA root key — neither was visible.

Changes:
* Print full artifact summary before the prompt: URL, sha256, compatibleSkus,
  and signature status for each artifact.
* Verify each .sig file with gpg --status-fd=1 and check the primary key
  fingerprint against OTA_ROOT_KEY_FPR (mirrored from rv1106-system's
  release_r2.sh). Reports valid / wrong-root / invalid / missing-pubkey /
  gpg-unavailable / absent, with a loud WARNING line for wrong-root and
  invalid signatures so the operator cannot miss them.
* Print the latest already-synced release of the same type before the prompt
  so the operator can confirm this is the next expected version.
* Add an interactive rollout-percentage prompt with 10% default, validated to
  0-100, replacing the hardcoded 10.
* Add an `a`/`abort` answer alongside y/N so operators can stop a multi-
  release sync mid-run when they spot something wrong, instead of having to
  N through every remaining version.
* Print the DB target and bucket as the first line of main() so a wrong
  .env.production selection is obvious before any prompts fire.
* Print a final run summary with counters: created / skipped-by-user /
  already-synced / no-artifacts, plus an "aborted at <type> <version>" line
  when the run was cut short.
* Add `npm run sync-releases:production` script and ignore .env.production.

Verification path runs only when NODE_ENV=production, so non-prod runs and
the test suite never spawn gpg or download artifacts. All 52 existing tests
still pass; tsc build is clean.

* refactor: hoist objectKeyFromArtifactUrl into helpers

Both src/releases.ts and scripts/sync-releases.ts had their own copy of the
same URL-to-S3-key conversion. Moved into src/helpers.ts and imported from
both call sites so a future change (e.g. CDN path prefix handling) only needs
to land once.

* fix(sync-releases): only treat ERRSIG rc=9 as missing pubkey

GnuPG's ERRSIG line carries an `rc` reason code. rc=9 is the only one that
means "we don't have the signer's key" — rc=4 (unsupported algorithm) and
other codes are real verification failures. The previous implementation
collapsed every ERRSIG into noPubkey, which would have falsely told the
operator the OTA root key was missing when the actual problem was e.g. an
unsupported pubkey algorithm.

Now parses the rc field and surfaces non-9 ERRSIG codes as `invalid` with a
human reason (rc=4 → "unsupported algorithm", others → "gpg error code N").

* feat(releases): map recovery artifact filename per SKU (#59)

The system recovery endpoint hard-coded `update.img`, which is the
eMMC/RKDevTool image. The SDMMC variant ships as `update_sd.img.zip`
(a balenaEtcher-flashable archive), so requesting recovery for the
`jetkvm-v2-sdmmc` SKU returned the wrong artifact (or 404'd once SKU
folders were enforced). Drive the filename from a small per-SKU map
and reject unmapped SKUs with 400 so a typo can't silently fall back
to the wrong image.
2026-04-29 09:53:15 +02:00
2026-04-29 09:53:15 +02:00
2026-04-29 09:53:15 +02:00
2026-04-29 09:53:15 +02:00
2026-04-29 09:53:15 +02:00
2024-12-29 21:29:59 +01:00
2024-12-29 21:29:59 +01:00
2026-01-30 14:07:36 +01:00
2024-12-29 21:29:59 +01:00
2026-01-28 10:53:23 +01:00
2026-04-29 09:53:15 +02:00
2024-12-29 21:29:59 +01:00
2026-01-30 14:07:36 +01:00

JetKVM logo

Cloud API

Discord | Website | Issues | Docs

Twitter

JetKVM is a high-performance, open-source KVM over IP (Keyboard, Video, Mouse) solution designed for efficient remote management of computers, servers, and workstations. Whether you're dealing with boot failures, installing a new operating system, adjusting BIOS settings, or simply taking control of a machine from afar, JetKVM provides the tools to get it done effectively.

Contributing

We welcome contributions from the community! Whether it's improving the firmware, adding new features, or enhancing documentation, your input is valuable. We also have some rules and taboos here, so please read this page and our Code of Conduct carefully.

I need help

The best place to search for answers is our Documentation. If you can't find the answer there, check our Discord Server.

I want to report an issue

If you've found an issue and want to report it, please check our Issues page. Make sure the description contains information about the firmware version you're using, your platform, and a clear explanation of the steps to reproduce the issue.

Development

This project is built with Node.js, Prisma, and Express.

# Start the database
docker compose -f compose.development.yaml up -d

# Copy and configure environment variables
cp .env.example .env

# Install dependencies
npm install

# Run database migrations
npm run prisma-dev-migrate

# Seed development data (optional)
npm run seed

# Start the development server with hot reload
npm run dev

# Run tests
npm test

Self-Hosting

For self-hosting, use the default compose file which runs the complete stack:

# Copy and configure environment variables
cp .env.example .env

# Start everything (database, migrations, and app)
docker compose up -d

The app will be available on port 3000. Configure a reverse proxy (nginx, Caddy, etc.) for TLS termination.

Updating

git pull
docker compose up -d --build

Database migrations run automatically on startup.

S
Description
JetKVM Cloud API
Readme GPL-2.0 454 KiB
Languages
TypeScript 87.3%
Shell 12.3%
Dockerfile 0.4%