Skip to content

feat: Support repository server - #237

Draft
hhvrc wants to merge 15 commits into
developfrom
feature/support-repository-server
Draft

feat: Support repository server#237
hhvrc wants to merge 15 commits into
developfrom
feature/support-repository-server

Conversation

@hhvrc

@hhvrchhvrc commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

No description provided.

hhvrcand others added 8 commits March 30, 2026 10:48
…pository-server
# Conflicts:
#	.env
#	.env.production
#	src/lib/api/firmwareCDN.ts
#	src/lib/components/FirmwareChannelSelector.svelte
#	src/routes/(app)/hubs/[hubId=guid]/update/+page.svelte
#	src/routes/terminal/+page.svelte
#	src/routes/terminal/FirmwareBoardSelector.svelte
#	src/routes/terminal/FirmwareFlasher.svelte
#	svelte.config.js
@hhvrchhvrc self-assigned this Aug 4, 2026
CopilotAI lite review requested due to automatic review settings August 4, 2026 13:42
@hhvrchhvrc added the enhancement New feature or request label Aug 4, 2026
@hhvrc
hhvrc marked this pull request as draft August 4, 2026 13:42

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates the frontend’s firmware update/flash flow from the legacy firmware CDN endpoints to a new “repository server” API, and wires the new base URL through environment/config so different deployments can point at different firmware repositories.

Changes:

  • Replace the firmware CDN client with a new firmwareRepo API client (latest/version/history + artifact download + SHA-256 verification).
  • Update terminal flashing UI components to operate on a FirmwareRelease response (board extraction + artifact selection).
  • Make the firmware repository origin configurable via PUBLIC_FIRMWARE_REPO_URL and include it in CSP connect-src.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Show a summary per file
FileDescription
vite.config.tsAdds firmware repo URL to CSP connect-src.
src/routes/terminal/FirmwareFlasher.svelteSwitches flashing to download/verify a selected artifact from the repo response.
src/routes/terminal/FirmwareBoardSelector.svelteDerives board list from the fetched release metadata instead of fetching boards per version.
src/routes/terminal/+page.sveltePlumbs latestResponse through the terminal flashing flow and updates component bindings.
src/routes/(app)/hubs/[hubId=guid]/update/+page.svelteUpdates firmware channel type import to the new module.
src/lib/components/FirmwareChannelSelector.svelteFetches latest firmware release per channel and caches responses.
src/lib/api/firmwareRepo.tsIntroduces repository server API client + artifact download/verification helpers.
src/lib/api/firmwareCDN.tsRemoves legacy firmware CDN implementation.
.env.developmentAdds PUBLIC_FIRMWARE_REPO_URL for development.
.envAdds PUBLIC_FIRMWARE_REPO_URL for default environment.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadvite.config.ts Outdated
dotenv.PUBLIC_GATEWAY_CSP_WILDCARD,
getWsUrlFromHttpUrl(dotenv.PUBLIC_GATEWAY_CSP_WILDCARD),
'https://firmware.openshock.org',
dotenv.PUBLIC_FIRMWARE_REPO_URL,
Comment on lines 43 to 45
// Capture the current channel to avoid race conditions if channel changes.
const currentChannel = channel;

Comment threadsrc/lib/api/firmwareRepo.ts Outdated
changelog: string;
}

const BASE_URL = PUBLIC_FIRMWARE_REPO_URL.replace(/\/+$/, '');
Comment threadsrc/lib/api/firmwareRepo.ts Outdated
export async function DownloadAndVerifyArtifact(artifact: FirmwareArtifact): Promise<Uint8Array> {
const binary = await DownloadBinary(artifact.url);

const calculatedHash = await HashBuffer(binary.buffer as ArrayBuffer, 'SHA-256');
@cloudflare-workers-and-pages

cloudflare-workers-and-pagesBot commented Aug 4, 2026

Copy link
Copy Markdown

Deploying with Cloudflare Workers Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

StatusNameLatest CommitUpdated (UTC)
❌ Deployment failed
View logs
openshock-app4640535Aug 13 2026, 12:49 PM

CopilotAI review requested due to automatic review settings August 5, 2026 08:23
@cloudflare-workers-and-pages

cloudflare-workers-and-pagesBot commented Aug 5, 2026

Copy link
Copy Markdown

Deploying openshockapp with Cloudflare Pages Cloudflare Pages

Latest commit:d228ee3
Status: ✅ Deploy successful!
Preview URL:https://0e718dbe.openshockapp.pages.dev
Branch Preview URL:https://feature-support-repository-s.openshockapp.pages.dev

View logs

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Suppressed comments (3)

src/lib/api/firmwareRepo.ts:35

  • FirmwareVersionSummary.channel is typed as string, which is inconsistent with the FirmwareChannel type used elsewhere and weakens type-safety for consumers.
 channel: string;

src/lib/api/firmwareRepo.ts:22

  • FirmwareRelease.channel is currently typed as string, which loses the stronger guarantee provided by FirmwareChannel and makes it easier for invalid values to leak into the UI. Since this value is expected to be one of the known channels, type it as FirmwareChannel.

This issue also appears on line 35 of the same file.

 channel: string;

src/lib/components/FirmwareChannelSelector.svelte:60

  • In the error path, the selector caches a null entry for the channel. Because the effect treats any defined cache entry (including null) as a hit, the component will never retry fetching for that channel (even after a transient outage) unless the page is reloaded.
 .catch((error) => {
latestResponse = null;
version = null;
cache[currentChannel] = null;
handleApiError(error);

Comment threadsrc/lib/api/firmwareRepo.ts Outdated
The client was written against an earlier draft of the API and two of its four
calls could not succeed against the shipped server.
Route shapes: version lookups are not scoped by channel. FetchVersion hit
/versions/{channel}/{version}, which the server routes to GetVersionForBoard
with version="stable", and FetchVersionHistory hit /versions/{channel}, which
routes to GetVersion with the same. Both 404 permanently. Versions are
globally unique, so FetchVersion now takes only a version, and channel becomes
an optional query filter on the history call.
Field shapes: board.chip is an object with id and name, not a string, so the
chip filter added in 14d78b4 could never match — masked only because the
terminal page does not yet pass a chip. The discontinued flag is
'discontinued', not 'deprecated', so EOL boards were never filtered. Releases
carry a structured releaseNotes array rather than a changelog string; the
markdown form is what CI submits on ingestion, not what the server returns.
Compare against chip.name, which the spec pins to esptool-js identifiers and
which is what EspSerialConnection reads out of loader.chip.CHIP_NAME.
The boards map is keyed by board name. The client already assumed this — it
renders the keys as the visible board label — and the server now agrees.
Also add FetchBoardRelease and the missing source/repository types, and route
the four calls through one helper.
@coderabbitai

coderabbitaiBot commented Aug 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: dce3ac2a-d54f-411d-9af0-42c0848a7c9c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

The server no longer exposes a chip UUID: chip names are unique and externally
pinned to esptool-js identifiers, and no chip appears in a storage path, so a
surrogate key bought nothing on the public surface. FirmwareChipRef.id was
declared required and is now never sent.
Nothing read it — the flashtool matches on chip.name, which is what
EspSerialConnection reads out of loader.chip.CHIP_NAME.
The server routes on /{version:apiVersion}/, matching the OpenShock backend and
firmware-api-spec.md, so the firmware API lives at /2/firmware/... rather than
/v2/firmware/....
Split the monolithic firmwareRepo.ts into the same shape as src/lib/api/next:
base.ts for the JSON fetch wrapper, endpoint functions grouped by area, one
file per model, and a matching runtime transformer per model.
Responses are now validated instead of blind-cast, so a malformed payload
throws TransformError at the boundary rather than surfacing as undefined deep
in the flasher. channel stays a plain string so an unknown channel cannot fail
a whole response, and nullable source fields accept absent-or-null.
Adds getFirmwareRepoURL alongside getBackendURL, which brings the HTTPS and
no-query/hash validation the ad-hoc base URL handling lacked.
releaseDate is now a Temporal.Instant, matching how next parses timestamps.
The non-ProblemDetails branch of handleResponseError now raises a generic
toast instead of only logging; without it the repository server's plain HTTP
errors would fail silently once they started throwing ResponseError.
@cloudflare-workers-and-pages

cloudflare-workers-and-pagesBot commented Aug 14, 2026

Copy link
Copy Markdown

Deploying with Cloudflare Workers Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

StatusNameLatest CommitUpdated (UTC)
❌ Deployment failed
View logs
openshock-app-dev52ae08eAug 18 2026, 01:28 PM

# Conflicts:
#	src/lib/api/firmwareCDN.ts
#	vite.config.ts
The OAuth login/link forms POST to our own API, which is allowlisted, but
the API answers with a 302 to the identity provider. Chrome re-checks
form-action against every hop of a form submission's redirect chain, so
that redirect was blocked and the flow died before reaching the provider.
The console error is misleading: it names the API URL (which is allowed)
rather than the redirect that actually got blocked, and it only reproduces
in Chromium, since Firefox checks the initial target alone.
The origins are the browser-facing authorization endpoints of the handlers
the backend registers - AspNet.Security.OAuth.Discord, the built-in Google
handler, and AspNet.Security.OAuth.Twitter - not their token/userinfo
endpoints, which are server-to-server. X needs both hosts, since the
handler builds a twitter.com URL that 301s to x.com mid-navigation.
List them unconditionally - a provider the backend doesn't offer is simply
never navigated to.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancementNew feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@hhvrc