Skip to content

fix(onboarding): add explicit EFI loader path for flash entry#1926

Merged
Ajit-Mehrotra merged 6 commits intomainfrom
codex/api-flash-efi-loader
Mar 18, 2026
Merged

fix(onboarding): add explicit EFI loader path for flash entry#1926
Ajit-Mehrotra merged 6 commits intomainfrom
codex/api-flash-efi-loader

Conversation

@Ajit-Mehrotra
Copy link
Contributor

@Ajit-Mehrotra Ajit-Mehrotra commented Mar 17, 2026

Summary

  • update API onboarding internal-boot BIOS update flow to create the flash UEFI entry with an explicit loader path
  • keep scope API-only (no webgui repo changes)
  • update onboarding internal-boot service spec to assert the new efibootmgr args

Why

Some motherboards fail to boot the USB entry in UEFI mode when the NVRAM boot entry is created without an explicit loader path, even when EFI/BOOT/BOOTX64.EFI exists.

Change Details

  • flash boot entry command now includes -l \EFI\BOOT\BOOTX64.EFI
  • internal boot entry behavior is unchanged

Testing

  • attempted: pnpm --filter ./api test src/unraid-api/graph/resolvers/onboarding/onboarding-internal-boot.service.spec.ts
  • note: not executed in this fresh worktree because dependencies are not installed (vitest: command not found)

Summary by CodeRabbit

  • Bug Fixes

    • Boot entry creation now includes the EFI loader path, improving reliability of system boot setup.
    • Skips creating BIOS entries for disks that cannot be resolved from assignable disks and avoids adding invalid boot entries.
  • Improvements

    • Internal-boot UI now prefers disk serial number first (then disk ID, then device) for more consistent selection.
    • Expanded diagnostic and debug logging around boot device resolution and BIOS/boot update flows.
  • Tests

    • Tests updated to cover assignable-disk resolution, expected output messages for unresolved disks, and BIOS update paths.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 17, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds EFI boot loader path to efibootmgr calls, replaces raw device mapping with resolved boot-device resolution and richer diagnostic logging during internal-boot creation, and changes onboarding UI disk selection to prefer serialNum, then diskId, then device. Tests updated accordingly.

Changes

Cohort / File(s) Summary
Internal boot service & tests
api/src/unraid-api/graph/resolvers/onboarding/onboarding-internal-boot.service.ts, api/src/unraid-api/graph/resolvers/onboarding/onboarding-internal-boot.service.spec.ts
Introduce resolved boot-device type and resolveRequestedBootDevices; add stringifyForOutput; replace raw mapping with resolvedDevices across BIOS/boot-entry flows; add extensive debug/warn logs and runStep wrapper; pass EFI boot loader path (-l '\\EFI\\BOOT\\BOOTX64.EFI') to efibootmgr; update tests to mock getAssignableDisks, adjust fixtures, assert new log/behavior and specific error message when a disk cannot be resolved.
Onboarding UI — internal boot selection & summary
web/src/components/Onboarding/steps/OnboardingInternalBootStep.vue, web/src/components/Onboarding/steps/OnboardingSummaryStep.vue
Change optionValue computation to prefer serialNum first, then diskId (trimmed disk.id), then device; add local diskId variable. Display labels unchanged.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant OnboardingService
  participant DisksService
  participant Emcmd
  participant Efibootmgr
  participant StateStore

  Client->>OnboardingService: createInternalBootPool(input)
  OnboardingService->>StateStore: loadStateFiles(var/devs/disks)
  OnboardingService->>DisksService: getAssignableDisks()
  OnboardingService->>OnboardingService: resolveRequestedBootDevices(assignableDisks, requested)
  OnboardingService->>Emcmd: runStep("bios-update"/others)
  Emcmd-->>OnboardingService: result / error (logged)
  OnboardingService->>Efibootmgr: create flash entry (-l '\EFI\BOOT\BOOTX64.EFI')
  Efibootmgr-->>OnboardingService: success / failure (logged)
  OnboardingService->>StateStore: invalidateInternalBootState()
  OnboardingService-->>Client: result (with diagnostics)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hop through logs with tiny feet,
I match each serial, tidy and neat.
EFI path tucked in the flash's light,
devices resolved before the night.
A snug little boot — all systems bright.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(onboarding): add explicit EFI loader path for flash entry' accurately and specifically describes the main change: adding an explicit EFI loader path to the flash boot entry creation in the onboarding flow.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/api-flash-efi-loader
📝 Coding Plan
  • Generate coding plan for human review comments

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 and usage tips.

@codecov
Copy link

codecov bot commented Mar 17, 2026

Codecov Report

❌ Patch coverage is 96.26168% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 51.71%. Comparing base (bb6f241) to head (2ea7198).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
...ers/onboarding/onboarding-internal-boot.service.ts 96.11% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1926      +/-   ##
==========================================
+ Coverage   51.66%   51.71%   +0.04%     
==========================================
  Files        1026     1026              
  Lines       70932    70989      +57     
  Branches     7841     7849       +8     
==========================================
+ Hits        36650    36713      +63     
+ Misses      34160    34154       -6     
  Partials      122      122              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@web/src/components/Onboarding/steps/OnboardingInternalBootStep.vue`:
- Around line 172-173: The backend cannot resolve serial numbers because
resolveBootDevicePath() only looks up keys in devsById (populated by
getDeviceMapFromEmhttpState() using disk.id), while the frontend may send
serialNum in the devices array to createInternalBootPool; update the backend
mapping logic to also index devices by serial number (add serial -> devicePath
entries when building devsById in getDeviceMapFromEmhttpState or add a parallel
map) so resolveBootDevicePath() can resolve either disk.id or serialNum, or
alternatively change the frontend to send only disk.id (ensure
createInternalBootPool is called with the id present in devsById).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 0a4412cc-cfd5-4667-a455-373eb1cc8046

📥 Commits

Reviewing files that changed from the base of the PR and between cc2c8ef and 43cb540.

📒 Files selected for processing (2)
  • web/src/components/Onboarding/steps/OnboardingInternalBootStep.vue
  • web/src/components/Onboarding/steps/OnboardingSummaryStep.vue

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@api/src/unraid-api/graph/resolvers/onboarding/onboarding-internal-boot.service.ts`:
- Around line 262-263: The code is appending full emhttp.devices dumps
(rawDevicesText and parsedDevicesText) to the response output array in
createInternalBootPool; remove those pushes (output.push(`emhttp.devices raw:
${rawDevicesText}`) and the parsedDevicesText push) so sensitive hardware
identifiers aren't returned, and instead, if needed, add a brief redacted
summary (e.g., counts or masked IDs) to output or rely on logger.debug
(`this.logger.debug(...)`) for full details; ensure rawDevicesText and
parsedDevicesText remain only in logs and not included in the API response.
- Around line 345-349: In createInternalBootPool, when a bootDevice input fails
to resolve (where resolved is falsy and you currently call this.logger.warn with
the message including bootDevice), set the hadFailures flag to true before
continuing so the overall result reflects the failure; update the unresolved
branch (the block that logs `createInternalBootPool unable to resolve boot
device input='${bootDevice}'`) to assign hadFailures = true and then continue.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 418275cc-019f-486e-9923-76286d2fe138

📥 Commits

Reviewing files that changed from the base of the PR and between 5162093 and f90f538.

📒 Files selected for processing (1)
  • api/src/unraid-api/graph/resolvers/onboarding/onboarding-internal-boot.service.ts

Comment on lines 345 to 349
if (!resolved) {
this.logger.warn(
`createInternalBootPool unable to resolve boot device input='${bootDevice}'`
);
continue;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Mark unresolved boot-device resolution as a BIOS update failure.

Line 345-Line 349 currently logs and skips unresolved inputs, but hadFailures remains unchanged. This can return a successful result even when a requested boot entry was not created.

Proposed fix
         for (const bootDevice of devices) {
             const resolved = this.resolveBootDevicePath(bootDevice, devsById);
             if (!resolved) {
                 this.logger.warn(
                     `createInternalBootPool unable to resolve boot device input='${bootDevice}'`
                 );
+                output.push(
+                    `efibootmgr skipped unresolved boot device input='${bootDevice}'`
+                );
+                hadFailures = true;
                 continue;
             }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!resolved) {
this.logger.warn(
`createInternalBootPool unable to resolve boot device input='${bootDevice}'`
);
continue;
if (!resolved) {
this.logger.warn(
`createInternalBootPool unable to resolve boot device input='${bootDevice}'`
);
output.push(
`efibootmgr skipped unresolved boot device input='${bootDevice}'`
);
hadFailures = true;
continue;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@api/src/unraid-api/graph/resolvers/onboarding/onboarding-internal-boot.service.ts`
around lines 345 - 349, In createInternalBootPool, when a bootDevice input fails
to resolve (where resolved is falsy and you currently call this.logger.warn with
the message including bootDevice), set the hadFailures flag to true before
continuing so the overall result reflects the failure; update the unresolved
branch (the block that logs `createInternalBootPool unable to resolve boot
device input='${bootDevice}'`) to assign hadFailures = true and then continue.

- Purpose: ensure API-created USB flash UEFI entries include an explicit loader path.

- Before: the API BIOS update flow created 'Unraid Flash' with efibootmgr using only disk/partition/label and no -l loader path.

- Problem: some firmware can leave the entry non-bootable in UEFI mode when loader path is omitted, even if EFI files are present on disk.

- Change: append '-l \EFI\BOOT\BOOTX64.EFI' when creating the flash entry in the onboarding internal-boot service.

- How: reused the existing EFI_BOOT_PATH constant and updated the unit test expectation to assert the exact efibootmgr args for flash entry creation.
- Purpose: ensure onboarding sends stable serial-based device identifiers to CreateInternalBootPool.

- Before: internal boot selection used disk.id as option value and persisted that in onboardingDraft, which could propagate IDs unsuitable for efibootmgr resolution paths.

- Problem: some environments surface non-kernel IDs that later fail BIOS entry updates, producing warnings and invalid /dev/<id> attempts.

- Change: use disk.serialNum as the canonical option value, with fallback only when serial is unavailable.

- How: added alias mapping so persisted legacy id/device values still hydrate to current serial-based options; updated summary label mapping to resolve serial/id/device keys consistently.
- Purpose: keep internal boot selection strictly serial-first without backward compatibility behavior.

- Before: form initialization and summary mapping translated legacy id/device values to new serial-based options.

- Problem: this added extra compatibility logic you do not want to carry.

- Change: removed alias fields and persisted-value remapping from the internal boot step, and removed extra summary label aliases for serial/id.

- How: selection now reads/writes the raw serial-first values directly, with no legacy id translation layer.
- Purpose: surface raw emhttp device payload and resolution decisions during BIOS boot entry updates.

- Before: device map misses silently fell back to /dev/<id>, making efibootmgr failures hard to diagnose from onboarding output alone.

- Problem: we could not see what getters.emhttp().devices contained at runtime or whether each selected boot device was mapped or fallback.

- Change: append diagnostic lines to mutation output with raw emhttp.devices data, parsed id->device map entries, and per-device resolution source/result.

- How: added safe JSON serialization helper and instrumented getDeviceMapFromEmhttpState + createInternalBootEntries resolution logging.
- Purpose: provide thorough observability for CreateInternalBootPool execution and BIOS update mapping behavior.

- Before: logs were limited and did not consistently show mutation input, per-step command flow, map contents, and resolution path decisions in server logs.

- Problem: diagnosing id-to-device mapping failures required inference and lacked direct evidence at each stage.

- Change: added debug/warn logs for received input, each emcmd step start/success/failure, efibootmgr args/results, emhttp.devices raw+parsed map, per-device resolution source/result, BIOS update lifecycle, and final outcome.

- How: instrumented runStep, runEfiBootMgr, getDeviceMapFromEmhttpState, createInternalBootEntries, createFlashBootEntry, updateBootOrder, updateBiosBootEntries, and createInternalBootPool.
- Purpose: make BIOS entry creation use the same assignable disk snapshot the UI/API already exposes instead of rebuilding device resolution later from emhttp state.
- Before: createInternalBootPool created the pool with serial-based disk IDs, then tried to remap those IDs to /dev paths from emhttp.devices and fell back to /dev/<serial> when the lookup missed.
- Why that was a problem: stale or incomplete emhttp state produced bogus efibootmgr device paths like /dev/TOSHIBA_..., which guaranteed BIOS update warnings even when pool creation itself succeeded.
- What changed: the mutation now snapshots assignableDisks up front, treats serialNum as the canonical input identifier, uses that serial for cmdAssignDisk, and uses the matched disk.device path for efibootmgr.
- How it works: unresolved serials are warned and skipped for BIOS entry creation, the broken fallback path generation was removed, and the onboarding service spec was updated to cover the new resolution flow and skip behavior.
@Ajit-Mehrotra Ajit-Mehrotra force-pushed the codex/api-flash-efi-loader branch from e1a1b50 to 2ea7198 Compare March 18, 2026 10:43
@github-actions
Copy link
Contributor

This plugin has been deployed to Cloudflare R2 and is available for testing.
Download it at this URL:

https://preview.dl.unraid.net/unraid-api/tag/PR1926/dynamix.unraid.net.plg

@Ajit-Mehrotra Ajit-Mehrotra marked this pull request as ready for review March 18, 2026 11:03
@Ajit-Mehrotra Ajit-Mehrotra requested a review from elibosley March 18, 2026 11:03
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2ea7198c84

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +512 to +514
const resolvedBootDevices = input.updateBios
? await this.resolveRequestedBootDevices(input.devices, output)
: new Map<string, ResolvedBootDevice>();

Choose a reason for hiding this comment

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

P1 Badge Defer disk-resolution errors until BIOS update step

createInternalBootPool now awaits resolveRequestedBootDevices before running any emcmd pool-creation commands, so a failure in disksService.getAssignableDisks() aborts the entire operation with code 1 when updateBios is true. Since BIOS updates are handled as best-effort warnings elsewhere in this flow, this change can block onboarding entirely due to transient disk-enumeration failures that are unrelated to creating the internal boot pool.

Useful? React with 👍 / 👎.

Comment on lines +302 to +305
const bootId = disk.serialNum.trim();
const devicePath = disk.device.trim();
if (bootId.length === 0 || devicePath.length === 0) {
continue;

Choose a reason for hiding this comment

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

P2 Badge Keep non-serial disk fallback in boot-device resolution

The resolution map is keyed only by disk.serialNum and drops entries when that value is empty, but the onboarding UI still falls back to device when serial/id are unavailable (serial || diskId || device). For those disks, updateBios now silently skips EFI entry creation because the submitted device value can never be resolved, whereas the prior logic supported device-based fallback.

Useful? React with 👍 / 👎.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (2)
api/src/unraid-api/graph/resolvers/onboarding/onboarding-internal-boot.service.ts (2)

294-315: ⚠️ Potential issue | 🟠 Major

Don't send raw assignableDisks mappings back in output.

output is part of the resolver response, and the onboarding flow already surfaces result.output back to the browser on failure paths. These two pushes reintroduce client-visible serial numbers and /dev/* mappings for every assignable disk. Keep the full payload in logger.debug(...) and return only a redacted count/summary here.

Suggested redaction
         const snapshot = assignableDisks.map((disk) => ({
             id: disk.id,
             serialNum: disk.serialNum,
             device: disk.device,
         }));
-        output.push(`assignableDisks snapshot: ${this.stringifyForOutput(snapshot)}`);
+        output.push(`assignableDisks snapshot count: ${snapshot.length}`);
         this.logger.debug(
             `createInternalBootPool assignableDisks snapshot=${this.stringifyForOutput(snapshot)}`
         );
@@
-        output.push(
-            `assignableDisks resolved serialNum->device: ${this.stringifyForOutput(Array.from(resolved.entries()))}`
-        );
+        const resolvedRequestedCount = bootIds.filter((bootId) => resolved.has(bootId)).length;
+        output.push(
+            `assignableDisks resolved requested devices: ${resolvedRequestedCount}/${bootIds.length}`
+        );
         this.logger.debug(
             `createInternalBootPool assignableDisks resolved serialNum->device=${this.stringifyForOutput(Array.from(resolved.entries()))}`
         );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@api/src/unraid-api/graph/resolvers/onboarding/onboarding-internal-boot.service.ts`
around lines 294 - 315, The two places that push full assignableDisks/resolved
serial->device data into the response output (the output.push calls around
assignableDisks and resolved) must be replaced with a redacted summary: keep the
detailed payload only in logger.debug (leave the existing this.logger.debug(...)
calls), and change the output.push(...) lines to append a non-sensitive summary
such as the count of assignableDisks and/or a masked placeholder (e.g.,
"assignableDisks count: N" or "assignableDisks resolved count: N") using the
same variables (output, assignableDisks, resolved, stringifyForOutput) so the
public resolver response no longer contains raw serialNum or devicePath values
while internals still log full details in createInternalBootPool.

318-330: ⚠️ Potential issue | 🟠 Major

Propagate unresolved boot IDs into the BIOS warning state.

resolveRequestedBootDevices() records when a requested disk cannot be mapped, but that signal is dropped. If the remaining efibootmgr calls succeed, this path still ends in the success summary even though one requested boot entry was skipped. The summary step only treats with warnings or efibootmgr failed markers as BIOS trouble, so this produces a false green result.

Suggested fix
+type ResolvedBootDeviceResolution = {
+    devices: Map<string, ResolvedBootDevice>;
+    hadUnresolved: boolean;
+};
+
     private async resolveRequestedBootDevices(
         bootIds: string[],
         output: string[]
-    ): Promise<Map<string, ResolvedBootDevice>> {
+    ): Promise<ResolvedBootDeviceResolution> {
         this.loadEmhttpBootContext(true);
         const assignableDisks = await this.disksService.getAssignableDisks();
@@
-        for (const bootId of bootIds) {
+        let hadUnresolved = false;
+        for (const bootId of bootIds) {
             if (resolved.has(bootId)) {
                 continue;
             }
 
+            hadUnresolved = true;
             const warning = `Unable to resolve boot device for serial '${bootId}' from assignableDisks; skipping BIOS entry creation for this disk.`;
             output.push(warning);
             this.logger.warn(
                 `createInternalBootPool could not resolve serial='${bootId}' from assignableDisks`
             );
         }
 
-        return resolved;
+        return { devices: resolved, hadUnresolved };
     }
@@
-            const resolvedBootDevices = input.updateBios
+            const bootResolution = input.updateBios
                 ? await this.resolveRequestedBootDevices(input.devices, output)
-                : new Map<string, ResolvedBootDevice>();
+                : {
+                      devices: new Map<string, ResolvedBootDevice>(),
+                      hadUnresolved: false,
+                  };
@@
                 const biosUpdateResult = await this.updateBiosBootEntries(
                     input.devices,
-                    resolvedBootDevices,
+                    bootResolution.devices,
                     output
                 );
+                const hadBiosWarnings =
+                    biosUpdateResult.hadFailures || bootResolution.hadUnresolved;
                 this.logger.debug(
-                    `createInternalBootPool BIOS boot entry updates completed hadFailures=${biosUpdateResult.hadFailures}`
+                    `createInternalBootPool BIOS boot entry updates completed hadFailures=${hadBiosWarnings}`
                 );
                 output.push(
-                    biosUpdateResult.hadFailures
+                    hadBiosWarnings
                         ? 'BIOS boot entry updates completed with warnings; manual BIOS boot order changes may still be required.'
                         : 'BIOS boot entry updates completed successfully.'
                 );

Also applies to: 512-514, 559-566

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@api/src/unraid-api/graph/resolvers/onboarding/onboarding-internal-boot.service.ts`
around lines 318 - 330, The loop over bootIds in createInternalBootPool drops
the fact that a bootId couldn't be resolved (it only logs and pushes a warning
message to output), so callers can still treat the run as success; change the
code that handles unresolved boot IDs (the block that currently builds warning
and calls this.logger.warn inside createInternalBootPool) to also propagate a
BIOS-warning marker/state back to the caller — e.g., set a boolean like
biosWarning = true or push a canonical warning sentinel into the same
summary/output aggregation used by the summary step (the one that looks for
"with warnings" / "efibootmgr failed"), and return or expose that marker
alongside resolved (or mutate the shared output collection) so
resolveRequestedBootDevices/createInternalBootPool callers see and surface the
BIOS warning in the final summary.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In
`@api/src/unraid-api/graph/resolvers/onboarding/onboarding-internal-boot.service.ts`:
- Around line 294-315: The two places that push full assignableDisks/resolved
serial->device data into the response output (the output.push calls around
assignableDisks and resolved) must be replaced with a redacted summary: keep the
detailed payload only in logger.debug (leave the existing this.logger.debug(...)
calls), and change the output.push(...) lines to append a non-sensitive summary
such as the count of assignableDisks and/or a masked placeholder (e.g.,
"assignableDisks count: N" or "assignableDisks resolved count: N") using the
same variables (output, assignableDisks, resolved, stringifyForOutput) so the
public resolver response no longer contains raw serialNum or devicePath values
while internals still log full details in createInternalBootPool.
- Around line 318-330: The loop over bootIds in createInternalBootPool drops the
fact that a bootId couldn't be resolved (it only logs and pushes a warning
message to output), so callers can still treat the run as success; change the
code that handles unresolved boot IDs (the block that currently builds warning
and calls this.logger.warn inside createInternalBootPool) to also propagate a
BIOS-warning marker/state back to the caller — e.g., set a boolean like
biosWarning = true or push a canonical warning sentinel into the same
summary/output aggregation used by the summary step (the one that looks for
"with warnings" / "efibootmgr failed"), and return or expose that marker
alongside resolved (or mutate the shared output collection) so
resolveRequestedBootDevices/createInternalBootPool callers see and surface the
BIOS warning in the final summary.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 20c0cadc-c320-4c0b-8c48-a2fce2bd8b57

📥 Commits

Reviewing files that changed from the base of the PR and between f90f538 and 2ea7198.

📒 Files selected for processing (4)
  • api/src/unraid-api/graph/resolvers/onboarding/onboarding-internal-boot.service.spec.ts
  • api/src/unraid-api/graph/resolvers/onboarding/onboarding-internal-boot.service.ts
  • web/src/components/Onboarding/steps/OnboardingInternalBootStep.vue
  • web/src/components/Onboarding/steps/OnboardingSummaryStep.vue
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/src/components/Onboarding/steps/OnboardingInternalBootStep.vue

@Ajit-Mehrotra Ajit-Mehrotra merged commit 429b438 into main Mar 18, 2026
13 checks passed
@Ajit-Mehrotra Ajit-Mehrotra deleted the codex/api-flash-efi-loader branch March 18, 2026 14:31
elibosley pushed a commit that referenced this pull request Mar 18, 2026
🤖 I have created a release *beep* *boop*
---


## [4.30.0](v4.29.2...v4.30.0)
(2026-03-18)


### Features

* add internal boot step to onboarding flow
([#1881](#1881))
([337aecc](337aecc))
* Add TPM licensing availability to registration
([#1908](#1908))
([aa162eb](aa162eb))
* add UPS power ([#1874](#1874))
([b531aed](b531aed))
* **api:** alert when usb boot has internal boot target
([#1898](#1898))
([b94df47](b94df47))
* **api:** expose internal boot devices in array GraphQL
([#1894](#1894))
([0736709](0736709))
* docker overview ([#1855](#1855))
([9ef1cf1](9ef1cf1))
* **docker:** add update actions to container context menu
([#1867](#1867))
([4ca3e06](4ca3e06))
* **docker:** disable containers page file modification
([#1870](#1870))
([aaa0372](aaa0372))
* issues/1597: Temperature Monitoring - Thanks @MitchellThompkins
([a1be458](a1be458))
* New Crowdin updates
([#1809](#1809))
([a7b3f07](a7b3f07))
* New Crowdin updates
([#1883](#1883))
([14a8fa8](14a8fa8))
* **onboarding:** add new onboarding flows for Unraid OS
([#1746](#1746))
([15bd747](15bd747))
* registration and trial actions use Account app
([#1928](#1928))
([c2c0425](c2c0425))
* share internal boot state
([#1921](#1921))
([8e4d44d](8e4d44d))
* **web:** show TPM move control for trial licenses
([#1911](#1911))
([d00fb63](d00fb63))


### Bug Fixes

* Add dedicated TPM license move option
([#1909](#1909))
([36c56f7](36c56f7))
* allow free USB targets in onboarding internal boot setup
([#1903](#1903))
([298da54](298da54))
* API key key display truncation
([#1890](#1890))
([b12f75c](b12f75c))
* **api:** harden PHP wrapper args for newer PHP versions
([#1901](#1901))
([849f177](849f177))
* **api:** prevent flash notification startup fd exhaustion
([#1893](#1893))
([4b231ad](4b231ad))
* clear stale onboarding modal session state
([#1904](#1904))
([23f7836](23f7836))
* consistently clear onboarding draft
([#1916](#1916))
([199d803](199d803))
* correct graphql-api.log timestamp formatting
([#1918](#1918))
([243c5a8](243c5a8))
* **deps:** pin dependencies
([#1878](#1878))
([db88eb8](db88eb8))
* **docker:** change "visit" to "webui" & use correct link
([#1863](#1863))
([cab0880](cab0880))
* **docker:** improve start/stop UX with visual feedback
([#1865](#1865))
([c084e25](c084e25))
* **docker:** remove aggressive caching to ensure data correctness
([#1864](#1864))
([1c1bae8](1c1bae8))
* **docker:** sync template mappings in organizer to prevent false
orphan warnings ([#1866](#1866))
([38a6f0c](38a6f0c))
* onboarding internal-boot warning panel contrast and semantics
([#1927](#1927))
([bb6f241](bb6f241))
* **onboarding:** add explicit EFI loader path for flash entry
([#1926](#1926))
([429b438](429b438))
* **onboarding:** extend onboarding refresh timeout
([#1925](#1925))
([e2a5f44](e2a5f44))
* **onboarding:** persist installed plugins in summary
([#1915](#1915))
([07f4ebd](07f4ebd))
* **onboarding:** refine storage boot setup UX
([#1900](#1900))
([1108d0a](1108d0a))
* polish onboarding flow
([#1902](#1902))
([8742cac](8742cac))
* preserve registration device limits after refresh
([#1905](#1905))
([234bfc7](234bfc7))
* prevent onboarding on API errors
([#1917](#1917))
([540d6f9](540d6f9))
* remap TPM guid prefix to 01
([#1924](#1924))
([5360b5b](5360b5b))
* Return null for corrupted/invalid API key files and add Connect
fixtures test ([#1886](#1886))
([013e6c5](013e6c5))
* share internal boot state across onboarding
([#1920](#1920))
([f9b293f](f9b293f))
* too many file descriptors with thousands of notifications
([#1887](#1887))
([7956987](7956987))
* Treat onboarding patch updates as completed
([#1884](#1884))
([d03b25e](d03b25e))
* unify onboarding internal boot state refresh
([#1923](#1923))
([d3032c1](d3032c1))
* **web:** refresh internal boot onboarding state
([#1913](#1913))
([1ca2129](1ca2129))
* **web:** stop showing callback errors after successful key installs
([#1892](#1892))
([45f1402](45f1402))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant