Repository: hashicorp/boundary-ui
Pull request #2793: Icu 16546 upgrade ember for admin UI
Author: login: lisbet-alvarez
Labels: name: ui
name: desktop
name: admin
Created: 2025-04-23T17:23:45Z | Merged: 2025-04-25T21:40:00Z

# Description
<!-- Add a brief description of changes here -->
1. Update admin ui to ember v5.12
2. Run ember init & codemods
3. Run linter + formatter

<!-- Uncomment line below to manually add link to JIRA ticket -->
<!-- :tickets: [Jira ticket](https://hashicorp.atlassian.net/browse/ICU-16546) -->

## Screenshots (if appropriate)

![image](https://github.com/user-attachments/assets/0789c953-d2d5-4a66-bf8d-b33275a925f0)

## How to Test
<!-- Add steps to test this change. Include any other necessary relevant links -->
[Desktop Releases Test Run](https://github.com/hashicorp/boundary-desktop-releases/actions/runs/14624322298)

## Checklist
<!-- strikethrough the checklist item that is not relevant to your change -->

- [ ] I have added before and after screenshots for UI changes
- [ ] I have added JSON response output for API changes
- [ ] I have added steps to reproduce and test for bug fixes in the description
- [ ] I have commented on my code, particularly in hard-to-understand areas
- [X] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works



Diff:
diff --git a/ui/admin/.editorconfig b/ui/admin/.editorconfig
index e1681d8169..c35a002406 100644
--- a/ui/admin/.editorconfig
+++ b/ui/admin/.editorconfig
@@ -12,8 +12,8 @@ insert_final_newline = true
 indent_style = space
 indent_size = 2
 
-[*.{diff,md}]
-trim_trailing_whitespace = false
-
 [*.hbs]
 insert_final_newline = false
+
+[*.{diff,md}]
+trim_trailing_whitespace = false
diff --git a/ui/admin/.ember-cli b/ui/admin/.ember-cli
index 8c1812cff8..465c4050de 100644
--- a/ui/admin/.ember-cli
+++ b/ui/admin/.ember-cli
@@ -1,12 +1,4 @@
 {
-  /**
-    Ember CLI sends analytics information by default. The data is completely
-    anonymous, but there are times when you might want to disable this behavior.
-
-    Setting `disableAnalytics` to true will prevent any data from being sent.
-  */
-  "disableAnalytics": false,
-
   /**
     Setting `isTypeScriptProject` to true will force the blueprint generators to generate TypeScript
     rather than JavaScript by default, when a TypeScript version of a given blueprint is available.
diff --git a/ui/admin/.eslintignore b/ui/admin/.eslintignore
index d474a40bd5..768fab33b6 100644
--- a/ui/admin/.eslintignore
+++ b/ui/admin/.eslintignore
@@ -1,25 +1,14 @@
 # unconventional js
 /blueprints/*/files/
-/vendor/
 
 # compiled output
+/declarations/
 /dist/
-/tmp/
-
-# dependencies
-/bower_components/
-/node_modules/
 
 # misc
 /coverage/
 !.*
 .*/
-.eslintcache
 
 # ember-try
 /.node_modules.ember-try/
-/bower.json.ember-try
-/npm-shrinkwrap.json.ember-try
-/package.json.ember-try
-/package-lock.json.ember-try
-/yarn.lock.ember-try
diff --git a/ui/admin/.eslintrc.js b/ui/admin/.eslintrc.js
index 614b6c10ad..690ab8e4b3 100644
--- a/ui/admin/.eslintrc.js
+++ b/ui/admin/.eslintrc.js
@@ -11,17 +11,19 @@ module.exports = {
   parserOptions: {
     ecmaVersion: 'latest',
     sourceType: 'module',
-    // This is specific babel-config. If grows consider creating a babel config file
     requireConfigFile: false,
     babelOptions: {
       plugins: [
         ['@babel/plugin-proposal-decorators', { decoratorsBeforeExport: true }],
       ],
     },
-    // end of babel-config
   },
   plugins: ['ember'],
-  extends: ['eslint:recommended', 'plugin:ember/recommended', 'prettier'],
+  extends: [
+    'eslint:recommended',
+    'plugin:ember/recommended',
+    'plugin:prettier/recommended',
+  ],
   env: {
     browser: true,
   },
@@ -57,7 +59,7 @@ module.exports = {
       extends: ['plugin:n/recommended'],
     },
     {
-      // Test files:
+      // test files
       files: ['tests/**/*-test.{js,ts}'],
       extends: ['plugin:qunit/recommended'],
       rules: {
diff --git a/ui/admin/.gitignore b/ui/admin/.gitignore
new file mode 100644
index 0000000000..71ad79d02e
--- /dev/null
+++ b/ui/admin/.gitignore
@@ -0,0 +1,25 @@
+# compiled output
+/dist/
+/declarations/
+
+# dependencies
+/node_modules/
+
+# misc
+/.env*
+/.pnp*
+/.eslintcache
+/coverage/
+/npm-debug.log*
+/testem.log
+/yarn-error.log
+
+# ember-try
+/.node_modules.ember-try/
+/npm-shrinkwrap.json.ember-try
+/package.json.ember-try
+/package-lock.json.ember-try
+/yarn.lock.ember-try
+
+# broccoli-debug
+/DEBUG/
diff --git a/ui/admin/.prettierignore b/ui/admin/.prettierignore
index 4178fd571e..9385391f21 100644
--- a/ui/admin/.prettierignore
+++ b/ui/admin/.prettierignore
@@ -1,25 +1,13 @@
 # unconventional js
 /blueprints/*/files/
-/vendor/
 
 # compiled output
 /dist/
-/tmp/
-
-# dependencies
-/bower_components/
-/node_modules/
 
 # misc
 /coverage/
 !.*
-.eslintcache
-.lint-todo/
+.*/
 
 # ember-try
 /.node_modules.ember-try/
-/bower.json.ember-try
-/npm-shrinkwrap.json.ember-try
-/package.json.ember-try
-/package-lock.json.ember-try
-/yarn.lock.ember-try
diff --git a/ui/admin/.prettierrc.js b/ui/admin/.prettierrc.js
index b6a3c90e0c..91bdf941a7 100644
--- a/ui/admin/.prettierrc.js
+++ b/ui/admin/.prettierrc.js
@@ -3,6 +3,8 @@
  * SPDX-License-Identifier: BUSL-1.1
  */
 
+'use strict';
+
 module.exports = {
   singleQuote: true,
   printWidth: 80,
diff --git a/ui/admin/.watchmanconfig b/ui/admin/.watchmanconfig
index e7834e3e4f..f9c3d8f84f 100644
--- a/ui/admin/.watchmanconfig
+++ b/ui/admin/.watchmanconfig
@@ -1,3 +1,3 @@
 {
-  "ignore_dirs": ["tmp", "dist"]
+  "ignore_dirs": ["dist"]
 }
diff --git a/ui/admin/README.md b/ui/admin/README.md
index fdbfb267bc..58b89e28a1 100644
--- a/ui/admin/README.md
+++ b/ui/admin/README.md
@@ -54,9 +54,9 @@ List of available project commands.  `yarn run <command-name>`
 
 ## Running / Development
 
-* `ember serve`
-* Visit your app at [http://localhost:4200](http://localhost:4200).
-* Visit your tests at [http://localhost:4200/tests](http://localhost:4200/tests).
+- `ember serve`
+- Visit your app at [http://localhost:4200](http://localhost:4200).
+- Visit your tests at [http://localhost:4200/tests](http://localhost:4200/tests).
 
 ### Building for Production
 
@@ -102,8 +102,8 @@ Specify what it takes to deploy your app.
 
 ## Further Reading / Useful Links
 
-* [ember.js](https://emberjs.com/)
-* [ember-cli](https://cli.emberjs.com/release/)
-* Development Browser Extensions
-  * [ember inspector for chrome](https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi)
-  * [ember inspector for firefox](https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/)
+- [ember.js](https://emberjs.com/)
+- [ember-cli](https://cli.emberjs.com/release/)
+- Development Browser Extensions
+  - [ember inspector for chrome](https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi)
+  - [ember inspector for firefox](https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/)
diff --git a/ui/admin/app/index.html b/ui/admin/app/index.html
index 17dbe698a1..f5cc44780c 100644
--- a/ui/admin/app/index.html
+++ b/ui/admin/app/index.html
@@ -1,24 +1,21 @@
-<!doctype html>
 <!--
  Copyright (c) HashiCorp, Inc.
  SPDX-License-Identifier: BUSL-1.1
 -->
 
+<!DOCTYPE html>
 <html>
   <head>
-    <meta charset="utf-8" />
+    <meta charset="utf-8">
     <title>Admin</title>
-    <meta
-      name="description"
-      content="Simple and secure remote access with HashiCorp Boundary."
-    />
-    <meta name="viewport" content="width=device-width, initial-scale=1" />
-    <meta name="theme-color" content="#f24c53" />
+    <meta name="description" content="Simple and secure remote access with HashiCorp Boundary.">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <meta name="theme-color" content="#f24c53">
 
     {{content-for "head"}}
 
-    <link integrity="" rel="stylesheet" href="{{rootURL}}assets/vendor.css" />
-    <link integrity="" rel="stylesheet" href="{{rootURL}}assets/admin.css" />
+    <link integrity="" rel="stylesheet" href="{{rootURL}}assets/vendor.css">
+    <link integrity="" rel="stylesheet" href="{{rootURL}}assets/admin.css">
 
     <link rel="icon" type="image/svg+xml" href="{{rootURL}}core/logo-app.svg" />
 
diff --git a/ui/admin/app/routes/scopes/scope/workers/worker/create-tags.js b/ui/admin/app/routes/scopes/scope/workers/worker/create-tags.js
index 001d33afc4..6977fd1789 100644
--- a/ui/admin/app/routes/scopes/scope/workers/worker/create-tags.js
+++ b/ui/admin/app/routes/scopes/scope/workers/worker/create-tags.js
@@ -18,7 +18,7 @@ export default class ScopesScopeWorkersWorkerCreateTagsRoute extends Route {
   async willTransition(transition) {
     // eslint-disable-next-line ember/no-controller-access-in-routes
     const controller = this.controllerFor(this.routeName);
-    if (controller.get('apiTags').length) {
+    if (controller.apiTags.length) {
       transition.abort();
       try {
         await this.confirm.confirm(this.intl.t('questions.abandon-confirm'), {
diff --git a/ui/admin/config/ember-cli-update.json b/ui/admin/config/ember-cli-update.json
index 4af68eb94d..ad19ce7fa0 100644
--- a/ui/admin/config/ember-cli-update.json
+++ b/ui/admin/config/ember-cli-update.json
@@ -3,13 +3,17 @@
   "packages": [
     {
       "name": "ember-cli",
-      "version": "4.12.2",
+      "version": "5.12.0",
       "blueprints": [
         {
           "name": "app",
           "outputRepo": "https://github.com/ember-cli/ember-new-output",
           "codemodsSource": "ember-app-codemods-manifest@1",
-          "isBaseBlueprint": true
+          "isBaseBlueprint": true,
+          "options": [
+            "--no-welcome",
+            "--yarn"
+          ]
         }
       ]
     }
diff --git a/ui/admin/config/optional-features.json b/ui/admin/config/optional-features.json
index b26286e2ec..5329dd9913 100644
--- a/ui/admin/config/optional-features.json
+++ b/ui/admin/config/optional-features.json
@@ -2,5 +2,6 @@
   "application-template-wrapper": false,
   "default-async-observers": true,
   "jquery-integration": false,
-  "template-only-glimmer-components": true
+  "template-only-glimmer-components": true,
+  "no-implicit-route-model": true
 }
diff --git a/ui/admin/package.json b/ui/admin/package.json
index f7010a8698..3a815ecd64 100644
--- a/ui/admin/package.json
+++ b/ui/admin/package.json
@@ -16,8 +16,8 @@
     "build:oss": "EDITION=oss ember build --environment=production",
     "build:enterprise": "EDITION=enterprise ember build --environment=production",
     "build:hcp": "EDITION=hcp ember build --environment=production",
-    "lint": "concurrently \"npm:lint:*(!fix)\" --names \"lint:\"",
-    "lint:fix": "concurrently \"npm:lint:*:fix\" --names \"fix:\"",
+    "lint": "concurrently \"yarn:lint:*(!fix)\" --names \"lint:\"",
+    "lint:fix": "concurrently \"yarn:lint:*:fix\" --names \"fix:\"",
     "lint:hbs": "ember-template-lint .",
     "lint:hbs:fix": "ember-template-lint . --fix",
     "lint:js": "eslint .",
@@ -42,32 +42,33 @@
   },
   "devDependencies": {
     "@babel/core": "^7.26.10",
-    "@babel/eslint-parser": "^7.21.3",
-    "@babel/plugin-proposal-decorators": "^7.21.0",
-    "@ember/optional-features": "^2.0.0",
+    "@babel/eslint-parser": "^7.25.1",
+    "@babel/plugin-proposal-decorators": "^7.24.7",
+    "@ember/optional-features": "^2.1.0",
     "@ember/render-modifiers": "^2.0.4",
-    "@ember/string": "^3.0.1",
-    "@ember/test-helpers": "^4.0.5",
+    "@ember/string": "^4.0.0",
+    "@ember/test-helpers": "^3.3.1",
     "@embroider/macros": "^1.16.9",
     "@faker-js/faker": "^8.0.2",
     "@glimmer/component": "^1.1.2",
     "@glimmer/tracking": "^1.1.2",
     "@hashicorp/ember-asciinema-player": "https://github.com/hashicorp/ember-asciinema-player.git#e047a096039cff70234c232efe75dcad74c6358a",
     "@warp-drive/build-config": "^0.0.2",
-    "babel-loader": "^9.2.1",
     "broccoli-asset-rev": "^3.0.0",
     "concurrently": "^9.1.0",
     "core": "workspace:*",
     "doctoc": "^2.2.0",
     "ember-a11y-testing": "^7.0.0",
     "ember-auto-import": "^2.10.0",
-    "ember-cli": "^5.12.0",
+    "ember-cli": "~5.12.0",
+    "ember-cli-app-version": "^7.0.0",
     "ember-cli-babel": "^8.2.0",
+    "ember-cli-clean-css": "^3.0.0",
     "ember-cli-code-coverage": "^1.0.3",
     "ember-cli-content-security-policy": "^2.0.3",
     "ember-cli-dependency-checker": "^3.3.2",
     "ember-cli-flash": "^4.0.0",
-    "ember-cli-htmlbars": "^6.2.0",
+    "ember-cli-htmlbars": "^6.3.0",
     "ember-cli-inject-live-reload": "^2.1.0",
     "ember-cli-sass": "^11.0.1",
     "ember-cli-sri": "^2.1.1",
@@ -76,31 +77,32 @@
     "ember-exam": "^8.0.0",
     "ember-inline-svg": "^1.0.1",
     "ember-load-initializers": "^2.1.2",
-    "ember-modifier": "^4.1.0",
-    "ember-page-title": "^7.0.0",
+    "ember-modifier": "^4.2.0",
+    "ember-page-title": "^8.2.3",
     "ember-qunit": "^8.1.0",
-    "ember-resolver": "^10.0.0",
-    "ember-source": "~4.12.0",
-    "ember-template-lint": "^5.7.2",
+    "ember-resolver": "^12.0.1",
+    "ember-source": "~5.12.0",
+    "ember-template-lint": "^6.0.0",
     "ember-template-lint-plugin-prettier": "^5.0.0",
-    "eslint": "^8.54.0",
-    "eslint-config-prettier": "^9.0.0",
-    "eslint-plugin-ember": "^11.11.1",
-    "eslint-plugin-n": "^16.3.1",
-    "eslint-plugin-qunit": "^8.0.1",
+    "eslint": "^8.57.1",
+    "eslint-config-prettier": "^9.1.0",
+    "eslint-plugin-ember": "^12.2.1",
+    "eslint-plugin-n": "^16.6.2",
+    "eslint-plugin-prettier": "^5.2.1",
+    "eslint-plugin-qunit": "^8.1.2",
     "js-bexpr": "hashicorp/js-bexpr#9b4a4b54d85eba67fdfc0990133d1518d890b1e1",
     "loader.js": "^4.7.0",
     "postcss": "^8.4.31",
-    "prettier": "^3.0.0",
+    "prettier": "^3.3.3",
     "qunit": "^2.22.0",
     "qunit-dom": "^3.2.1",
     "rose": "workspace:*",
     "sinon": "^19.0.2",
-    "stylelint": "^15.10.1",
+    "stylelint": "^15.11.0",
     "stylelint-config-prettier-scss": "^0.0.1",
     "stylelint-config-standard-scss": "^11.0.0",
-    "tracked-built-ins": "^3.1.1",
-    "webpack": "^5.94.0"
+    "tracked-built-ins": "^3.3.0",
+    "webpack": "^5.95.0"
   },
   "engines": {
     "node": "20.* || 22.*"
diff --git a/ui/admin/tests/helpers/index.js b/ui/admin/tests/helpers/index.js
index be3d6bd1fe..09279d80ee 100644
--- a/ui/admin/tests/helpers/index.js
+++ b/ui/admin/tests/helpers/index.js
@@ -13,7 +13,7 @@ import {
   authenticateSession,
 } from 'ember-simple-auth/test-support';
 
-// This file exists to provide wrappers around ember-qunit's / ember-mocha's
+// This file exists to provide wrappers around ember-qunit's
 // test setup functions. This way, you can easily extend the setup that is
 // needed per test type.
 
diff --git a/ui/admin/tests/index.html b/ui/admin/tests/index.html
index 75b2069328..29683588b6 100644
--- a/ui/admin/tests/index.html
+++ b/ui/admin/tests/index.html
@@ -1,26 +1,29 @@
-<!doctype html>
 <!--
  Copyright (c) HashiCorp, Inc.
  SPDX-License-Identifier: BUSL-1.1
 -->
 
+<!DOCTYPE html>
 <html>
   <head>
-    <meta charset="utf-8" />
+    <meta charset="utf-8">
     <title>Admin Tests</title>
-    <meta name="description" content="" />
-    <meta name="viewport" content="width=device-width, initial-scale=1" />
+    <meta name="description" content="">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
 
-    {{content-for "head"}} {{content-for "test-head"}}
+    {{content-for "head"}}
+    {{content-for "test-head"}}
 
-    <link rel="stylesheet" href="{{rootURL}}assets/vendor.css" />
-    <link rel="stylesheet" href="{{rootURL}}assets/admin.css" />
-    <link rel="stylesheet" href="{{rootURL}}assets/test-support.css" />
+    <link rel="stylesheet" href="{{rootURL}}assets/vendor.css">
+    <link rel="stylesheet" href="{{rootURL}}assets/admin.css">
+    <link rel="stylesheet" href="{{rootURL}}assets/test-support.css">
 
-    {{content-for "head-footer"}} {{content-for "test-head-footer"}}
+    {{content-for "head-footer"}}
+    {{content-for "test-head-footer"}}
   </head>
   <body>
-    {{content-for "body"}} {{content-for "test-body"}}
+    {{content-for "body"}}
+    {{content-for "test-body"}}
 
     <div id="qunit"></div>
     <div id="qunit-fixture">
@@ -35,6 +38,7 @@
     <script src="{{rootURL}}assets/admin.js"></script>
     <script src="{{rootURL}}assets/tests.js"></script>
 
-    {{content-for "body-footer"}} {{content-for "test-body-footer"}}
+    {{content-for "body-footer"}}
+    {{content-for "test-body-footer"}}
   </body>
 </html>
diff --git a/ui/admin/tests/integration/components/form/field/json-secret-skeleton-test.js b/ui/admin/tests/integration/components/form/field/json-secret-skeleton-test.js
index a7a42a15fb..ce4ef19152 100644
--- a/ui/admin/tests/integration/components/form/field/json-secret-skeleton-test.js
+++ b/ui/admin/tests/integration/components/form/field/json-secret-skeleton-test.js
@@ -17,10 +17,10 @@ module(
       this.set('value', 'Skeleton Message');
 
       await render(hbs`
-      <Form::Field::JsonSecret::Skeleton>
-        {{this.value}}
-      </Form::Field::JsonSecret::Skeleton>
-    `);
+    <Form::Field::JsonSecret::Skeleton>
+      {{this.value}}
+    </Form::Field::JsonSecret::Skeleton>
+  `);
       assert.dom('.secret-editor-skeleton-wrapper').isVisible();
       assert.dom('.secret-editor-skeleton-message').hasText('Skeleton Message');
     });
diff --git a/ui/admin/tests/integration/components/ordered-series-diagram/group/index-test.js b/ui/admin/tests/integration/components/ordered-series-diagram/group/index-test.js
index bba03430b7..94c6bf0491 100644
--- a/ui/admin/tests/integration/components/ordered-series-diagram/group/index-test.js
+++ b/ui/admin/tests/integration/components/ordered-series-diagram/group/index-test.js
@@ -18,15 +18,15 @@ module(
       this.set('egressWorker', 'Egress Worker');
 
       await render(hbs`
-        <OrderedSeriesDiagram::Group @title='Private Network' @color='highlight'>
-          <OrderedSeriesDiagram::Item @icon='user'>
-            {{this.client}}
-          </OrderedSeriesDiagram::Item>
-          <OrderedSeriesDiagram::Item @icon='settings'>
-            {{this.egressWorker}}
-          </OrderedSeriesDiagram::Item>
-        </OrderedSeriesDiagram::Group>
-      `);
+      <OrderedSeriesDiagram::Group @title='Private Network' @color='highlight'>
+        <OrderedSeriesDiagram::Item @icon='user'>
+          {{this.client}}
+        </OrderedSeriesDiagram::Item>
+        <OrderedSeriesDiagram::Item @icon='settings'>
+          {{this.egressWorker}}
+        </OrderedSeriesDiagram::Item>
+      </OrderedSeriesDiagram::Group>
+    `);
 
       assert
         .dom('.ordered-series-diagram-group-content')
diff --git a/ui/admin/tests/integration/components/ordered-series-diagram/index-test.js b/ui/admin/tests/integration/components/ordered-series-diagram/index-test.js
index b970c36519..7c7caae7b9 100644
--- a/ui/admin/tests/integration/components/ordered-series-diagram/index-test.js
+++ b/ui/admin/tests/integration/components/ordered-series-diagram/index-test.js
@@ -18,11 +18,11 @@ module(
       this.set('egressWorker', 'Egress Worker');
 
       await render(hbs`
-        <OrderedSeriesDiagram as |D|>
-          <D.Item @icon='user'>{{this.client}}</D.Item>
-          <D.Item @icon='settings'>{{this.egressWorker}}</D.Item>
-        </OrderedSeriesDiagram>
-      `);
+      <OrderedSeriesDiagram as |D|>
+        <D.Item @icon='user'>{{this.client}}</D.Item>
+        <D.Item @icon='settings'>{{this.egressWorker}}</D.Item>
+      </OrderedSeriesDiagram>
+    `);
 
       assert.dom('[data-test-icon="user"]').isVisible();
       assert.dom('.ordered-series-diagram-item-title').hasText('Client');
diff --git a/ui/admin/tests/integration/components/ordered-series-diagram/item/index-test.js b/ui/admin/tests/integration/components/ordered-series-diagram/item/index-test.js
index a33c984cc7..118b5adce1 100644
--- a/ui/admin/tests/integration/components/ordered-series-diagram/item/index-test.js
+++ b/ui/admin/tests/integration/components/ordered-series-diagram/item/index-test.js
@@ -17,10 +17,10 @@ module(
       this.set('client', 'Client');
 
       await render(hbs`
-        <OrderedSeriesDiagram::Item @icon='user'>
-          {{this.client}}
-        </OrderedSeriesDiagram::Item>
-      `);
+      <OrderedSeriesDiagram::Item @icon='user'>
+        {{this.client}}
+      </OrderedSeriesDiagram::Item>
+    `);
 
       assert.dom('[data-test-icon="user"]').isVisible();
       assert.dom('.ordered-series-diagram-item-title').hasText('Client');
diff --git a/ui/admin/tests/integration/components/workers/worker/header/index-test.js b/ui/admin/tests/integration/components/workers/worker/header/index-test.js
index b4b7df2edb..6ad4d31408 100644
--- a/ui/admin/tests/integration/components/workers/worker/header/index-test.js
+++ b/ui/admin/tests/integration/components/workers/worker/header/index-test.js
@@ -19,8 +19,8 @@ module(
       this.set('model', { id: 'w_123' });
 
       await render(hbs`
-      <Workers::Worker::Header @model={{this.model}} />
-    `);
+    <Workers::Worker::Header @model={{this.model}} />
+  `);
 
       assert.dom(this.element).includesText('w_123');
     });
diff --git a/ui/admin/tests/unit/instance-initializers/feature-edition-test.js b/ui/admin/tests/unit/instance-initializers/feature-edition-test.js
index e00c8ba023..3463b96a39 100644
--- a/ui/admin/tests/unit/instance-initializers/feature-edition-test.js
+++ b/ui/admin/tests/unit/instance-initializers/feature-edition-test.js
@@ -32,7 +32,9 @@ module('Unit | Instance Initializer | feature-edition', function (hooks) {
   });
 
   hooks.afterEach(function () {
+    // eslint-disable-next-line ember/no-runloop
     run(this.instance, 'destroy');
+    // eslint-disable-next-line ember/no-runloop
     run(this.application, 'destroy');
   });
 
diff --git a/ui/desktop/.gitignore b/ui/desktop/.gitignore
index 55ac2a7d38..be2f12270c 100644
--- a/ui/desktop/.gitignore
+++ b/ui/desktop/.gitignore
@@ -1,6 +1,6 @@
 # compiled output
 /dist/
-/tmp/
+/declarations/
 
 # dependencies
 /node_modules/
diff --git a/yarn.lock b/yarn.lock
index 9f750f281e..9e3f3210ca 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5563,6 +5563,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@ember/string@npm:^4.0.0":
+  version: 4.0.1
+  resolution: "@ember/string@npm:4.0.1"
+  checksum: 10c0/c30f4596d2ea0e64d5e37fd218dc823f35d72329b0cf7645eb86ffb1e55ca257bb3b84924ac11672c8b2d445ba4c8783bb754907921927156e5f6ab9a2731e9c
+  languageName: node
+  linkType: hard
+
 "@ember/test-helpers@npm:^3.3.1":
   version: 3.3.1
   resolution: "@ember/test-helpers@npm:3.3.1"
@@ -8458,33 +8465,34 @@ __metadata:
   resolution: "admin@workspace:ui/admin"
   dependencies:
     "@babel/core": "npm:^7.26.10"
-    "@babel/eslint-parser": "npm:^7.21.3"
-    "@babel/plugin-proposal-decorators": "npm:^7.21.0"
+    "@babel/eslint-parser": "npm:^7.25.1"
+    "@babel/plugin-proposal-decorators": "npm:^7.24.7"
     "@babel/runtime": "npm:7.12.18"
-    "@ember/optional-features": "npm:^2.0.0"
+    "@ember/optional-features": "npm:^2.1.0"
     "@ember/render-modifiers": "npm:^2.0.4"
-    "@ember/string": "npm:^3.0.1"
-    "@ember/test-helpers": "npm:^4.0.5"
+    "@ember/string": "npm:^4.0.0"
+    "@ember/test-helpers": "npm:^3.3.1"
     "@embroider/macros": "npm:^1.16.9"
     "@faker-js/faker": "npm:^8.0.2"
     "@glimmer/component": "npm:^1.1.2"
     "@glimmer/tracking": "npm:^1.1.2"
     "@hashicorp/ember-asciinema-player": "https://github.com/hashicorp/ember-asciinema-player.git#e047a096039cff70234c232efe75dcad74c6358a"
     "@warp-drive/build-config": "npm:^0.0.2"
-    babel-loader: "npm:^9.2.1"
     broccoli-asset-rev: "npm:^3.0.0"
     concurrently: "npm:^9.1.0"
     core: "workspace:*"
     doctoc: "npm:^2.2.0"
     ember-a11y-testing: "npm:^7.0.0"
     ember-auto-import: "npm:^2.10.0"
-    ember-cli: "npm:^5.12.0"
+    ember-cli: "npm:~5.12.0"
+    ember-cli-app-version: "npm:^7.0.0"
     ember-cli-babel: "npm:^8.2.0"
+    ember-cli-clean-css: "npm:^3.0.0"
     ember-cli-code-coverage: "npm:^1.0.3"
     ember-cli-content-security-policy: "npm:^2.0.3"
     ember-cli-dependency-checker: "npm:^3.3.2"
     ember-cli-flash: "npm:^4.0.0"
-    ember-cli-htmlbars: "npm:^6.2.0"
+    ember-cli-htmlbars: "npm:^6.3.0"
     ember-cli-inject-live-reload: "npm:^2.1.0"
     ember-cli-sass: "npm:^11.0.1"
     ember-cli-sri: "npm:^2.1.1"
@@ -8493,34 +8501,35 @@ __metadata:
     ember-exam: "npm:^8.0.0"
     ember-inline-svg: "npm:^1.0.1"
     ember-load-initializers: "npm:^2.1.2"
-    ember-modifier: "npm:^4.1.0"
+    ember-modifier: "npm:^4.2.0"
     ember-named-blocks-polyfill: "npm:^0.2.5"
-    ember-page-title: "npm:^7.0.0"
+    ember-page-title: "npm:^8.2.3"
     ember-qunit: "npm:^8.1.0"
-    ember-resolver: "npm:^10.0.0"
-    ember-source: "npm:~4.12.0"
-    ember-template-lint: "npm:^5.7.2"
+    ember-resolver: "npm:^12.0.1"
+    ember-source: "npm:~5.12.0"
+    ember-template-lint: "npm:^6.0.0"
     ember-template-lint-plugin-prettier: "npm:^5.0.0"
-    eslint: "npm:^8.54.0"
-    eslint-config-prettier: "npm:^9.0.0"
-    eslint-plugin-ember: "npm:^11.11.1"
-    eslint-plugin-n: "npm:^16.3.1"
-    eslint-plugin-qunit: "npm:^8.0.1"
+    eslint: "npm:^8.57.1"
+    eslint-config-prettier: "npm:^9.1.0"
+    eslint-plugin-ember: "npm:^12.2.1"
+    eslint-plugin-n: "npm:^16.6.2"
+    eslint-plugin-prettier: "npm:^5.2.1"
+    eslint-plugin-qunit: "npm:^8.1.2"
     js-bexpr: "hashicorp/js-bexpr#9b4a4b54d85eba67fdfc0990133d1518d890b1e1"
     loader.js: "npm:^4.7.0"
     lodash: "npm:^4.17.21"
     postcss: "npm:^8.4.31"
-    prettier: "npm:^3.0.0"
+    prettier: "npm:^3.3.3"
     qunit: "npm:^2.22.0"
     qunit-dom: "npm:^3.2.1"
     rose: "workspace:*"
     sinon: "npm:^19.0.2"
-    stylelint: "npm:^15.10.1"
+    stylelint: "npm:^15.11.0"
     stylelint-config-prettier-scss: "npm:^0.0.1"
     stylelint-config-standard-scss: "npm:^11.0.0"
-    tracked-built-ins: "npm:^3.1.1"
+    tracked-built-ins: "npm:^3.3.0"
     uuid: "npm:^11.0.3"
-    webpack: "npm:^5.94.0"
+    webpack: "npm:^5.95.0"
   languageName: unknown
   linkType: soft
 
@@ -12534,6 +12543,18 @@ __metadata:
   languageName: node
   linkType: hard
 
+"ember-cli-app-version@npm:^7.0.0":
+  version: 7.0.0
+  resolution: "ember-cli-app-version@npm:7.0.0"
+  dependencies:
+    ember-cli-babel: "npm:^7.26.11"
+    git-repo-info: "npm:^2.1.1"
+  peerDependencies:
+    ember-source: ^3.28.0 || >= 4.0.0
+  checksum: 10c0/6c3d31f74dd03d43c6b80d1496474daeace7799ce3f51f0273f5a728650a274adf2f0701cea7a42b238aafbfbcc00f7517fd10293ca46484efb2354288f2b733
+  languageName: node
+  linkType: hard
+
 "ember-cli-babel-plugin-helpers@npm:^1.0.0, ember-cli-babel-plugin-helpers@npm:^1.1.0, ember-cli-babel-plugin-helpers@npm:^1.1.1":
   version: 1.1.1
   resolution: "ember-cli-babel-plugin-helpers@npm:1.1.1"
@@ -24995,6 +25016,17 @@ __metadata:
   languageName: node
   linkType: hard
 
+"tracked-built-ins@npm:^3.3.0":
+  version: 3.4.0
+  resolution: "tracked-built-ins@npm:3.4.0"
+  dependencies:
+    "@embroider/addon-shim": "npm:^1.8.7"
+    decorator-transforms: "npm:^2.0.0"
+    ember-tracked-storage-polyfill: "npm:^1.0.0"
+  checksum: 10c0/db53509dd5910d0472976593a2b2ce3fc27f6e81c73eea850fbfdc2deafe5b64aa2dca6bcb1c727a3761dbdc182e7ec2da3243e83c82164e87ec47b61caa802d
+  languageName: node
+  linkType: hard
+
 "tracked-maps-and-sets@npm:^3.0.2":
   version: 3.0.2
   resolution: "tracked-maps-and-sets@npm:3.0.2"


Reviews:
user: login: hashicc
body: 🕺 One question but no blockers at all. Nice work, thanks for the upgrade. I can't wait to use the new toys. I noticed `@ember/test-helpers` was downgraded but I have #2797 that I want to rebase after all the ember upgrade work that'll get all `@ember/test-helpers` in the monorepo to v5
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-25T13:48:22Z
user: login: lisbet-alvarez
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-25T16:49:39Z
user: login: cameronperera
body: 🎉 
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-25T18:48:18Z
user: login: DhariniJeeva
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-25T18:54:16Z
user: login: DhariniJeeva
body: Thanks for the work! looks good to me
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-25T18:54:32Z
user: login: lisbet-alvarez
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-25T18:59:45Z

Review comments:
diff_hunk: @@ -32,7 +32,9 @@ module('Unit | Instance Initializer | feature-edition', function (hooks) {
   });
 
   hooks.afterEach(function () {
+    // eslint-disable-next-line ember/no-runloop
     run(this.instance, 'destroy');
+    // eslint-disable-next-line ember/no-runloop
     run(this.application, 'destroy');
   });
 
path: ui/admin/tests/unit/instance-initializers/feature-edition-test.js
user: login: hashicc
body: This test _does_ test that the initializer succeeds but doesn't assert anything else. I'm guessing this was just the blueprint test. This one does have some value maybe more than other generated tests. As a team do we generally commit and keep these `"it works"` tests?
created_at: 2025-04-25T13:46:53Z
author_association: COLLABORATOR
diff_hunk: @@ -32,7 +32,9 @@ module('Unit | Instance Initializer | feature-edition', function (hooks) {
   });
 
   hooks.afterEach(function () {
+    // eslint-disable-next-line ember/no-runloop
     run(this.instance, 'destroy');
+    // eslint-disable-next-line ember/no-runloop
     run(this.application, 'destroy');
   });
 
path: ui/admin/tests/unit/instance-initializers/feature-edition-test.js
user: login: lisbet-alvarez
body: Yes, that is correct its the blueprint tests and, yup at the very minimum we keep the test file with the generated test case. The same thing can be observed for controller, and route unit tests. But, we should be adding more test cases where ever possible. 
created_at: 2025-04-25T16:49:39Z
author_association: COLLABORATOR
diff_hunk: @@ -2,5 +2,6 @@
   "application-template-wrapper": false,
   "default-async-observers": true,
   "jquery-integration": false,
-  "template-only-glimmer-components": true
+  "template-only-glimmer-components": true,
+  "no-implicit-route-model": true
path: ui/admin/config/optional-features.json
user: login: cameronperera
body: learning: We need this because we previously relied on the fact that if you don't define a model hook for a route, it will use the model from the parent route correct?
created_at: 2025-04-25T18:46:33Z
author_association: COLLABORATOR
diff_hunk: @@ -16,8 +16,8 @@
     "build:oss": "EDITION=oss ember build --environment=production",
     "build:enterprise": "EDITION=enterprise ember build --environment=production",
     "build:hcp": "EDITION=hcp ember build --environment=production",
-    "lint": "concurrently \"npm:lint:*(!fix)\" --names \"lint:\"",
-    "lint:fix": "concurrently \"npm:lint:*:fix\" --names \"fix:\"",
+    "lint": "concurrently \"yarn:lint:*(!fix)\" --names \"lint:\"",
path: ui/admin/package.json
user: login: DhariniJeeva
body: good catch!
created_at: 2025-04-25T18:54:16Z
author_association: COLLABORATOR
diff_hunk: @@ -2,5 +2,6 @@
   "application-template-wrapper": false,
   "default-async-observers": true,
   "jquery-integration": false,
-  "template-only-glimmer-components": true
+  "template-only-glimmer-components": true,
+  "no-implicit-route-model": true
path: ui/admin/config/optional-features.json
user: login: lisbet-alvarez
body: When I was initially looking at this deprecation, I had thought the same, but looking closer at the docs it was actually [referring to this behaviour for routes with dynamic segments](https://guides.emberjs.com/v4.7.0/routing/specifying-a-routes-model/#:~:text=If%20you%20do%20not%20define%20a%20model%20hook%20for%20a%20route%2C%20it%20will%20default%20to%20using%20Ember%20Data%20to%20look%20up%20the%20record%2C%20as%20shown%20below%3A).
created_at: 2025-04-25T18:59:45Z
author_association: COLLABORATOR

PR comments:
user: login: vercel[bot]
created_at: 2025-04-23T17:23:50Z
body: [vc]: #TSe7xz02WU9oi4SqUr2ZzviHh6/txgtHOvF7UrzbE9E=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJib3VuZGFyeS11aSIsInJvb3REaXJlY3RvcnkiOiJ1aS9hZG1pbiIsImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS9oYXNoaWNvcnAvYm91bmRhcnktdWkvQk5RS1NKQkJOM0Z2cXR3NzJNcVBSdTJxbU53TCIsInByZXZpZXdVcmwiOiJib3VuZGFyeS11aS1naXQtaWN1LTE2NTQ2LXVwZ3JhZGUtZW1iZXItYWRtaW4tdWktaGFzaGljb3JwLnZlcmNlbC5hcHAiLCJuZXh0Q29tbWl0U3RhdHVzIjoiREVQTE9ZRUQiLCJsaXZlRmVlZGJhY2siOnsicmVzb2x2ZWQiOjAsInVucmVzb2x2ZWQiOjAsInRvdGFsIjowLCJsaW5rIjoiYm91bmRhcnktdWktZ2l0LWljdS0xNjU0Ni11cGdyYWRlLWVtYmVyLWFkbWluLXVpLWhhc2hpY29ycC52ZXJjZWwuYXBwIn19LHsibmFtZSI6ImJvdW5kYXJ5LXVpLWRlc2t0b3AiLCJyb290RGlyZWN0b3J5IjoidWkvZGVza3RvcCIsImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS9oYXNoaWNvcnAvYm91bmRhcnktdWktZGVza3RvcC91U1JOc1F2emcxamQzeENnQnI4aWFOZ3dQV0FXIiwicHJldmlld1VybCI6ImJvdW5kYXJ5LXVpLWRlc2t0b3AtZ2l0LWljdS0xNjU0Ni11cGdyYWRlLWVtYmUtYTE2MzQxLWhhc2hpY29ycC52ZXJjZWwuYXBwIiwibmV4dENvbW1pdFN0YXR1cyI6IkRFUExPWUVEIiwibGl2ZUZlZWRiYWNrIjp7InJlc29sdmVkIjowLCJ1bnJlc29sdmVkIjowLCJ0b3RhbCI6MCwibGluayI6ImJvdW5kYXJ5LXVpLWRlc2t0b3AtZ2l0LWljdS0xNjU0Ni11cGdyYWRlLWVtYmUtYTE2MzQxLWhhc2hpY29ycC52ZXJjZWwuYXBwIn19XX0=
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **boundary-ui** | ✅ Ready ([Inspect](https://vercel.com/hashicorp/boundary-ui/BNQKSJBBN3Fvqtw72MqPRu2qmNwL)) | [Visit Preview](https://boundary-ui-git-icu-16546-upgrade-ember-admin-ui-hashicorp.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/boundary-ui-git-icu-16546-upgrade-ember-admin-ui-hashicorp.vercel.app?via=pr-comment-feedback-link) | Apr 25, 2025 9:16pm |
| **boundary-ui-desktop** | ✅ Ready ([Inspect](https://vercel.com/hashicorp/boundary-ui-desktop/uSRNsQvzg1jd3xCgBr8iaNgwPWAW)) | [Visit Preview](https://boundary-ui-desktop-git-icu-16546-upgrade-embe-a16341-hashicorp.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/boundary-ui-desktop-git-icu-16546-upgrade-embe-a16341-hashicorp.vercel.app?via=pr-comment-feedback-link) | Apr 25, 2025 9:16pm |



author_association: NONE
user: login: lisbet-alvarez
created_at: 2025-04-25T16:59:05Z
body: > I noticed `@ember/test-helpers` was downgraded but I have #2797 that I want to rebase after all the ember upgrade work that'll get all `@ember/test-helpers` in the monorepo to v5

Thats awesome!! Yeah only reason I had to downgrade (& match new blueprints) is because v4 was causing an error in the test env. Funny enough, once upgrading the api addon to v5.12, I can update `@ember/test-helpers` to v4 with no errors.
![image](https://github.com/user-attachments/assets/964fe7a2-7c15-41b4-a0ea-ddc0d6acac15)

author_association: COLLABORATOR