Repository: kubernetes-sigs/kueue

Issue:
Use a framework independant name for the the backend environment variable in kueue-viz
<!-- Please only use this template for submitting clean up requests -->

**What would you like to be cleaned**:
Right now, kueue-viz frontend supports 2 env vars to specify the url of the backend:
- REACT_APP_WEBSOCKET_URL
- VITE_WEBSOCKET_URL

It should be better to have a framework agnostic variable like: `KUEUE_VIZ_BACKEND_WEBSOCKET_URL`

**Why is this needed**:
It should be better to have a framework agnostic variable like: `KUEUE_VIZ_BACKEND_WEBSOCKET_URL`


Discussion:
@akram: /kind dashboard@k8s-triage-robot: The Kubernetes project currently lacks enough contributors to adequately respond to all issues.

This bot triages un-triaged issues according to the following rules:
- After 90d of inactivity, `lifecycle/stale` is applied
- After 30d of inactivity since `lifecycle/stale` was applied, `lifecycle/rotten` is applied
- After 30d of inactivity since `lifecycle/rotten` was applied, the issue is closed

You can:
- Mark this issue as fresh with `/remove-lifecycle stale`
- Close this issue with `/close`
- Offer to help out with [Issue Triage][1]

Please send feedback to sig-contributor-experience at [kubernetes/community](https://github.com/kubernetes/community).

/lifecycle stale

[1]: https://www.kubernetes.dev/docs/guide/issue-triage/@tenzen-y: /remove-lifecycle stale@k8s-triage-robot: The Kubernetes project currently lacks enough contributors to adequately respond to all issues.

This bot triages un-triaged issues according to the following rules:
- After 90d of inactivity, `lifecycle/stale` is applied
- After 30d of inactivity since `lifecycle/stale` was applied, `lifecycle/rotten` is applied
- After 30d of inactivity since `lifecycle/rotten` was applied, the issue is closed

You can:
- Mark this issue as fresh with `/remove-lifecycle stale`
- Close this issue with `/close`
- Offer to help out with [Issue Triage][1]

Please send feedback to sig-contributor-experience at [kubernetes/community](https://github.com/kubernetes/community).

/lifecycle stale

[1]: https://www.kubernetes.dev/docs/guide/issue-triage/@k8s-triage-robot: The Kubernetes project currently lacks enough active contributors to adequately respond to all issues.

This bot triages un-triaged issues according to the following rules:
- After 90d of inactivity, `lifecycle/stale` is applied
- After 30d of inactivity since `lifecycle/stale` was applied, `lifecycle/rotten` is applied
- After 30d of inactivity since `lifecycle/rotten` was applied, the issue is closed

You can:
- Mark this issue as fresh with `/remove-lifecycle rotten`
- Close this issue with `/close`
- Offer to help out with [Issue Triage][1]

Please send feedback to sig-contributor-experience at [kubernetes/community](https://github.com/kubernetes/community).

/lifecycle rotten

[1]: https://www.kubernetes.dev/docs/guide/issue-triage/@k8s-triage-robot: The Kubernetes project currently lacks enough active contributors to adequately respond to all issues and PRs.

This bot triages issues according to the following rules:
- After 90d of inactivity, `lifecycle/stale` is applied
- After 30d of inactivity since `lifecycle/stale` was applied, `lifecycle/rotten` is applied
- After 30d of inactivity since `lifecycle/rotten` was applied, the issue is closed

You can:
- Reopen this issue with `/reopen`
- Mark this issue as fresh with `/remove-lifecycle rotten`
- Offer to help out with [Issue Triage][1]

Please send feedback to sig-contributor-experience at [kubernetes/community](https://github.com/kubernetes/community).

/close not-planned

[1]: https://www.kubernetes.dev/docs/guide/issue-triage/@k8s-ci-robot: @k8s-triage-robot: Closing this issue, marking it as "Not Planned".

<details>

In response to [this](https://github.com/kubernetes-sigs/kueue/issues/4578#issuecomment-3506122357):

>The Kubernetes project currently lacks enough active contributors to adequately respond to all issues and PRs.
>
>This bot triages issues according to the following rules:
>- After 90d of inactivity, `lifecycle/stale` is applied
>- After 30d of inactivity since `lifecycle/stale` was applied, `lifecycle/rotten` is applied
>- After 30d of inactivity since `lifecycle/rotten` was applied, the issue is closed
>
>You can:
>- Reopen this issue with `/reopen`
>- Mark this issue as fresh with `/remove-lifecycle rotten`
>- Offer to help out with [Issue Triage][1]
>
>Please send feedback to sig-contributor-experience at [kubernetes/community](https://github.com/kubernetes/community).
>
>/close not-planned
>
>[1]: https://www.kubernetes.dev/docs/guide/issue-triage/


Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository.
</details>

Solution patch:
diff --git a/apis/config/v1beta1/configuration_types.go b/apis/config/v1beta1/configuration_types.go
index 9acb2c619..d2484a6d4 100644
--- a/apis/config/v1beta1/configuration_types.go
+++ b/apis/config/v1beta1/configuration_types.go
@@ -318,9 +318,16 @@ const (
 )
 
 type InternalCertManagement struct {
-	// Enable controls whether to enable internal cert management or not.
-	// Defaults to true. If you want to use a third-party management, e.g. cert-manager,
-	// set it to false. See the user guide for more information.
+	// Enable controls the use of internal cert management for the webhook
+	// and metrics endpoints.
+	// When enabled Kueue is using libraries to generate and
+	// self-sign the certificates.
+	// When disabled, you need to provide the certificates for
+	// the webhooks and metrics through a third party certificate
+	// This secret is mounted to the kueue controller manager pod. The mount
+	// path for webhooks is /tmp/k8s-webhook-server/serving-certs, whereas for
+	// metrics endpoint the expected path is `/etc/kueue/metrics/certs`.
+	// The keys and certs are named tls.key and tls.crt.
 	Enable *bool `json:"enable,omitempty"`
 
 	// WebhookServiceName is the name of the Service used as part of the DNSName.
diff --git a/apis/kueue/v1alpha1/tas_types.go b/apis/kueue/v1alpha1/tas_types.go
index 5538b2d61..84ba98f03 100644
--- a/apis/kueue/v1alpha1/tas_types.go
+++ b/apis/kueue/v1alpha1/tas_types.go
@@ -38,6 +38,14 @@ const (
 	// among multiple topology domains.
 	PodSetPreferredTopologyAnnotation = "kueue.x-k8s.io/podset-preferred-topology"
 
+	// PodSetUnconstrainedTopologyAnnotation indicates that a PodSet does not have any topology requirements.
+	// Kueue admits the PodSet if there's enough free capacity available.
+	// Recommended for PodSets that don't need low-latency or high-throughput pod-to-pod communication,
+	// but want to leverage TAS capabilities improve accuracy of admitting jobs
+	//
+	// +kubebuilder:validation:Type=boolean
+	PodSetUnconstrainedTopologyAnnotation = "kueue.x-k8s.io/podset-unconstrained-topology"
+
 	// TopologySchedulingGate is used to delay scheduling of a Pod until the
 	// nodeSelectors corresponding to the assigned topology domain are injected
 	// into the Pod. For the Pod-based integrations the gate is added in webhook
diff --git a/apis/kueue/v1beta1/workload_types.go b/apis/kueue/v1beta1/workload_types.go
index be31e10ce..db8a7c2b1 100644
--- a/apis/kueue/v1beta1/workload_types.go
+++ b/apis/kueue/v1beta1/workload_types.go
@@ -104,6 +104,14 @@ type PodSetTopologyRequest struct {
 	// +optional
 	Preferred *string `json:"preferred,omitempty"`
 
+	// unconstrained indicates that Kueue has the freedom to schedule the PodSet within
+	// the entire available capacity, without constraints on the compactness of the placement.
+	// This is indicated by the `kueue.x-k8s.io/podset-unconstrained-topology` PodSet annotation.
+	//
+	// +optional
+	// +kubebuilder:validation:Type=boolean
+	Unconstrained *bool `json:"unconstrained,omitempty"`
+
 	// PodIndexLabel indicates the name of the label indexing the pods.
 	// For example, in the context of
 	// - kubernetes job this is: kubernetes.io/job-completion-index
diff --git a/apis/kueue/v1beta1/zz_generated.deepcopy.go b/apis/kueue/v1beta1/zz_generated.deepcopy.go
index 19af8c5e5..b6ab50c9f 100644
--- a/apis/kueue/v1beta1/zz_generated.deepcopy.go
+++ b/apis/kueue/v1beta1/zz_generated.deepcopy.go
@@ -1055,6 +1055,11 @@ func (in *PodSetTopologyRequest) DeepCopyInto(out *PodSetTopologyRequest) {
 		*out = new(string)
 		**out = **in
 	}
+	if in.Unconstrained != nil {
+		in, out := &in.Unconstrained, &out.Unconstrained
+		*out = new(bool)
+		**out = **in
+	}
 	if in.PodIndexLabel != nil {
 		in, out := &in.PodIndexLabel, &out.PodIndexLabel
 		*out = new(string)
diff --git a/charts/kueue/templates/certmanager/certificatemetrics.yaml b/charts/kueue/templates/certmanager/certificatemetrics.yaml
new file mode 100644
index 000000000..4c5cf15fb
--- /dev/null
+++ b/charts/kueue/templates/certmanager/certificatemetrics.yaml
@@ -0,0 +1,17 @@
+{{- if .Values.enableCertManager }}
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+  name: {{ include "kueue.fullname" . }}-metrics-cert
+  namespace: '{{ .Release.Namespace }}'
+  labels:
+  {{- include "kueue.labels" . | nindent 4 }}
+spec:
+  dnsNames:
+  - '{{ include "kueue.fullname" . }}-controller-manager-metrics-service.{{ .Release.Namespace }}.svc'
+  - '{{ include "kueue.fullname" . }}-controller-manager-metrics-service.{{ .Release.Namespace }}.svc.{{ .Values.kubernetesClusterDomain }}'
+  issuerRef:
+    kind: Issuer
+    name: {{ include "kueue.fullname" . }}-selfsigned-issuer
+  secretName: {{ include "kueue.fullname" . }}-metrics-server-cert
+{{- end }}
\ No newline at end of file
diff --git a/charts/kueue/templates/crd/kueue.x-k8s.io_workloads.yaml b/charts/kueue/templates/crd/kueue.x-k8s.io_workloads.yaml
index 03a39b556..5767c72f3 100644
--- a/charts/kueue/templates/crd/kueue.x-k8s.io_workloads.yaml
+++ b/charts/kueue/templates/crd/kueue.x-k8s.io_workloads.yaml
@@ -8329,6 +8329,12 @@ spec:
                             SubGroupIndexLabel indicates the name of the label indexing the instances of replicated Jobs (groups)
                             within a PodSet. For example, in the context of JobSet this is jobset.sigs.k8s.io/job-index.
                           type: string
+                        unconstrained:
+                          description: |-
+                            unconstrained indicates that Kueue has the freedom to schedule the PodSet within
+                            the entire available capacity, without constraints on the compactness of the placement.
+                            This is indicated by the `kueue.x-k8s.io/podset-unconstrained-topology` PodSet annotation.
+                          type: boolean
                       type: object
                   required:
                   - count
diff --git a/charts/kueue/templates/manager/manager.yaml b/charts/kueue/templates/manager/manager.yaml
index b1be101ff..06dff5922 100644
--- a/charts/kueue/templates/manager/manager.yaml
+++ b/charts/kueue/templates/manager/manager.yaml
@@ -70,6 +70,11 @@ spec:
         - mountPath: /controller_manager_config.yaml
           name: manager-config
           subPath: controller_manager_config.yaml
+        {{- if .Values.enableCertManager }}
+        - mountPath: /etc/kueue/metrics/certs
+          name: metrics-certs
+          readOnly: true
+        {{- end }}
       securityContext:
         {{- toYaml .Values.controllerManager.manager.podSecurityContext | nindent 8 }}
       serviceAccountName: {{ include "kueue.fullname" . }}-controller-manager
@@ -87,6 +92,19 @@ spec:
         secret:
           defaultMode: 420
           secretName: {{ include "kueue.fullname" . }}-webhook-server-cert
-      - configMap:
+      - name: manager-config
+        configMap:
           name: {{ include "kueue.fullname" . }}-manager-config
-        name: manager-config
+      {{- if .Values.enableCertManager }}
+      - name: metrics-certs
+        secret:
+          secretName: {{ include "kueue.fullname" . }}-metrics-server-cert
+          optional: false
+          items:
+          - key: ca.crt
+            path: ca.crt
+          - key: tls.crt
+            path: tls.crt
+          - key: tls.key
+            path: tls.key
+      {{- end }}
diff --git a/charts/kueue/templates/prometheus/monitor.yaml b/charts/kueue/templates/prometheus/monitor.yaml
index 6798ae63a..7ce986f29 100644
--- a/charts/kueue/templates/prometheus/monitor.yaml
+++ b/charts/kueue/templates/prometheus/monitor.yaml
@@ -12,8 +12,7 @@ spec:
     path: /metrics
     port: https
     scheme: https
-    tlsConfig:
-      insecureSkipVerify: true
+    tlsConfig: {{- toYaml .Values.metrics.serviceMonitor.tlsConfig | nindent 6 }}
   selector:
     matchLabels:
     {{- include "kueue.labels" . | nindent 6 }}
diff --git a/charts/kueue/values.yaml b/charts/kueue/values.yaml
index 06360e595..18518abfc 100644
--- a/charts/kueue/values.yaml
+++ b/charts/kueue/values.yaml
@@ -156,3 +156,6 @@ enableKueueViz: false
 
 metrics:
   prometheusNamespace: monitoring
+  serviceMonitor:
+    tlsConfig:
+      insecureSkipVerify: true
diff --git a/client-go/applyconfiguration/kueue/v1beta1/podsettopologyrequest.go b/client-go/applyconfiguration/kueue/v1beta1/podsettopologyrequest.go
index 906eef5ad..3756f7181 100644
--- a/client-go/applyconfiguration/kueue/v1beta1/podsettopologyrequest.go
+++ b/client-go/applyconfiguration/kueue/v1beta1/podsettopologyrequest.go
@@ -22,6 +22,7 @@ package v1beta1
 type PodSetTopologyRequestApplyConfiguration struct {
 	Required           *string `json:"required,omitempty"`
 	Preferred          *string `json:"preferred,omitempty"`
+	Unconstrained      *bool   `json:"unconstrained,omitempty"`
 	PodIndexLabel      *string `json:"podIndexLabel,omitempty"`
 	SubGroupIndexLabel *string `json:"subGroupIndexLabel,omitempty"`
 	SubGroupCount      *int32  `json:"subGroupCount,omitempty"`
@@ -49,6 +50,14 @@ func (b *PodSetTopologyRequestApplyConfiguration) WithPreferred(value string) *P
 	return b
 }
 
+// WithUnconstrained sets the Unconstrained field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the Unconstrained field is set to the value of the last call.
+func (b *PodSetTopologyRequestApplyConfiguration) WithUnconstrained(value bool) *PodSetTopologyRequestApplyConfiguration {
+	b.Unconstrained = &value
+	return b
+}
+
 // WithPodIndexLabel sets the PodIndexLabel field in the declarative configuration to the given value
 // and returns the receiver, so that objects can be built by chaining "With" function invocations.
 // If called multiple times, the PodIndexLabel field is set to the value of the last call.
diff --git a/cmd/experimental/kueue-viz/frontend/.dockerignore b/cmd/experimental/kueue-viz/frontend/.dockerignore
new file mode 100644
index 000000000..a031a9e8c
--- /dev/null
+++ b/cmd/experimental/kueue-viz/frontend/.dockerignore
@@ -0,0 +1,7 @@
+.gitignore
+.git
+.env*
+*.log
+node_modules
+build
+README.md
diff --git a/cmd/experimental/kueue-viz/frontend/.env b/cmd/experimental/kueue-viz/frontend/.env
index c2f275d40..84e794bfc 100644
--- a/cmd/experimental/kueue-viz/frontend/.env
+++ b/cmd/experimental/kueue-viz/frontend/.env
@@ -1 +1,2 @@
+VITE_WEBSOCKET_URL=ws://localhost:8080
 REACT_APP_WEBSOCKET_URL=ws://localhost:8080
diff --git a/cmd/experimental/kueue-viz/frontend/Dockerfile b/cmd/experimental/kueue-viz/frontend/Dockerfile
index 4319f5e70..e9843148a 100644
--- a/cmd/experimental/kueue-viz/frontend/Dockerfile
+++ b/cmd/experimental/kueue-viz/frontend/Dockerfile
@@ -1,19 +1,36 @@
-#Build the React app
-FROM node:23 AS build
+# Build stage
+FROM node:23 AS builder
 
-ENV NPM_CONFIG_CACHE=/tmp/.npm-cache
+# Set working directory
 WORKDIR /app
+
+# Copy package files
 COPY package*.json ./
+
+# Install ALL dependencies (including dev dependencies needed for build)
 RUN npm install
+
+# Copy source files
 COPY . .
 
-# Build the production-ready static files
+# Build the app
 RUN npm run build
-RUN mkdir -p build && touch build/env.js && chmod ugo+rw -R build/ $NPM_CONFIG_CACHE
-EXPOSE 8080
 
-# Use react-inject-env to be able to inject env vars at runtime
-ENTRYPOINT npx react-inject-env set && npx http-server build
+# Runtime stage
+FROM node:23 AS runtime
 
+WORKDIR /app
+
+# Install serve for production static file serving
+RUN npm install -g serve
+
+# Copy only the built files from builder
+COPY --from=builder /app/build ./build
+COPY start.sh /app/start.sh
+RUN chmod +x /app/start.sh
+
+EXPOSE 8080
 
+# Use the start script
+ENTRYPOINT ["/app/start.sh"]
 
diff --git a/cmd/experimental/kueue-viz/frontend/index.html b/cmd/experimental/kueue-viz/frontend/index.html
new file mode 100644
index 000000000..c01300ff1
--- /dev/null
+++ b/cmd/experimental/kueue-viz/frontend/index.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <script src='/env.js'></script>
+    <meta charset="utf-8" />
+    <link rel="icon" href="/favicon.ico" />
+    <meta name="viewport" content="width=device-width, initial-scale=1" />
+    <meta name="theme-color" content="#000000" />
+    <meta
+      name="description"
+      content="Kueue Visualization Dashboard"
+    />
+    <title>Kueue Dashboard</title>
+  </head>
+  <body>
+    <noscript>You need to enable JavaScript to run this app.</noscript>
+    <div id="root"></div>
+    <script type="module" src="/src/index.jsx"></script>
+  </body>
+</html> 
\ No newline at end of file
diff --git a/cmd/experimental/kueue-viz/frontend/package.json b/cmd/experimental/kueue-viz/frontend/package.json
index 172e22de2..4009d56df 100644
--- a/cmd/experimental/kueue-viz/frontend/package.json
+++ b/cmd/experimental/kueue-viz/frontend/package.json
@@ -3,26 +3,30 @@
   "version": "1.0.0",
   "private": true,
   "description": "Frontend dashboard for visualizing Kueue status",
-  "main": "src/index.js",
+  "main": "src/index.jsx",
+  "type": "module",
   "scripts": {
-    "start": "SKIP_PREFLIGHT_CHECK=true react-scripts start",
-    "build": "SKIP_PREFLIGHT_CHECK=true react-scripts build"
+    "start": "vite",
+    "build": "vite build",
+    "preview": "vite preview",
+    "check-unused": "depcheck"
   },
   "dependencies": {
-    "@emotion/react": "^11.0.0",
-    "@emotion/styled": "^11.0.0",
-    "@mui/icons-material": "^6.4.6",
-    "@mui/material": "^6.4.6",
-    "axios": "^1.7.9",
+    "@emotion/react": "^11.14.0",
+    "@emotion/styled": "^11.14.0",
+    "@mui/icons-material": "^6.4.7",
+    "@mui/material": "^6.4.7",
+    "axios": "^1.8.3",
     "react": "^19.0.0",
     "react-dom": "^19.0.0",
-    "react-router-dom": "^7.0.2",
-    "react-scripts": "^5.0.0",
-    "react-toastify": "^11.0.2"
+    "react-router-dom": "^7.3.0",
+    "react-toastify": "^11.0.5"
   },
   "devDependencies": {
-    "@babel/plugin-proposal-private-property-in-object": "7.21.11",
-    "react-inject-env": "^2.1.0"
+    "@vitejs/plugin-react": "^4.3.4",
+    "depcheck": "^1.4.7",
+    "serve": "^14.2.4",
+    "vite": "^6.2.1"
   },
   "browserslist": {
     "production": [
diff --git a/cmd/experimental/kueue-viz/frontend/public/env.js b/cmd/experimental/kueue-viz/frontend/public/env.js
index 63649a035..264a57b2e 100644
--- a/cmd/experimental/kueue-viz/frontend/public/env.js
+++ b/cmd/experimental/kueue-viz/frontend/public/env.js
@@ -14,6 +14,9 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-export const env = { ...process.env, ...window['env'] }
+window.env = window.env || {
+  VITE_WEBSOCKET_URL: 'ws://localhost:8080',
+  REACT_APP_WEBSOCKET_URL: 'ws://localhost:8080'
+};
 
 
diff --git a/cmd/experimental/kueue-viz/frontend/src/App.js b/cmd/experimental/kueue-viz/frontend/src/App.jsx
similarity index 100%
rename from cmd/experimental/kueue-viz/frontend/src/App.js
rename to cmd/experimental/kueue-viz/frontend/src/App.jsx
diff --git a/cmd/experimental/kueue-viz/frontend/src/ClusterQueueDetail.js b/cmd/experimental/kueue-viz/frontend/src/ClusterQueueDetail.jsx
similarity index 100%
rename from cmd/experimental/kueue-viz/frontend/src/ClusterQueueDetail.js
rename to cmd/experimental/kueue-viz/frontend/src/ClusterQueueDetail.jsx
diff --git a/cmd/experimental/kueue-viz/frontend/src/ClusterQueues.js b/cmd/experimental/kueue-viz/frontend/src/ClusterQueues.jsx
similarity index 100%
rename from cmd/experimental/kueue-viz/frontend/src/ClusterQueues.js
rename to cmd/experimental/kueue-viz/frontend/src/ClusterQueues.jsx
diff --git a/cmd/experimental/kueue-viz/frontend/src/CohortDetail.js b/cmd/experimental/kueue-viz/frontend/src/CohortDetail.jsx
similarity index 100%
rename from cmd/experimental/kueue-viz/frontend/src/CohortDetail.js
rename to cmd/experimental/kueue-viz/frontend/src/CohortDetail.jsx
diff --git a/cmd/experimental/kueue-viz/frontend/src/Cohorts.js b/cmd/experimental/kueue-viz/frontend/src/Cohorts.jsx
similarity index 100%
rename from cmd/experimental/kueue-viz/frontend/src/Cohorts.js
rename to cmd/experimental/kueue-viz/frontend/src/Cohorts.jsx
diff --git a/cmd/experimental/kueue-viz/frontend/src/Dashboard.js b/cmd/experimental/kueue-viz/frontend/src/Dashboard.jsx
similarity index 100%
rename from cmd/experimental/kueue-viz/frontend/src/Dashboard.js
rename to cmd/experimental/kueue-viz/frontend/src/Dashboard.jsx
diff --git a/cmd/experimental/kueue-viz/frontend/src/FlavorTable.js b/cmd/experimental/kueue-viz/frontend/src/FlavorTable.jsx
similarity index 100%
rename from cmd/experimental/kueue-viz/frontend/src/FlavorTable.js
rename to cmd/experimental/kueue-viz/frontend/src/FlavorTable.jsx
diff --git a/cmd/experimental/kueue-viz/frontend/src/LocalQueueDetail.js b/cmd/experimental/kueue-viz/frontend/src/LocalQueueDetail.jsx
similarity index 100%
rename from cmd/experimental/kueue-viz/frontend/src/LocalQueueDetail.js
rename to cmd/experimental/kueue-viz/frontend/src/LocalQueueDetail.jsx
diff --git a/cmd/experimental/kueue-viz/frontend/src/LocalQueues.js b/cmd/experimental/kueue-viz/frontend/src/LocalQueues.jsx
similarity index 100%
rename from cmd/experimental/kueue-viz/frontend/src/LocalQueues.js
rename to cmd/experimental/kueue-viz/frontend/src/LocalQueues.jsx
diff --git a/cmd/experimental/kueue-viz/frontend/src/Navbar.js b/cmd/experimental/kueue-viz/frontend/src/Navbar.jsx
similarity index 100%
rename from cmd/experimental/kueue-viz/frontend/src/Navbar.js
rename to cmd/experimental/kueue-viz/frontend/src/Navbar.jsx
diff --git a/cmd/experimental/kueue-viz/frontend/src/ResourceFlavorDetail.js b/cmd/experimental/kueue-viz/frontend/src/ResourceFlavorDetail.jsx
similarity index 100%
rename from cmd/experimental/kueue-viz/frontend/src/ResourceFlavorDetail.js
rename to cmd/experimental/kueue-viz/frontend/src/ResourceFlavorDetail.jsx
diff --git a/cmd/experimental/kueue-viz/frontend/src/ResourceFlavors.js b/cmd/experimental/kueue-viz/frontend/src/ResourceFlavors.jsx
similarity index 100%
rename from cmd/experimental/kueue-viz/frontend/src/ResourceFlavors.js
rename to cmd/experimental/kueue-viz/frontend/src/ResourceFlavors.jsx
diff --git a/cmd/experimental/kueue-viz/frontend/src/WorkloadDetail.js b/cmd/experimental/kueue-viz/frontend/src/WorkloadDetail.jsx
similarity index 100%
rename from cmd/experimental/kueue-viz/frontend/src/WorkloadDetail.js
rename to cmd/experimental/kueue-viz/frontend/src/WorkloadDetail.jsx
diff --git a/cmd/experimental/kueue-viz/frontend/src/Workloads.js b/cmd/experimental/kueue-viz/frontend/src/Workloads.jsx
similarity index 100%
rename from cmd/experimental/kueue-viz/frontend/src/Workloads.js
rename to cmd/experimental/kueue-viz/frontend/src/Workloads.jsx
diff --git a/cmd/experimental/kueue-viz/frontend/src/WorkloadsList.js b/cmd/experimental/kueue-viz/frontend/src/WorkloadsList.jsx
similarity index 100%
rename from cmd/experimental/kueue-viz/frontend/src/WorkloadsList.js
rename to cmd/experimental/kueue-viz/frontend/src/WorkloadsList.jsx
diff --git a/cmd/experimental/kueue-viz/frontend/src/env.js b/cmd/experimental/kueue-viz/frontend/src/env.js
index 63649a035..607281aa6 100644
--- a/cmd/experimental/kueue-viz/frontend/src/env.js
+++ b/cmd/experimental/kueue-viz/frontend/src/env.js
@@ -14,6 +14,10 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-export const env = { ...process.env, ...window['env'] }
+// Combine Vite's environment variables with window.env
+export const env = { 
+  ...import.meta.env,
+  ...(window['env'] || {})
+}
 
 
diff --git a/cmd/experimental/kueue-viz/frontend/src/index.js b/cmd/experimental/kueue-viz/frontend/src/index.jsx
similarity index 100%
rename from cmd/experimental/kueue-viz/frontend/src/index.js
rename to cmd/experimental/kueue-viz/frontend/src/index.jsx
diff --git a/cmd/experimental/kueue-viz/frontend/start.sh b/cmd/experimental/kueue-viz/frontend/start.sh
new file mode 100755
index 000000000..ff130547b
--- /dev/null
+++ b/cmd/experimental/kueue-viz/frontend/start.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+# Copyright The Kubernetes Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Generate env.js with runtime environment variables
+cat << EOF > ./build/env.js
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+window.env = {
+  VITE_WEBSOCKET_URL: "${REACT_APP_WEBSOCKET_URL:-ws://localhost:8080}",
+  REACT_APP_WEBSOCKET_URL: "${REACT_APP_WEBSOCKET_URL:-ws://localhost:8080}"
+};
+EOF
+
+# Start the server
+exec serve -s build -l 8080 
diff --git a/cmd/experimental/kueue-viz/frontend/vite.config.js b/cmd/experimental/kueue-viz/frontend/vite.config.js
new file mode 100644
index 000000000..97c9ffa5e
--- /dev/null
+++ b/cmd/experimental/kueue-viz/frontend/vite.config.js
@@ -0,0 +1,19 @@
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+
+export default defineConfig({
+  plugins: [react()],
+  server: {
+    port: 3000, // Same port as react-scripts for consistency
+    open: true,
+  },
+  build: {
+    outDir: 'build', // Same output directory as react-scripts
+    sourcemap: true,
+  },
+  resolve: {
+    extensions: ['.js', '.jsx', '.json'],
+  },
+  publicDir: 'public',
+  envPrefix: ['VITE_', 'REACT_APP_'], // Support both VITE_ and REACT_APP_ prefixes
+}); 
\ No newline at end of file
diff --git a/cmd/kueue/main.go b/cmd/kueue/main.go
index afd6baf80..e132a090c 100644
--- a/cmd/kueue/main.go
+++ b/cmd/kueue/main.go
@@ -18,10 +18,12 @@ package main
 
 import (
 	"context"
+	"crypto/tls"
 	"errors"
 	"flag"
 	"net/http"
 	"os"
+	"path/filepath"
 
 	zaplog "go.uber.org/zap"
 	"go.uber.org/zap/zapcore"
@@ -39,6 +41,7 @@ import (
 	"k8s.io/client-go/util/flowcontrol"
 	"k8s.io/utils/ptr"
 	ctrl "sigs.k8s.io/controller-runtime"
+	"sigs.k8s.io/controller-runtime/pkg/certwatcher"
 	"sigs.k8s.io/controller-runtime/pkg/healthz"
 	"sigs.k8s.io/controller-runtime/pkg/log/zap"
 	"sigs.k8s.io/controller-runtime/pkg/metrics/filters"
@@ -153,6 +156,26 @@ func main() {
 		SecureServing:  true,
 		FilterProvider: filters.WithAuthenticationAndAuthorization,
 	}
+
+	if cfg.InternalCertManagement == nil || !*cfg.InternalCertManagement.Enable {
+		metricsCertPath := "/etc/kueue/metrics/certs"
+		setupLog.Info("Initializing metrics certificate watcher using provided certificates",
+			"metrics-cert-path", metricsCertPath)
+
+		var err error
+		metricsCertWatcher, err := certwatcher.New(
+			filepath.Join(metricsCertPath, "tls.crt"),
+			filepath.Join(metricsCertPath, "tls.key"),
+		)
+		if err != nil {
+			setupLog.Error(err, "Unable to initialize metrics certificate watcher")
+			os.Exit(1)
+		}
+
+		metricsServerOptions.TLSOpts = append(metricsServerOptions.TLSOpts, func(config *tls.Config) {
+			config.GetCertificate = metricsCertWatcher.GetCertificate
+		})
+	}
 	options.Metrics = metricsServerOptions
 
 	metrics.Register()
diff --git a/config/components/certmanager/certificate-metrics.yaml b/config/components/certmanager/certificate-metrics.yaml
new file mode 100644
index 000000000..958cb7c16
--- /dev/null
+++ b/config/components/certmanager/certificate-metrics.yaml
@@ -0,0 +1,17 @@
+# The following manifests contain a metrics certificate CR.
+# More document can be found at https://docs.cert-manager.io
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+  name: metrics-certs  # this name should match the one appeared in kustomizeconfig.yaml
+  namespace: system
+spec:
+  dnsNames:
+  # SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize
+  # replacements in the config/default/kustomization.yaml file.
+  - SERVICE_NAME.SERVICE_NAMESPACE.svc
+  - SERVICE_NAME.SERVICE_NAMESPACE.svc.cluster.local
+  issuerRef:
+    kind: Issuer
+    name: selfsigned-issuer
+  secretName: metrics-server-cert
diff --git a/config/components/certmanager/kustomization.yaml b/config/components/certmanager/kustomization.yaml
index bebea5a59..fc1018507 100644
--- a/config/components/certmanager/kustomization.yaml
+++ b/config/components/certmanager/kustomization.yaml
@@ -1,5 +1,7 @@
 resources:
 - certificate.yaml
+- certificate-metrics.yaml
+
 
 configurations:
 - kustomizeconfig.yaml
diff --git a/config/components/crd/bases/kueue.x-k8s.io_workloads.yaml b/config/components/crd/bases/kueue.x-k8s.io_workloads.yaml
index 2f79cafed..c879bd310 100644
--- a/config/components/crd/bases/kueue.x-k8s.io_workloads.yaml
+++ b/config/components/crd/bases/kueue.x-k8s.io_workloads.yaml
@@ -8314,6 +8314,12 @@ spec:
                             SubGroupIndexLabel indicates the name of the label indexing the instances of replicated Jobs (groups)
                             within a PodSet. For example, in the context of JobSet this is jobset.sigs.k8s.io/job-index.
                           type: string
+                        unconstrained:
+                          description: |-
+                            unconstrained indicates that Kueue has the freedom to schedule the PodSet within
+                            the entire available capacity, without constraints on the compactness of the placement.
+                            This is indicated by the `kueue.x-k8s.io/podset-unconstrained-topology` PodSet annotation.
+                          type: boolean
                       type: object
                   required:
                   - count
diff --git a/config/components/prometheus/kustomization.yaml b/config/components/prometheus/kustomization.yaml
index 2363f098b..2a9620d35 100644
--- a/config/components/prometheus/kustomization.yaml
+++ b/config/components/prometheus/kustomization.yaml
@@ -1,3 +1,11 @@
 resources:
 - monitor.yaml
 - role.yaml
+# [PROMETHEUS-WITH-CERTS] The following patch configures the ServiceMonitor in ../prometheus
+# to securely reference certificates created and managed by cert-manager.
+# Additionally, ensure that you uncomment the [METRICS WITH CERTMANAGER] patch under config/default/kustomization.yaml
+# to mount the "metrics-server-cert" secret in the Manager Deployment.
+# patches:
+# - path: monitor_tls_patch.yaml
+#   target:
+#     kind: ServiceMonitor
diff --git a/config/components/prometheus/monitor_tls_patch.yaml b/config/components/prometheus/monitor_tls_patch.yaml
new file mode 100644
index 000000000..5bf84ce0d
--- /dev/null
+++ b/config/components/prometheus/monitor_tls_patch.yaml
@@ -0,0 +1,19 @@
+# Patch for Prometheus ServiceMonitor to enable secure TLS configuration
+# using certificates managed by cert-manager
+- op: replace
+  path: /spec/endpoints/0/tlsConfig
+  value:
+    # SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize
+    serverName: SERVICE_NAME.SERVICE_NAMESPACE.svc
+    insecureSkipVerify: false
+    ca:
+      secret:
+        name: metrics-server-cert
+        key: ca.crt
+    cert:
+      secret:
+        name: metrics-server-cert
+        key: tls.crt
+    keySecret:
+      name: metrics-server-cert
+      key: tls.key
diff --git a/config/default/cert_metrics_manager_patch.yaml b/config/default/cert_metrics_manager_patch.yaml
new file mode 100644
index 000000000..78fc5929f
--- /dev/null
+++ b/config/default/cert_metrics_manager_patch.yaml
@@ -0,0 +1,25 @@
+# This patch adds the args, volumes, and ports to allow the manager to use the metrics-server certs.
+
+# Add the volumeMount for the metrics-server certs
+- op: add
+  path: /spec/template/spec/containers/0/volumeMounts/-
+  value:
+    mountPath: /etc/kueue/metrics/certs
+    name: metrics-certs
+    readOnly: true
+
+# Add the metrics-server certs volume configuration
+- op: add
+  path: /spec/template/spec/volumes/-
+  value:
+    name: metrics-certs
+    secret:
+      secretName: metrics-server-cert
+      optional: false
+      items:
+        - key: ca.crt
+          path: ca.crt
+        - key: tls.crt
+          path: tls.crt
+        - key: tls.key
+          path: tls.key
diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml
index c547ad1d3..18a0dc483 100644
--- a/config/default/kustomization.yaml
+++ b/config/default/kustomization.yaml
@@ -29,7 +29,7 @@ resources:
 # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required.
 # - ../components/certmanager
 # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.
-#- ../components/prometheus
+# - ../components/prometheus
 # [METRICS] Expose the controller manager metrics service.
 - metrics_service.yaml
 
@@ -58,6 +58,13 @@ patches:
 # - path: mutating_webhookcainjection_patch.yaml
 # - path: validating_webhookcainjection_patch.yaml
 
+# Uncomment the patches line if you enable Metrics and CertManager
+# [CERTMANAGER] To enable metrics protected with certManager, uncomment the following line.
+# This patch will protect the metrics with certManager self-signed certs.
+# - path: cert_metrics_manager_patch.yaml
+#  target:
+#    kind: Deployment
+
 
 # the following config is for teaching kustomize how to do var substitution
 # vars:
diff --git a/keps/2724-topology-aware-scheduling/README.md b/keps/2724-topology-aware-scheduling/README.md
index 5ec53d106..4eefae794 100644
--- a/keps/2724-topology-aware-scheduling/README.md
+++ b/keps/2724-topology-aware-scheduling/README.md
@@ -653,15 +653,10 @@ targetting CQs with only TAS Resource Flavors (RFs with the `spec.topologyName`
 field specified).
 
 A PodSet scheduled with TAS without the explicit annotation is handled as
-if it had the `podset-preferred-topology` annotation pointing to the lowest
+if it had the `podset-unconstrained-topology: true` annotation pointing to the lowest
 topology level defined in the Topology referenced by the selected TAS flavor.
 We call it "implicit default" as the annotation isn't persisted.
 
-To change the implicit default from `podset-preferred-topology` to `podset-unconstrained-topology`
-a user can switch on the `TASImplicitDefaultUnconstrained` feature gate.
-This feature gate is experimental, to collect user feedback. If users find this
-configuration valuable we will introduce a dedicated TAS configuration.
-
 ### Computing the assignment
 
 The extended PodSet assignment is set on admitting the workload. In order to
diff --git a/keps/2724-topology-aware-scheduling/kep.yaml b/keps/2724-topology-aware-scheduling/kep.yaml
index 620e243ef..c1de42aa1 100644
--- a/keps/2724-topology-aware-scheduling/kep.yaml
+++ b/keps/2724-topology-aware-scheduling/kep.yaml
@@ -34,7 +34,6 @@ feature-gates:
   - name: TASProfileLeastAllocated
   - name: TASProfileMixed
   - name: TASProfileLeastFreeCapacity
-  - name: TASImplicitDefaultUnconstrained
 disable-supported: true
 
 # The following PRR answers are required at beta release
diff --git a/pkg/cache/tas_flavor_snapshot.go b/pkg/cache/tas_flavor_snapshot.go
index 358d4ce91..0c52b760e 100644
--- a/pkg/cache/tas_flavor_snapshot.go
+++ b/pkg/cache/tas_flavor_snapshot.go
@@ -414,6 +414,7 @@ func (s *TASFlavorSnapshot) findTopologyAssignment(
 	count := tasPodSetRequests.Count
 	required := isRequired(tasPodSetRequests.PodSet.TopologyRequest)
 	key := s.levelKeyWithImpliedFallback(&tasPodSetRequests)
+	unconstrained := isUnconstrained(tasPodSetRequests.PodSet.TopologyRequest, &tasPodSetRequests)
 	if key == nil {
 		return nil, "topology level not specified"
 	}
@@ -426,24 +427,25 @@ func (s *TASFlavorSnapshot) findTopologyAssignment(
 
 	// phase 2a: determine the level at which the assignment is done along with
 	// the domains which can accommodate all pods
-	fitLevelIdx, currFitDomain, reason := s.findLevelWithFitDomains(levelIdx, required, count)
+	fitLevelIdx, currFitDomain, reason := s.findLevelWithFitDomains(levelIdx, required, count, unconstrained)
 	if len(reason) > 0 {
 		return nil, reason
 	}
 
 	// phase 2b: traverse the tree down level-by-level optimizing the number of
 	// topology domains at each level
-	currFitDomain = s.updateCountsToMinimum(currFitDomain, count)
+	// if unconstrained is set, we'll only do it once
+	currFitDomain = s.updateCountsToMinimum(currFitDomain, count, unconstrained)
 	for levelIdx := fitLevelIdx; levelIdx+1 < len(s.domainsPerLevel); levelIdx++ {
 		lowerFitDomains := s.lowerLevelDomains(currFitDomain)
-		sortedLowerDomains := s.sortedDomains(lowerFitDomains)
-		currFitDomain = s.updateCountsToMinimum(sortedLowerDomains, count)
+		sortedLowerDomains := s.sortedDomains(lowerFitDomains, unconstrained)
+		currFitDomain = s.updateCountsToMinimum(sortedLowerDomains, count, unconstrained)
 	}
 	return s.buildAssignment(currFitDomain), ""
 }
 
 func (s *TASFlavorSnapshot) HasLevel(r *kueue.PodSetTopologyRequest) bool {
-	key := levelKey(r)
+	key := s.levelKey(r)
 	if key == nil {
 		return false
 	}
@@ -464,7 +466,7 @@ func isRequired(tr *kueue.PodSetTopologyRequest) bool {
 }
 
 func (s *TASFlavorSnapshot) levelKeyWithImpliedFallback(tasRequests *TASPodSetRequests) *string {
-	if key := levelKey(tasRequests.PodSet.TopologyRequest); key != nil {
+	if key := s.levelKey(tasRequests.PodSet.TopologyRequest); key != nil {
 		return key
 	}
 	if tasRequests.Implied {
@@ -473,16 +475,24 @@ func (s *TASFlavorSnapshot) levelKeyWithImpliedFallback(tasRequests *TASPodSetRe
 	return nil
 }
 
-func levelKey(topologyRequest *kueue.PodSetTopologyRequest) *string {
+func (s *TASFlavorSnapshot) levelKey(topologyRequest *kueue.PodSetTopologyRequest) *string {
 	if topologyRequest == nil {
 		return nil
 	}
-	if topologyRequest.Required != nil {
+	switch {
+	case topologyRequest.Required != nil:
 		return topologyRequest.Required
-	} else if topologyRequest.Preferred != nil {
+	case topologyRequest.Preferred != nil:
 		return topologyRequest.Preferred
+	case ptr.Deref(topologyRequest.Unconstrained, false):
+		return ptr.To(s.lowestLevel())
+	default:
+		return nil
 	}
-	return nil
+}
+
+func isUnconstrained(tr *kueue.PodSetTopologyRequest, tasRequests *TASPodSetRequests) bool {
+	return (tr != nil && tr.Unconstrained != nil && *tr.Unconstrained) || tasRequests.Implied
 }
 
 // findBestFitDomainIdx finds an index of the first domain with the lowest
@@ -501,29 +511,31 @@ func findBestFitDomainIdx(domains []*domain, count int32) int {
 	return bestFitIdx
 }
 
-func (s *TASFlavorSnapshot) findLevelWithFitDomains(levelIdx int, required bool, count int32) (int, []*domain, string) {
+func (s *TASFlavorSnapshot) findLevelWithFitDomains(levelIdx int, required bool, count int32, unconstrained bool) (int, []*domain, string) {
 	domains := s.domainsPerLevel[levelIdx]
 	if len(domains) == 0 {
 		return 0, nil, fmt.Sprintf("no topology domains at level: %s", s.levelKeys[levelIdx])
 	}
 	levelDomains := slices.Collect(maps.Values(domains))
-	sortedDomain := s.sortedDomains(levelDomains)
+	sortedDomain := s.sortedDomains(levelDomains, unconstrained)
 	topDomain := sortedDomain[0]
-	if !features.Enabled(features.TASMostFreeCapacity) && topDomain.state >= count {
+	if useBestFitAlgorithm(unconstrained) && topDomain.state >= count {
+		// optimize the potentially last domain
 		topDomain = sortedDomain[findBestFitDomainIdx(sortedDomain, count)]
 	}
 	if topDomain.state < count {
 		if required {
 			return 0, nil, s.notFitMessage(topDomain.state, count)
 		}
-		if levelIdx > 0 {
-			return s.findLevelWithFitDomains(levelIdx-1, required, count)
+		if levelIdx > 0 && !unconstrained {
+			return s.findLevelWithFitDomains(levelIdx-1, required, count, unconstrained)
 		}
 		results := []*domain{}
 		remainingCount := count
 		for idx := 0; remainingCount > 0 && idx < len(sortedDomain) && sortedDomain[idx].state > 0; idx++ {
 			offset := 0
-			if !features.Enabled(features.TASMostFreeCapacity) && sortedDomain[idx].state >= remainingCount {
+			if useBestFitAlgorithm(unconstrained) && sortedDomain[idx].state >= remainingCount {
+				// optimize the last domain
 				offset = findBestFitDomainIdx(sortedDomain[idx:], remainingCount)
 			}
 			results = append(results, sortedDomain[idx+offset])
@@ -532,18 +544,38 @@ func (s *TASFlavorSnapshot) findLevelWithFitDomains(levelIdx int, required bool,
 		if remainingCount > 0 {
 			return 0, nil, s.notFitMessage(count-remainingCount, count)
 		}
-		return 0, results, ""
+		return levelIdx, results, ""
 	}
 	return levelIdx, []*domain{topDomain}, ""
 }
 
-func (s *TASFlavorSnapshot) updateCountsToMinimum(domains []*domain, count int32) []*domain {
+func useBestFitAlgorithm(unconstrained bool) bool {
+	if features.Enabled(features.TASProfileMostFreeCapacity) ||
+		features.Enabled(features.TASProfileLeastFreeCapacity) ||
+		(unconstrained && features.Enabled(features.TASProfileMixed)) {
+		// following the matrix from KEP#2724
+		return false
+	}
+	return true
+}
+
+func useLeastFreeCapacityAlgorithm(unconstrained bool) bool {
+	if features.Enabled(features.TASProfileLeastFreeCapacity) ||
+		(unconstrained && features.Enabled(features.TASProfileMixed)) {
+		// following the matrix from KEP#2724
+		return true
+	}
+	return false
+}
+
+func (s *TASFlavorSnapshot) updateCountsToMinimum(domains []*domain, count int32, unconstrained bool) []*domain {
 	result := make([]*domain, 0)
 	remainingCount := count
 	for i, domain := range domains {
-		if !features.Enabled(features.TASMostFreeCapacity) && domain.state >= remainingCount {
-			bestFitIdx := findBestFitDomainIdx(domains[i:], remainingCount)
-			domain = domains[i+bestFitIdx]
+		if useBestFitAlgorithm(unconstrained) && domain.state >= remainingCount {
+			// optimize the last domain
+			mostAllocatedIdx := findBestFitDomainIdx(domains[i:], remainingCount)
+			domain = domains[i+mostAllocatedIdx]
 		}
 
 		if domain.state >= remainingCount {
@@ -597,7 +629,7 @@ func (s *TASFlavorSnapshot) lowerLevelDomains(domains []*domain) []*domain {
 	return result
 }
 
-func (s *TASFlavorSnapshot) sortedDomains(domains []*domain) []*domain {
+func (s *TASFlavorSnapshot) sortedDomains(domains []*domain, unconstrained bool) []*domain {
 	result := slices.Clone(domains)
 	slices.SortFunc(result, func(a, b *domain) int {
 		if a.state == b.state {
@@ -606,6 +638,10 @@ func (s *TASFlavorSnapshot) sortedDomains(domains []*domain) []*domain {
 		// descending order.
 		return cmp.Compare(b.state, a.state)
 	})
+	if useLeastFreeCapacityAlgorithm(unconstrained) {
+		// start from the domain with the least amount of free resources
+		slices.Reverse(result)
+	}
 	return result
 }
 
diff --git a/pkg/config/validation.go b/pkg/config/validation.go
index 6341074c6..1600f5a88 100644
--- a/pkg/config/validation.go
+++ b/pkg/config/validation.go
@@ -360,5 +360,22 @@ func ValidateFeatureGates(featureGateCLI string, featureGateMap map[string]bool)
 	if featureGateCLI != "" && featureGateMap != nil {
 		return errors.New("feature gates for CLI and configuration cannot both specified")
 	}
+	TASProfilesEnabled := []bool{features.Enabled(features.TASProfileMixed),
+		features.Enabled(features.TASProfileLeastFreeCapacity),
+		features.Enabled(features.TASProfileMostFreeCapacity),
+	}
+	enabledProfilesCount := 0
+	for _, enabled := range TASProfilesEnabled {
+		if enabled {
+			enabledProfilesCount++
+		}
+	}
+	if enabledProfilesCount > 1 {
+		return errors.New("Cannot use more than one TAS profiles")
+	}
+	if !features.Enabled(features.TopologyAwareScheduling) && enabledProfilesCount > 0 {
+		return errors.New("Cannot use a TAS profile with TAS disabled")
+	}
+
 	return nil
 }
diff --git a/pkg/controller/jobframework/tas.go b/pkg/controller/jobframework/tas.go
index 9cebfd4d4..e08a0b9a2 100644
--- a/pkg/controller/jobframework/tas.go
+++ b/pkg/controller/jobframework/tas.go
@@ -17,6 +17,8 @@ limitations under the License.
 package jobframework
 
 import (
+	"strconv"
+
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
 	kueuealpha "sigs.k8s.io/kueue/apis/kueue/v1alpha1"
@@ -26,17 +28,22 @@ import (
 func PodSetTopologyRequest(meta *metav1.ObjectMeta, podIndexLabel *string, subGroupIndexLabel *string, subGroupCount *int32) *kueue.PodSetTopologyRequest {
 	requiredValue, requiredFound := meta.Annotations[kueuealpha.PodSetRequiredTopologyAnnotation]
 	preferredValue, preferredFound := meta.Annotations[kueuealpha.PodSetPreferredTopologyAnnotation]
+	unconstrained, unconstrainedFound := meta.Annotations[kueuealpha.PodSetUnconstrainedTopologyAnnotation]
 
-	if requiredFound || preferredFound {
+	if requiredFound || preferredFound || unconstrainedFound {
 		psTopologyReq := &kueue.PodSetTopologyRequest{
 			PodIndexLabel:      podIndexLabel,
 			SubGroupIndexLabel: subGroupIndexLabel,
 			SubGroupCount:      subGroupCount,
 		}
-		if requiredFound {
+		switch {
+		case requiredFound:
 			psTopologyReq.Required = &requiredValue
-		} else {
+		case preferredFound:
 			psTopologyReq.Preferred = &preferredValue
+		case unconstrainedFound:
+			unconstrained, _ := strconv.ParseBool(unconstrained)
+			psTopologyReq.Unconstrained = &unconstrained
 		}
 		return psTopologyReq
 	}
diff --git a/pkg/controller/jobframework/tas_validation.go b/pkg/controller/jobframework/tas_validation.go
index 5a672381e..a94c11c5a 100644
--- a/pkg/controller/jobframework/tas_validation.go
+++ b/pkg/controller/jobframework/tas_validation.go
@@ -30,12 +30,20 @@ func ValidateTASPodSetRequest(replicaPath *field.Path, replicaMetadata *metav1.O
 	var allErrs field.ErrorList
 	requiredValue, requiredFound := replicaMetadata.Annotations[kueuealpha.PodSetRequiredTopologyAnnotation]
 	preferredValue, preferredFound := replicaMetadata.Annotations[kueuealpha.PodSetPreferredTopologyAnnotation]
+	_, unconstrainedFound := replicaMetadata.Annotations[kueuealpha.PodSetUnconstrainedTopologyAnnotation]
+	annotationFoundCount := 0
+	for _, found := range []bool{requiredFound, preferredFound, unconstrainedFound} {
+		if found {
+			annotationFoundCount++
+		}
+	}
 	annotationsPath := replicaPath.Child("annotations")
-	if requiredFound && preferredFound {
+	if annotationFoundCount > 1 {
 		allErrs = append(allErrs, field.Invalid(annotationsPath, field.OmitValueType{},
-			fmt.Sprintf("must not contain both %q and %q",
+			fmt.Sprintf("must not contain more than one topology annotation: [%q, %q, %q]",
 				kueuealpha.PodSetRequiredTopologyAnnotation,
-				kueuealpha.PodSetPreferredTopologyAnnotation),
+				kueuealpha.PodSetPreferredTopologyAnnotation,
+				kueuealpha.PodSetUnconstrainedTopologyAnnotation),
 		))
 	}
 	if requiredFound {
diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go
index 4227e94c2..70daec9c3 100644
--- a/pkg/features/kube_features.go
+++ b/pkg/features/kube_features.go
@@ -150,7 +150,19 @@ const (
 	// kep: https://github.com/kubernetes-sigs/kueue/tree/main/keps/2724-topology-aware-scheduling
 	//
 	// Enable to set use LeastAlloactedFit algorithm for TAS
-	TASMostFreeCapacity featuregate.Feature = "TASMostFreeCapacity"
+	TASProfileMostFreeCapacity featuregate.Feature = "TASProfileMostFreeCapacity"
+
+	// owner: @pbundyra
+	// kep: https://github.com/kubernetes-sigs/kueue/tree/main/keps/2724-topology-aware-scheduling
+	//
+	// Enable to set use LeastAlloactedFit algorithm for TAS
+	TASProfileLeastFreeCapacity featuregate.Feature = "TASProfileLeastFreeCapacity"
+
+	// owner: @pbundyra
+	// kep: https://github.com/kubernetes-sigs/kueue/tree/main/keps/2724-topology-aware-scheduling
+	//
+	// Enable to set use LeastAlloactedFit algorithm for TAS
+	TASProfileMixed featuregate.Feature = "TASProfileMixed"
 )
 
 func init() {
@@ -231,7 +243,13 @@ var defaultVersionedFeatureGates = map[featuregate.Feature]featuregate.Versioned
 	LocalQueueDefaulting: {
 		{Version: version.MustParse("0.10"), Default: false, PreRelease: featuregate.Alpha},
 	},
-	TASMostFreeCapacity: {
+	TASProfileMostFreeCapacity: {
+		{Version: version.MustParse("0.11"), Default: false, PreRelease: featuregate.Deprecated},
+	},
+	TASProfileLeastFreeCapacity: {
+		{Version: version.MustParse("0.11"), Default: false, PreRelease: featuregate.Deprecated},
+	},
+	TASProfileMixed: {
 		{Version: version.MustParse("0.11"), Default: false, PreRelease: featuregate.Deprecated},
 	},
 }
diff --git a/pkg/scheduler/preemption/preemption.go b/pkg/scheduler/preemption/preemption.go
index 84d51cdb6..000e218a2 100644
--- a/pkg/scheduler/preemption/preemption.go
+++ b/pkg/scheduler/preemption/preemption.go
@@ -144,6 +144,9 @@ func (p *Preemptor) getTargets(preemptionCtx *preemptionCtx) []*Target {
 		return nil
 	}
 	sort.Slice(candidates, candidatesOrdering(candidates, preemptionCtx.preemptorCQ.Name, p.clock.Now()))
+	if p.enableFairSharing {
+		return fairPreemptions(preemptionCtx, candidates, p.fsStrategies)
+	}
 
 	sameQueueCandidates := candidatesOnlyFromQueue(candidates, preemptionCtx.preemptorCQ.Name)
 
@@ -158,9 +161,6 @@ func (p *Preemptor) getTargets(preemptionCtx *preemptionCtx) []*Target {
 		return minimalPreemptions(preemptionCtx, candidates, true, nil)
 	}
 
-	if p.enableFairSharing {
-		return fairPreemptions(preemptionCtx, candidates, p.fsStrategies)
-	}
 	// There is a potential of preemption of workloads from the other queue in the
 	// cohort. We proceed with borrowing only if the dedicated policy
 	// (borrowWithinCohort) is enabled. This ensures the preempted workloads
diff --git a/site/content/en/docs/reference/kueue-config.v1beta1.md b/site/content/en/docs/reference/kueue-config.v1beta1.md
index 02230cfef..ec9c395b0 100644
--- a/site/content/en/docs/reference/kueue-config.v1beta1.md
+++ b/site/content/en/docs/reference/kueue-config.v1beta1.md
@@ -579,9 +579,16 @@ underlying job are changed.</p>
 <code>bool</code>
 </td>
 <td>
-   <p>Enable controls whether to enable internal cert management or not.
-Defaults to true. If you want to use a third-party management, e.g. cert-manager,
-set it to false. See the user guide for more information.</p>
+   <p>Enable controls the use of internal cert management for the webhook
+and metrics endpoints.
+When enabled Kueue is using libraries to generate and
+self-sign the certificates.
+When disabled, you need to provide the certificates for
+the webhooks and metrics through a third party certificate
+This secret is mounted to the kueue controller manager pod. The mount
+path for webhooks is /tmp/k8s-webhook-server/serving-certs, whereas for
+metrics endpoint the expected path is <code>/etc/kueue/metrics/certs</code>.
+The keys and certs are named tls.key and tls.crt.</p>
 </td>
 </tr>
 <tr><td><code>webhookServiceName</code> <B>[Required]</B><br/>
diff --git a/site/content/en/docs/reference/kueue.v1beta1.md b/site/content/en/docs/reference/kueue.v1beta1.md
index b922e3876..d9975242a 100644
--- a/site/content/en/docs/reference/kueue.v1beta1.md
+++ b/site/content/en/docs/reference/kueue.v1beta1.md
@@ -1832,6 +1832,15 @@ indicated by the <code>kueue.x-k8s.io/podset-preferred-topology</code> PodSet
 annotation.</p>
 </td>
 </tr>
+<tr><td><code>unconstrained</code><br/>
+<code>bool</code>
+</td>
+<td>
+   <p>unconstrained indicates that Kueue has the freedom to schedule the PodSet within
+the entire available capacity, without constraints on the compactness of the placement.
+This is indicated by the <code>kueue.x-k8s.io/podset-unconstrained-topology</code> PodSet annotation.</p>
+</td>
+</tr>
 <tr><td><code>podIndexLabel</code> <B>[Required]</B><br/>
 <code>string</code>
 </td>



Test patch:
diff --git a/pkg/cache/tas_cache_test.go b/pkg/cache/tas_cache_test.go
index 3918717e6..4d67498d1 100644
--- a/pkg/cache/tas_cache_test.go
+++ b/pkg/cache/tas_cache_test.go
@@ -23,6 +23,7 @@ import (
 	"github.com/google/go-cmp/cmp"
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/api/resource"
+	"k8s.io/component-base/featuregate"
 	"k8s.io/utils/ptr"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
@@ -115,6 +116,69 @@ func TestFindTopologyAssignment(t *testing.T) {
 			Ready().
 			Obj(),
 	}
+	//nolint:dupword // suppress duplicate r1 word
+	//       b1           b2
+	//       |             |
+	//       r1           r1
+	//     /  |  \       /  \
+	//   x1  x2  x3     x4  x5
+	scatteredNodes := []corev1.Node{
+		*testingnode.MakeNode("b1-r1-x1").
+			Label(tasBlockLabel, "b1").
+			Label(tasRackLabel, "r1").
+			Label(corev1.LabelHostname, "x1").
+			StatusAllocatable(corev1.ResourceList{
+				corev1.ResourceCPU:    resource.MustParse("4"),
+				corev1.ResourceMemory: resource.MustParse("1Gi"),
+				corev1.ResourcePods:   resource.MustParse("10"),
+			}).
+			Ready().
+			Obj(),
+		*testingnode.MakeNode("b1-r1-x2").
+			Label(tasBlockLabel, "b1").
+			Label(tasRackLabel, "r1").
+			Label(corev1.LabelHostname, "x2").
+			StatusAllocatable(corev1.ResourceList{
+				corev1.ResourceCPU:    resource.MustParse("1"),
+				corev1.ResourceMemory: resource.MustParse("1Gi"),
+				corev1.ResourcePods:   resource.MustParse("10"),
+			}).
+			Ready().
+			Obj(),
+		*testingnode.MakeNode("b1-r1-x3").
+			Label(tasBlockLabel, "b1").
+			Label(tasRackLabel, "r1").
+			Label(corev1.LabelHostname, "x3").
+			StatusAllocatable(corev1.ResourceList{
+				corev1.ResourceCPU:    resource.MustParse("1"),
+				corev1.ResourceMemory: resource.MustParse("1Gi"),
+				corev1.ResourcePods:   resource.MustParse("10"),
+			}).
+			Ready().
+			Obj(),
+		*testingnode.MakeNode("b2-r1-x4").
+			Label(tasBlockLabel, "b2").
+			Label(tasRackLabel, "r1").
+			Label(corev1.LabelHostname, "x4").
+			StatusAllocatable(corev1.ResourceList{
+				corev1.ResourceCPU:    resource.MustParse("2"),
+				corev1.ResourceMemory: resource.MustParse("1Gi"),
+				corev1.ResourcePods:   resource.MustParse("10"),
+			}).
+			Ready().
+			Obj(),
+		*testingnode.MakeNode("b2-r1-x5").
+			Label(tasBlockLabel, "b2").
+			Label(tasRackLabel, "r1").
+			Label(corev1.LabelHostname, "x5").
+			StatusAllocatable(corev1.ResourceList{
+				corev1.ResourceCPU:    resource.MustParse("1"),
+				corev1.ResourceMemory: resource.MustParse("1Gi"),
+				corev1.ResourcePods:   resource.MustParse("10"),
+			}).
+			Ready().
+			Obj(),
+	}
 	defaultOneLevel := []string{
 		corev1.LabelHostname,
 	}
@@ -226,17 +290,17 @@ func TestFindTopologyAssignment(t *testing.T) {
 
 	cases := map[string]struct {
 		// TODO: remove after dropping the TASMostFreeCapacity feature gate
-		enableTASMostFreeCapacity bool
-		wantReason                string
-		topologyRequest           kueue.PodSetTopologyRequest
-		levels                    []string
-		nodeLabels                map[string]string
-		nodes                     []corev1.Node
-		pods                      []corev1.Pod
-		requests                  resources.Requests
-		count                     int32
-		tolerations               []corev1.Toleration
-		wantAssignment            *kueue.TopologyAssignment
+		enableFeatureGates []featuregate.Feature
+		wantReason         string
+		topologyRequest    *kueue.PodSetTopologyRequest
+		levels             []string
+		nodeLabels         map[string]string
+		nodes              []corev1.Node
+		pods               []corev1.Pod
+		requests           resources.Requests
+		count              int32
+		tolerations        []corev1.Toleration
+		wantAssignment     *kueue.TopologyAssignment
 	}{
 		// TODO: remove suffixes MostFreeCapacity/BestFit after dropping the TASMostFreeCapacity feature gate
 		"minimize the number of used racks before optimizing the number of nodes; MostFreeCapacity": {
@@ -311,7 +375,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					Ready().
 					Obj(),
 			},
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(tasBlockLabel),
 			},
 			levels: defaultThreeLevels,
@@ -348,11 +412,337 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
+		},
+		"minimize resource fragmentation; LeastFreeCapacityFit": {
+			//        b1
+			//         |
+			//        r1
+			//    /    |    \
+			// x1:2, x2:1, x3:1
+			//
+			nodes: []corev1.Node{
+				*testingnode.MakeNode("b1-r1-x1").
+					Label(tasBlockLabel, "b1").
+					Label(tasRackLabel, "r1").
+					Label(corev1.LabelHostname, "x1").
+					StatusAllocatable(corev1.ResourceList{
+						corev1.ResourceCPU:  resource.MustParse("2"),
+						corev1.ResourcePods: resource.MustParse("10"),
+					}).
+					Ready().
+					Obj(),
+				*testingnode.MakeNode("b1-r1-x2").
+					Label(tasBlockLabel, "b1").
+					Label(tasRackLabel, "r1").
+					Label(corev1.LabelHostname, "x2").
+					StatusAllocatable(corev1.ResourceList{
+						corev1.ResourceCPU:  resource.MustParse("1"),
+						corev1.ResourcePods: resource.MustParse("10"),
+					}).
+					Ready().
+					Obj(),
+				*testingnode.MakeNode("b1-r1-x3").
+					Label(tasBlockLabel, "b1").
+					Label(tasRackLabel, "r1").
+					Label(corev1.LabelHostname, "x3").
+					StatusAllocatable(corev1.ResourceList{
+						corev1.ResourceCPU:  resource.MustParse("1"),
+						corev1.ResourcePods: resource.MustParse("10"),
+					}).
+					Ready().
+					Obj(),
+			},
+			topologyRequest: &kueue.PodSetTopologyRequest{
+				Required: ptr.To(tasBlockLabel),
+			},
+			levels: defaultThreeLevels,
+			requests: resources.Requests{
+				corev1.ResourceCPU: 1000,
+			},
+			count: 2,
+			wantAssignment: &kueue.TopologyAssignment{
+				Levels: defaultOneLevel,
+				Domains: []kueue.TopologyDomainAssignment{
+					{
+						Count: 1,
+						Values: []string{
+							"x3",
+						},
+					},
+					{
+						Count: 1,
+						Values: []string{
+							"x2",
+						},
+					},
+				},
+			},
+			enableFeatureGates: []featuregate.Feature{features.TASProfileLeastFreeCapacity},
+		},
+		"choose the node that can accommodate all Pods": {
+			//        b1
+			//         |
+			//        r1
+			//    /    |    \
+			// x1:2, x2:1, x3:1
+			nodes: []corev1.Node{
+				*testingnode.MakeNode("b1-r1-x1").
+					Label(tasBlockLabel, "b1").
+					Label(tasRackLabel, "r1").
+					Label(corev1.LabelHostname, "x1").
+					StatusAllocatable(corev1.ResourceList{
+						corev1.ResourceCPU:  resource.MustParse("2"),
+						corev1.ResourcePods: resource.MustParse("10"),
+					}).
+					Ready().
+					Obj(),
+				*testingnode.MakeNode("b1-r1-x2").
+					Label(tasBlockLabel, "b1").
+					Label(tasRackLabel, "r1").
+					Label(corev1.LabelHostname, "x2").
+					StatusAllocatable(corev1.ResourceList{
+						corev1.ResourceCPU:  resource.MustParse("1"),
+						corev1.ResourcePods: resource.MustParse("10"),
+					}).
+					Ready().
+					Obj(),
+				*testingnode.MakeNode("b1-r1-x3").
+					Label(tasBlockLabel, "b1").
+					Label(tasRackLabel, "r1").
+					Label(corev1.LabelHostname, "x3").
+					StatusAllocatable(corev1.ResourceList{
+						corev1.ResourceCPU:  resource.MustParse("1"),
+						corev1.ResourcePods: resource.MustParse("10"),
+					}).
+					Ready().
+					Obj(),
+			},
+			topologyRequest: &kueue.PodSetTopologyRequest{
+				Required: ptr.To(tasBlockLabel),
+			},
+			levels: defaultThreeLevels,
+			requests: resources.Requests{
+				corev1.ResourceCPU: 1000,
+			},
+			count: 2,
+			wantAssignment: &kueue.TopologyAssignment{
+				Levels: defaultOneLevel,
+				Domains: []kueue.TopologyDomainAssignment{
+					{
+						Count: 2,
+						Values: []string{
+							"x1",
+						},
+					},
+				},
+			},
+		},
+		"unconstrained; 2 pods fit into hosts scattered across the whole datacenter even they could fit into single rack; LeastFreeCapacity": {
+			nodes: scatteredNodes,
+			topologyRequest: &kueue.PodSetTopologyRequest{
+				Unconstrained: ptr.To(true),
+			},
+			levels: defaultThreeLevels,
+			requests: resources.Requests{
+				corev1.ResourceCPU: 1000,
+			},
+			count: 2,
+			wantAssignment: &kueue.TopologyAssignment{
+				Levels: defaultOneLevel,
+				Domains: []kueue.TopologyDomainAssignment{
+					{
+						Count: 1,
+						Values: []string{
+							"x3",
+						},
+					},
+					{
+						Count: 1,
+						Values: []string{
+							"x5",
+						},
+					},
+				},
+			},
+			enableFeatureGates: []featuregate.Feature{features.TASProfileLeastFreeCapacity},
+		},
+		"no annotation; implied default to unconstrained; 6 pods fit into hosts scattered across the whole datacenter even they could fit into single rack; BestFit": {
+			nodes:  scatteredNodes,
+			levels: defaultThreeLevels,
+			requests: resources.Requests{
+				corev1.ResourceCPU: 1000,
+			},
+			count: 6,
+			wantAssignment: &kueue.TopologyAssignment{
+				Levels: defaultOneLevel,
+				Domains: []kueue.TopologyDomainAssignment{
+					{
+						Count: 4,
+						Values: []string{
+							"x1",
+						},
+					},
+					{
+						Count: 2,
+						Values: []string{
+							"x4",
+						},
+					},
+				},
+			},
+		},
+		"unconstrained; 6 pods fit into hosts scattered across the whole datacenter even they could fit into single rack; BestFit": {
+			nodes: scatteredNodes,
+			topologyRequest: &kueue.PodSetTopologyRequest{
+				Unconstrained: ptr.To(true),
+			},
+			levels: defaultThreeLevels,
+			requests: resources.Requests{
+				corev1.ResourceCPU: 1000,
+			},
+			count: 6,
+			wantAssignment: &kueue.TopologyAssignment{
+				Levels: defaultOneLevel,
+				Domains: []kueue.TopologyDomainAssignment{
+					{
+						Count: 4,
+						Values: []string{
+							"x1",
+						},
+					},
+					{
+						Count: 2,
+						Values: []string{
+							"x4",
+						},
+					},
+				},
+			},
+		},
+		"unconstrained; 6 pods fit into hosts scattered across the whole datacenter even they could fit into single rack; MostFreeCapacityFit": {
+			nodes: scatteredNodes,
+			topologyRequest: &kueue.PodSetTopologyRequest{
+				Unconstrained: ptr.To(true),
+			},
+			levels: defaultThreeLevels,
+			requests: resources.Requests{
+				corev1.ResourceCPU: 1000,
+			},
+			count: 6,
+			wantAssignment: &kueue.TopologyAssignment{
+				Levels: defaultOneLevel,
+				Domains: []kueue.TopologyDomainAssignment{
+					{
+						Count: 4,
+						Values: []string{
+							"x1",
+						},
+					},
+					{
+						Count: 2,
+						Values: []string{
+							"x4",
+						},
+					},
+				},
+			},
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
+		},
+		"unconstrained; a single pod fits into each host; BestFit": {
+			nodes: defaultNodes,
+			topologyRequest: &kueue.PodSetTopologyRequest{
+				Unconstrained: ptr.To(true),
+			},
+			levels: defaultThreeLevels,
+			requests: resources.Requests{
+				corev1.ResourceCPU: 1000,
+			},
+			count: 1,
+			wantAssignment: &kueue.TopologyAssignment{
+				Levels: defaultOneLevel,
+				Domains: []kueue.TopologyDomainAssignment{
+					{
+						Count: 1,
+						Values: []string{
+							"x1",
+						},
+					},
+				},
+			},
+		},
+		"unconstrained; a single pod fits into each host; MostFreeCapacity": {
+			nodes: defaultNodes,
+			topologyRequest: &kueue.PodSetTopologyRequest{
+				Unconstrained: ptr.To(true),
+			},
+			levels: defaultThreeLevels,
+			requests: resources.Requests{
+				corev1.ResourceCPU: 1000,
+			},
+			count: 1,
+			wantAssignment: &kueue.TopologyAssignment{
+				Levels: defaultOneLevel,
+				Domains: []kueue.TopologyDomainAssignment{
+					{
+						Count: 1,
+						Values: []string{
+							"x6",
+						},
+					},
+				},
+			},
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
+		},
+		"unconstrained; a single pod fits into each host; LeastFreeCapacity; TASProfileLeastFreeCapacity": {
+			nodes: defaultNodes,
+			topologyRequest: &kueue.PodSetTopologyRequest{
+				Unconstrained: ptr.To(true),
+			},
+			levels: defaultThreeLevels,
+			requests: resources.Requests{
+				corev1.ResourceCPU: 1000,
+			},
+			count: 1,
+			wantAssignment: &kueue.TopologyAssignment{
+				Levels: defaultOneLevel,
+				Domains: []kueue.TopologyDomainAssignment{
+					{
+						Count: 1,
+						Values: []string{
+							"x5",
+						},
+					},
+				},
+			},
+			enableFeatureGates: []featuregate.Feature{features.TASProfileLeastFreeCapacity},
+		},
+		"unconstrained; a single pod fits into each host; LeastFreeCapacity; TASProfileMixed": {
+			nodes: defaultNodes,
+			topologyRequest: &kueue.PodSetTopologyRequest{
+				Unconstrained: ptr.To(true),
+			},
+			levels: defaultThreeLevels,
+			requests: resources.Requests{
+				corev1.ResourceCPU: 1000,
+			},
+			count: 1,
+			wantAssignment: &kueue.TopologyAssignment{
+				Levels: defaultOneLevel,
+				Domains: []kueue.TopologyDomainAssignment{
+					{
+						Count: 1,
+						Values: []string{
+							"x5",
+						},
+					},
+				},
+			},
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMixed},
 		},
 		"block required; 4 pods fit into one host each; MostFreeCapacity": {
 			nodes: binaryTreesNodes,
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(tasBlockLabel),
 			},
 			levels: defaultThreeLevels,
@@ -389,11 +779,11 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"block required; 4 pods fit into one host each; BestFit": {
 			nodes: binaryTreesNodes,
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(tasBlockLabel),
 			},
 			levels: defaultThreeLevels,
@@ -430,12 +820,11 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: false,
 		},
 		"host required; single Pod fits in the host; MostFreeCapacity": {
 			// TODO: remove after dropping the TASMostFreeCapacity feature gate
 			nodes: defaultNodes,
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(corev1.LabelHostname),
 			},
 			levels: defaultThreeLevels,
@@ -454,11 +843,34 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
+		},
+		"host required; single Pod fits in the host; LeastFreeCapacityFit": {
+			nodes: defaultNodes,
+			topologyRequest: &kueue.PodSetTopologyRequest{
+				Required: ptr.To(corev1.LabelHostname),
+			},
+			levels: defaultThreeLevels,
+			requests: resources.Requests{
+				corev1.ResourceCPU: 1000,
+			},
+			count: 1,
+			wantAssignment: &kueue.TopologyAssignment{
+				Levels: defaultOneLevel,
+				Domains: []kueue.TopologyDomainAssignment{
+					{
+						Count: 1,
+						Values: []string{
+							"x5",
+						},
+					},
+				},
+			},
+			enableFeatureGates: []featuregate.Feature{features.TASProfileLeastFreeCapacity},
 		},
 		"host required; single Pod fits in the host; BestFit": {
 			nodes: defaultNodes,
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(corev1.LabelHostname),
 			},
 			levels: defaultThreeLevels,
@@ -477,12 +889,57 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: false,
+		},
+		"host required; single Pod fits in the host; BestFit; TASProfileMixed": {
+			nodes: defaultNodes,
+			topologyRequest: &kueue.PodSetTopologyRequest{
+				Required: ptr.To(corev1.LabelHostname),
+			},
+			levels: defaultThreeLevels,
+			requests: resources.Requests{
+				corev1.ResourceCPU: 1000,
+			},
+			count: 1,
+			wantAssignment: &kueue.TopologyAssignment{
+				Levels: defaultOneLevel,
+				Domains: []kueue.TopologyDomainAssignment{
+					{
+						Count: 1,
+						Values: []string{
+							"x1",
+						},
+					},
+				},
+			},
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMixed},
+		},
+		"host preferred; single Pod fits in the host; BestFit; TASProfileMixed": {
+			nodes: defaultNodes,
+			topologyRequest: &kueue.PodSetTopologyRequest{
+				Required: ptr.To(corev1.LabelHostname),
+			},
+			levels: defaultThreeLevels,
+			requests: resources.Requests{
+				corev1.ResourceCPU: 1000,
+			},
+			count: 1,
+			wantAssignment: &kueue.TopologyAssignment{
+				Levels: defaultOneLevel,
+				Domains: []kueue.TopologyDomainAssignment{
+					{
+						Count: 1,
+						Values: []string{
+							"x1",
+						},
+					},
+				},
+			},
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMixed},
 		},
 		"rack required; single Pod fits in a rack; MostFreeCapacity": {
 			// TODO: remove after dropping the TASMostFreeCapacity feature gate
 			nodes: defaultNodes,
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(tasRackLabel),
 			},
 			levels: defaultTwoLevels,
@@ -502,11 +959,65 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
+		},
+		"rack required; single Pod fits in a rack; LeastFreeCapacityFit": {
+			nodes: defaultNodes,
+			topologyRequest: &kueue.PodSetTopologyRequest{
+				Required: ptr.To(tasRackLabel),
+			},
+			levels: defaultThreeLevels,
+			requests: resources.Requests{
+				corev1.ResourceCPU: 1000,
+			},
+			count: 1,
+			wantAssignment: &kueue.TopologyAssignment{
+				Levels: defaultOneLevel,
+				Domains: []kueue.TopologyDomainAssignment{
+					{
+						Count: 1,
+						Values: []string{
+							"x5",
+						},
+					},
+				},
+			},
+			enableFeatureGates: []featuregate.Feature{features.TASProfileLeastFreeCapacity},
+		},
+		"rack preferred; multiple Pods fits in multiple racks; LeastFreeCapacityFit": {
+			nodes: defaultNodes,
+			topologyRequest: &kueue.PodSetTopologyRequest{
+				Preferred: ptr.To(tasRackLabel),
+			},
+			levels: defaultTwoLevels,
+			requests: resources.Requests{
+				corev1.ResourceCPU: 1000,
+			},
+			count: 2,
+			wantAssignment: &kueue.TopologyAssignment{
+				Levels: defaultTwoLevels,
+				Domains: []kueue.TopologyDomainAssignment{
+					{
+						Count: 1,
+						Values: []string{
+							"b2",
+							"r1",
+						},
+					},
+					{
+						Count: 1,
+						Values: []string{
+							"b2",
+							"r2",
+						},
+					},
+				},
+			},
+			enableFeatureGates: []featuregate.Feature{features.TASProfileLeastFreeCapacity},
 		},
 		"rack required; multiple Pods fits in a rack; MostFreeCapacity": {
 			nodes: defaultNodes,
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(tasRackLabel),
 			},
 			levels: defaultTwoLevels,
@@ -526,11 +1037,11 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"rack required; multiple Pods fit in a rack; BestFit": {
 			nodes: defaultNodes,
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(tasRackLabel),
 			},
 			levels: defaultTwoLevels,
@@ -550,7 +1061,6 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: false,
 		},
 		"block preferred; Pods fit in 2 blocks; BestFit": {
 			nodes: []corev1.Node{
@@ -579,7 +1089,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					Ready().
 					Obj(),
 			},
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Preferred: ptr.To(tasBlockLabel),
 			},
 			levels: []string{tasBlockLabel},
@@ -604,11 +1114,10 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: false,
 		},
 		"rack required; multiple Pods fit in some racks; BestFit": {
 			nodes: defaultNodes,
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(tasRackLabel),
 			},
 			levels: defaultTwoLevels,
@@ -628,25 +1137,25 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: false,
 		},
 		"rack required; too many pods to fit in any rack; MostFreeCapacity": {
 			nodes: defaultNodes,
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(tasRackLabel),
 			},
 			levels: defaultTwoLevels,
 			requests: resources.Requests{
 				corev1.ResourceCPU: 1000,
 			},
-			count:                     4,
-			wantReason:                `topology "default" allows to fit only 3 out of 4 pod(s)`,
-			enableTASMostFreeCapacity: true,
+			count:      4,
+			wantReason: `topology "default" allows to fit only 3 out of 4 pod(s)`,
+
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"block required; single Pod fits in a block; MostFreeCapacity": {
 			// TODO: remove after dropping the TASMostFreeCapacity feature gate
 			nodes: defaultNodes,
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(tasBlockLabel),
 			},
 			levels: defaultTwoLevels,
@@ -669,11 +1178,63 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
+		},
+		"block required; single Pod fits in a block; LeastFreeCapacityFit": {
+			nodes: defaultNodes,
+			topologyRequest: &kueue.PodSetTopologyRequest{
+				Required: ptr.To(tasBlockLabel),
+			},
+			levels: defaultThreeLevels,
+			requests: resources.Requests{
+				corev1.ResourceCPU: 1000,
+			},
+			count: 1,
+			wantAssignment: &kueue.TopologyAssignment{
+				Levels: defaultOneLevel,
+				Domains: []kueue.TopologyDomainAssignment{
+					{
+						Count: 1,
+						Values: []string{
+							"x5",
+						},
+					},
+				},
+			},
+			enableFeatureGates: []featuregate.Feature{features.TASProfileLeastFreeCapacity},
+		},
+		"block required; two Pods fits in a block; LeastFreeCapacityFit": {
+			nodes: defaultNodes,
+			topologyRequest: &kueue.PodSetTopologyRequest{
+				Required: ptr.To(tasBlockLabel),
+			},
+			levels: defaultThreeLevels,
+			requests: resources.Requests{
+				corev1.ResourceCPU: 1000,
+			},
+			count: 2,
+			wantAssignment: &kueue.TopologyAssignment{
+				Levels: defaultOneLevel,
+				Domains: []kueue.TopologyDomainAssignment{
+					{
+						Count: 1,
+						Values: []string{
+							"x5",
+						},
+					},
+					{
+						Count: 1,
+						Values: []string{
+							"x6",
+						},
+					},
+				},
+			},
+			enableFeatureGates: []featuregate.Feature{features.TASProfileLeastFreeCapacity},
 		},
 		"block required; single Pod fits in a block and a single rack; BestFit": {
 			nodes: defaultNodes,
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(tasBlockLabel),
 			},
 			levels: defaultTwoLevels,
@@ -696,11 +1257,10 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: false,
 		},
 		"block required; single Pod fits in a block spread across two racks; BestFit": {
 			nodes: defaultNodes,
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(tasBlockLabel),
 			},
 			levels: defaultTwoLevels,
@@ -730,11 +1290,10 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: false,
 		},
 		"block required; Pods fit in a block spread across two racks; MostFreeCapacity": {
 			nodes: defaultNodes,
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(tasBlockLabel),
 			},
 			levels: defaultTwoLevels,
@@ -761,38 +1320,38 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"block required; single Pod which cannot be split; MostFreeCapacity": {
 			nodes: defaultNodes,
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(tasBlockLabel),
 			},
 			levels: defaultTwoLevels,
 			requests: resources.Requests{
 				corev1.ResourceCPU: 4000,
 			},
-			count:                     1,
-			wantReason:                `topology "default" doesn't allow to fit any of 1 pod(s)`,
-			enableTASMostFreeCapacity: true,
+			count:              1,
+			wantReason:         `topology "default" doesn't allow to fit any of 1 pod(s)`,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"block required; too many Pods to fit requested; MostFreeCapacity": {
 			nodes: defaultNodes,
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(tasBlockLabel),
 			},
 			levels: defaultTwoLevels,
 			requests: resources.Requests{
 				corev1.ResourceCPU: 1000,
 			},
-			count:                     5,
-			wantReason:                `topology "default" allows to fit only 4 out of 5 pod(s)`,
-			enableTASMostFreeCapacity: true,
+			count:              5,
+			wantReason:         `topology "default" allows to fit only 4 out of 5 pod(s)`,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"rack required; single Pod requiring memory; MostFreeCapacity": {
 			// TODO: remove after dropping the TASMostFreeCapacity feature gate
 			nodes: defaultNodes,
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(tasRackLabel),
 			},
 			levels: defaultTwoLevels,
@@ -812,11 +1371,11 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"rack preferred; but only block can accommodate the workload; MostFreeCapacity": {
 			nodes: defaultNodes,
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Preferred: ptr.To(tasRackLabel),
 			},
 			levels: defaultTwoLevels,
@@ -843,11 +1402,11 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"rack preferred; but only multiple blocks can accommodate the workload; MostFreeCapacity": {
 			nodes: defaultNodes,
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Preferred: ptr.To(tasRackLabel),
 			},
 			levels: defaultTwoLevels,
@@ -881,11 +1440,11 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"block preferred; but only multiple blocks can accommodate the workload; MostFreeCapacity": {
 			nodes: defaultNodes,
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Preferred: ptr.To(tasBlockLabel),
 			},
 			levels: defaultTwoLevels,
@@ -919,20 +1478,20 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"block preferred; but the workload cannot be accommodate in entire topology; MostFreeCapacity": {
 			nodes: defaultNodes,
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Preferred: ptr.To(tasBlockLabel),
 			},
 			levels: defaultTwoLevels,
 			requests: resources.Requests{
 				corev1.ResourceCPU: 1000,
 			},
-			count:                     10,
-			wantReason:                `topology "default" allows to fit only 7 out of 10 pod(s)`,
-			enableTASMostFreeCapacity: true,
+			count:              10,
+			wantReason:         `topology "default" allows to fit only 7 out of 10 pod(s)`,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"only nodes with matching labels are considered; no matching node; MostFreeCapacity": {
 			nodes: []corev1.Node{
@@ -946,7 +1505,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					}).
 					Obj(),
 			},
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(corev1.LabelHostname),
 			},
 			nodeLabels: map[string]string{
@@ -956,9 +1515,9 @@ func TestFindTopologyAssignment(t *testing.T) {
 			requests: resources.Requests{
 				corev1.ResourceCPU: 1000,
 			},
-			count:                     1,
-			wantReason:                "no topology domains at level: kubernetes.io/hostname",
-			enableTASMostFreeCapacity: true,
+			count:              1,
+			wantReason:         "no topology domains at level: kubernetes.io/hostname",
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"only nodes with matching labels are considered; matching node is found; MostFreeCapacity": {
 			nodes: []corev1.Node{
@@ -973,7 +1532,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					Ready().
 					Obj(),
 			},
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(corev1.LabelHostname),
 			},
 			nodeLabels: map[string]string{
@@ -995,7 +1554,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"only nodes with matching levels are considered; no host label on node; MostFreeCapacity": {
 			nodes: []corev1.Node{
@@ -1011,16 +1570,16 @@ func TestFindTopologyAssignment(t *testing.T) {
 					Ready().
 					Obj(),
 			},
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(tasRackLabel),
 			},
 			levels: defaultThreeLevels,
 			requests: resources.Requests{
 				corev1.ResourceCPU: 1000,
 			},
-			count:                     1,
-			wantReason:                "no topology domains at level: cloud.com/topology-rack",
-			enableTASMostFreeCapacity: true,
+			count:              1,
+			wantReason:         "no topology domains at level: cloud.com/topology-rack",
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"don't consider unscheduled Pods when computing capacity; MostFreeCapacity": {
 			// the Pod is not scheduled (no NodeName set, so is not blocking capacity)
@@ -1040,7 +1599,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					Request(corev1.ResourceCPU, "600m").
 					Obj(),
 			},
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(corev1.LabelHostname),
 			},
 			levels: defaultOneLevel,
@@ -1059,7 +1618,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"don't consider terminal pods when computing the capacity; MostFreeCapacity": {
 			nodes: []corev1.Node{
@@ -1083,7 +1642,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					StatusPhase(corev1.PodSucceeded).
 					Obj(),
 			},
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(corev1.LabelHostname),
 			},
 			levels: defaultOneLevel,
@@ -1102,7 +1661,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"include usage from pending scheduled non-TAS pods, blocked assignment; MostFreeCapacity": {
 			// there is not enough free capacity on the only node x1
@@ -1123,16 +1682,15 @@ func TestFindTopologyAssignment(t *testing.T) {
 					Request(corev1.ResourceCPU, "600m").
 					Obj(),
 			},
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(corev1.LabelHostname),
 			},
 			levels: defaultOneLevel,
 			requests: resources.Requests{
 				corev1.ResourceCPU: 600,
 			},
-			count:                     1,
-			wantReason:                `topology "default" doesn't allow to fit any of 1 pod(s)`,
-			enableTASMostFreeCapacity: true,
+			count:      1,
+			wantReason: `topology "default" doesn't allow to fit any of 1 pod(s)`,
 		},
 		"include usage from running non-TAS pods, blocked assignment; MostFreeCapacity": {
 			// there is not enough free capacity on the only node x1
@@ -1153,16 +1711,16 @@ func TestFindTopologyAssignment(t *testing.T) {
 					Request(corev1.ResourceCPU, "600m").
 					Obj(),
 			},
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(corev1.LabelHostname),
 			},
 			levels: defaultOneLevel,
 			requests: resources.Requests{
 				corev1.ResourceCPU: 600,
 			},
-			count:                     1,
-			wantReason:                `topology "default" doesn't allow to fit any of 1 pod(s)`,
-			enableTASMostFreeCapacity: true,
+			count:              1,
+			wantReason:         `topology "default" doesn't allow to fit any of 1 pod(s)`,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"include usage from running non-TAS pods, found free capacity on another node; MostFreeCapacity": {
 			// there is not enough free capacity on the node x1 as the
@@ -1192,7 +1750,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					Request(corev1.ResourceCPU, "600m").
 					Obj(),
 			},
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(corev1.LabelHostname),
 			},
 			levels: defaultOneLevel,
@@ -1211,7 +1769,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"no assignment as node is not ready; MostFreeCapacity": {
 			nodes: []corev1.Node{
@@ -1230,7 +1788,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					}).
 					Obj(),
 			},
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(corev1.LabelHostname),
 			},
 			nodeLabels: map[string]string{
@@ -1240,9 +1798,9 @@ func TestFindTopologyAssignment(t *testing.T) {
 			requests: resources.Requests{
 				corev1.ResourceCPU: 1000,
 			},
-			count:                     1,
-			wantReason:                "no topology domains at level: kubernetes.io/hostname",
-			enableTASMostFreeCapacity: true,
+			count:              1,
+			wantReason:         "no topology domains at level: kubernetes.io/hostname",
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"no assignment as node is unschedulable; MostFreeCapacity": {
 			nodes: []corev1.Node{
@@ -1258,7 +1816,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					Unschedulable().
 					Obj(),
 			},
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(corev1.LabelHostname),
 			},
 			nodeLabels: map[string]string{
@@ -1268,9 +1826,9 @@ func TestFindTopologyAssignment(t *testing.T) {
 			requests: resources.Requests{
 				corev1.ResourceCPU: 1000,
 			},
-			count:                     1,
-			wantReason:                "no topology domains at level: kubernetes.io/hostname",
-			enableTASMostFreeCapacity: true,
+			count:              1,
+			wantReason:         "no topology domains at level: kubernetes.io/hostname",
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"skip node which has untolerated taint; MostFreeCapacity": {
 			nodes: []corev1.Node{
@@ -1290,7 +1848,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					}).
 					Obj(),
 			},
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(corev1.LabelHostname),
 			},
 			nodeLabels: map[string]string{
@@ -1300,9 +1858,9 @@ func TestFindTopologyAssignment(t *testing.T) {
 			requests: resources.Requests{
 				corev1.ResourceCPU: 1000,
 			},
-			count:                     1,
-			wantReason:                `topology "default" doesn't allow to fit any of 1 pod(s)`,
-			enableTASMostFreeCapacity: true,
+			count:              1,
+			wantReason:         `topology "default" doesn't allow to fit any of 1 pod(s)`,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"allow to schedule on node with tolerated taint; MostFreeCapacity": {
 			nodes: []corev1.Node{
@@ -1329,7 +1887,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					Operator: corev1.TolerationOpEqual,
 				},
 			},
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(corev1.LabelHostname),
 			},
 			nodeLabels: map[string]string{
@@ -1351,7 +1909,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					},
 				},
 			},
-			enableTASMostFreeCapacity: true,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 		"no assignment as node does not have enough allocatable pods (.status.allocatable['pods']); MostFreeCapacity": {
 			nodes: []corev1.Node{
@@ -1372,7 +1930,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 					Request(corev1.ResourceCPU, "300m").
 					Obj(),
 			},
-			topologyRequest: kueue.PodSetTopologyRequest{
+			topologyRequest: &kueue.PodSetTopologyRequest{
 				Required: ptr.To(corev1.LabelHostname),
 			},
 			nodeLabels: map[string]string{
@@ -1382,16 +1940,18 @@ func TestFindTopologyAssignment(t *testing.T) {
 			requests: resources.Requests{
 				corev1.ResourceCPU: 300,
 			},
-			count:                     1,
-			wantReason:                `topology "default" doesn't allow to fit any of 1 pod(s)`,
-			enableTASMostFreeCapacity: true,
+			count:              1,
+			wantReason:         `topology "default" doesn't allow to fit any of 1 pod(s)`,
+			enableFeatureGates: []featuregate.Feature{features.TASProfileMostFreeCapacity},
 		},
 	}
 	for name, tc := range cases {
 		t.Run(name, func(t *testing.T) {
 			ctx, _ := utiltesting.ContextWithLog(t)
-			// TODO: remove after dropping the TASMostFreeCapacity feature gate
-			features.SetFeatureGateDuringTest(t, features.TASMostFreeCapacity, tc.enableTASMostFreeCapacity)
+			// TODO: remove after dropping the TAS profiles feature gates
+			for _, gate := range tc.enableFeatureGates {
+				features.SetFeatureGateDuringTest(t, gate, true)
+			}
 
 			initialObjects := make([]client.Object, 0)
 			for i := range tc.nodes {
@@ -1415,7 +1975,7 @@ func TestFindTopologyAssignment(t *testing.T) {
 			tasInput := TASPodSetRequests{
 				PodSet: &kueue.PodSet{
 					Name:            kueue.DefaultPodSetName,
-					TopologyRequest: &tc.topologyRequest,
+					TopologyRequest: tc.topologyRequest,
 					Template: corev1.PodTemplateSpec{
 						Spec: corev1.PodSpec{
 							Tolerations: tc.tolerations,
@@ -1425,6 +1985,9 @@ func TestFindTopologyAssignment(t *testing.T) {
 				SinglePodRequests: tc.requests,
 				Count:             tc.count,
 			}
+			if tc.topologyRequest == nil {
+				tasInput.Implied = true
+			}
 			flavorTASRequests := []TASPodSetRequests{tasInput}
 			wantResult := make(TASAssignmentsResult)
 			wantMainPodSetResult := tasPodSetAssignmentResult{
diff --git a/pkg/config/validation_test.go b/pkg/config/validation_test.go
index e278bade6..ac09c65b8 100644
--- a/pkg/config/validation_test.go
+++ b/pkg/config/validation_test.go
@@ -772,6 +772,20 @@ func TestValidateFeatureGates(t *testing.T) {
 
 			errorStr: "feature gates for CLI and configuration cannot both specified",
 		},
+		"cannot specify more than one TAS profile using GateMap": {
+			featureGateMap: map[string]bool{"TASProfileMostFreeCapacity": true,
+				"TASProfileLeastFreeCapacity": true},
+			errorStr: "Cannot use more than one TAS profiles",
+		},
+		"cannot specify more than one TAS profile using GatesCLI": {
+			featureGatesCLI: "TASProfileMostFreeCapacity:true,TASProfileMixed:true",
+			errorStr:        "Cannot use more than one TAS profiles",
+		},
+		"cannot set TAS profile with TAS disabled": {
+			featureGateMap: map[string]bool{"TASProfileMostFreeCapacity": true,
+				"TopologyAwareScheduling": true},
+			errorStr: "Cannot use a TAS profile with TAS disabled",
+		},
 	}
 	for name, tc := range cases {
 		t.Run(name, func(t *testing.T) {
diff --git a/pkg/controller/jobs/job/job_webhook_test.go b/pkg/controller/jobs/job/job_webhook_test.go
index d7c8f8cc8..f9fd1b802 100644
--- a/pkg/controller/jobs/job/job_webhook_test.go
+++ b/pkg/controller/jobs/job/job_webhook_test.go
@@ -252,7 +252,8 @@ func TestValidateCreate(t *testing.T) {
 				Obj(),
 			wantErr: field.ErrorList{
 				field.Invalid(replicaMetaPath.Child("annotations"), field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 			},
 		},
 		{
@@ -531,8 +532,8 @@ func TestValidateUpdate(t *testing.T) {
 				Obj(),
 			wantErr: field.ErrorList{
 				field.Invalid(replicaMetaPath.Child("annotations"), field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`),
-			},
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`)},
 		},
 	}
 
diff --git a/pkg/controller/jobs/jobset/jobset_webhook_test.go b/pkg/controller/jobs/jobset/jobset_webhook_test.go
index 3f4df6080..91e3f15bb 100644
--- a/pkg/controller/jobs/jobset/jobset_webhook_test.go
+++ b/pkg/controller/jobs/jobset/jobset_webhook_test.go
@@ -98,7 +98,8 @@ func TestValidateCreate(t *testing.T) {
 				},
 			}).Obj(),
 			wantErr: field.ErrorList{field.Invalid(field.NewPath("spec.replicatedJobs[1].template.metadata.annotations"),
-				field.OmitValueType{}, `must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`)}.ToAggregate(),
+				field.OmitValueType{}, `must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+					`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`)}.ToAggregate(),
 		},
 	}
 
@@ -148,7 +149,8 @@ func TestValidateUpdate(t *testing.T) {
 				},
 			}).Obj(),
 			wantErr: field.ErrorList{field.Invalid(field.NewPath("spec.replicatedJobs[0].template.metadata.annotations"),
-				field.OmitValueType{}, `must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`)},
+				field.OmitValueType{}, `must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+					`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`)},
 		},
 	}
 
diff --git a/pkg/controller/jobs/kubeflow/jobs/paddlejob/paddlejob_controller_test.go b/pkg/controller/jobs/kubeflow/jobs/paddlejob/paddlejob_controller_test.go
index 86941e199..8deb25c65 100644
--- a/pkg/controller/jobs/kubeflow/jobs/paddlejob/paddlejob_controller_test.go
+++ b/pkg/controller/jobs/kubeflow/jobs/paddlejob/paddlejob_controller_test.go
@@ -365,15 +365,15 @@ func TestValidate(t *testing.T) {
 						Key("Master").
 						Child("template", "metadata", "annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 				field.Invalid(
 					field.NewPath("spec", "paddleReplicaSpecs").
 						Key("Worker").
 						Child("template", "metadata", "annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 			},
 		},
 	}
diff --git a/pkg/controller/jobs/kubeflow/jobs/pytorchjob/pytorchjob_controller_test.go b/pkg/controller/jobs/kubeflow/jobs/pytorchjob/pytorchjob_controller_test.go
index 2a43e579e..6d5a661c8 100644
--- a/pkg/controller/jobs/kubeflow/jobs/pytorchjob/pytorchjob_controller_test.go
+++ b/pkg/controller/jobs/kubeflow/jobs/pytorchjob/pytorchjob_controller_test.go
@@ -368,15 +368,15 @@ func TestValidate(t *testing.T) {
 						Key("Master").
 						Child("template", "metadata", "annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 				field.Invalid(
 					field.NewPath("spec", "pytorchReplicaSpecs").
 						Key("Worker").
 						Child("template", "metadata", "annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 			},
 		},
 	}
diff --git a/pkg/controller/jobs/kubeflow/jobs/tfjob/tfjob_controller_test.go b/pkg/controller/jobs/kubeflow/jobs/tfjob/tfjob_controller_test.go
index c496ceb4a..dab1a8d3e 100644
--- a/pkg/controller/jobs/kubeflow/jobs/tfjob/tfjob_controller_test.go
+++ b/pkg/controller/jobs/kubeflow/jobs/tfjob/tfjob_controller_test.go
@@ -385,15 +385,15 @@ func TestValidate(t *testing.T) {
 						Key("Chief").
 						Child("template", "metadata", "annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 				field.Invalid(
 					field.NewPath("spec", "tfReplicaSpecs").
 						Key("PS").
 						Child("template", "metadata", "annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 			},
 		},
 	}
diff --git a/pkg/controller/jobs/kubeflow/jobs/xgboostjob/xgboostjob_controller_test.go b/pkg/controller/jobs/kubeflow/jobs/xgboostjob/xgboostjob_controller_test.go
index a9c130762..e5b817afa 100644
--- a/pkg/controller/jobs/kubeflow/jobs/xgboostjob/xgboostjob_controller_test.go
+++ b/pkg/controller/jobs/kubeflow/jobs/xgboostjob/xgboostjob_controller_test.go
@@ -374,15 +374,15 @@ func TestValidate(t *testing.T) {
 						Key("Master").
 						Child("template", "metadata", "annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 				field.Invalid(
 					field.NewPath("spec", "xgbReplicaSpecs").
 						Key("Worker").
 						Child("template", "metadata", "annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 			},
 		},
 	}
diff --git a/pkg/controller/jobs/mpijob/mpijob_webhook_test.go b/pkg/controller/jobs/mpijob/mpijob_webhook_test.go
index 61c0f8356..0e0fb0620 100644
--- a/pkg/controller/jobs/mpijob/mpijob_webhook_test.go
+++ b/pkg/controller/jobs/mpijob/mpijob_webhook_test.go
@@ -110,13 +110,13 @@ func TestValidateCreate(t *testing.T) {
 				field.Invalid(
 					field.NewPath("spec.mpiReplicaSpecs[Launcher].template.metadata.annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 				field.Invalid(
 					field.NewPath("spec.mpiReplicaSpecs[Worker].template.metadata.annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 			}.ToAggregate(),
 		},
 	}
diff --git a/pkg/controller/jobs/raycluster/raycluster_webhook_test.go b/pkg/controller/jobs/raycluster/raycluster_webhook_test.go
index 02884ab9f..2c55411ef 100644
--- a/pkg/controller/jobs/raycluster/raycluster_webhook_test.go
+++ b/pkg/controller/jobs/raycluster/raycluster_webhook_test.go
@@ -240,13 +240,13 @@ func TestValidateCreate(t *testing.T) {
 				field.Invalid(
 					field.NewPath("spec.headGroupSpec.template, metadata.annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 				field.Invalid(
 					field.NewPath("spec.workerGroupSpecs[0].template.metadata.annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 			}.ToAggregate(),
 		},
 	}
diff --git a/pkg/controller/jobs/rayjob/rayjob_webhook_test.go b/pkg/controller/jobs/rayjob/rayjob_webhook_test.go
index 92873ac90..e34c6ac55 100644
--- a/pkg/controller/jobs/rayjob/rayjob_webhook_test.go
+++ b/pkg/controller/jobs/rayjob/rayjob_webhook_test.go
@@ -267,13 +267,13 @@ func TestValidateCreate(t *testing.T) {
 				field.Invalid(
 					field.NewPath("spec.rayClusterSpec.headGroupSpec.template, metadata.annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 				field.Invalid(
 					field.NewPath("spec.rayClusterSpec.workerGroupSpecs[0].template.metadata.annotations"),
 					field.OmitValueType{},
-					`must not contain both "kueue.x-k8s.io/podset-required-topology" and "kueue.x-k8s.io/podset-preferred-topology"`,
-				),
+					`must not contain more than one topology annotation: ["kueue.x-k8s.io/podset-required-topology", `+
+						`"kueue.x-k8s.io/podset-preferred-topology", "kueue.x-k8s.io/podset-unconstrained-topology"]`),
 			}.ToAggregate(),
 		},
 	}
diff --git a/pkg/scheduler/preemption/preemption_test.go b/pkg/scheduler/preemption/preemption_test.go
index 364f323d5..f79ef5a81 100644
--- a/pkg/scheduler/preemption/preemption_test.go
+++ b/pkg/scheduler/preemption/preemption_test.go
@@ -2342,6 +2342,25 @@ func TestFairPreemptions(t *testing.T) {
 			incoming: unitWl.Clone().Name("a_incoming").Obj(),
 			targetCQ: "a",
 		},
+		"can preempt within cluster queue when no cohort": {
+			clusterQueues: []*kueue.ClusterQueue{
+				utiltesting.MakeClusterQueue("a").
+					ResourceGroup(*utiltesting.MakeFlavorQuotas("default").
+						Resource(corev1.ResourceCPU, "1").Obj()).
+					Preemption(kueue.ClusterQueuePreemption{
+						WithinClusterQueue: kueue.PreemptionPolicyLowerPriority,
+					}).
+					Obj(),
+			},
+			admitted: []kueue.Workload{
+				*unitWl.Clone().Name("a1").SimpleReserveQuota("a", "default", now).Obj(),
+			},
+			incoming: unitWl.Clone().Name("a_incoming").Priority(1000).Obj(),
+			targetCQ: "a",
+			wantPreempted: sets.New(
+				targetKeyReason("/a1", kueue.InClusterQueueReason),
+			),
+		},
 	}
 	for name, tc := range cases {
 		t.Run(name, func(t *testing.T) {
diff --git a/test/integration/singlecluster/controller/jobs/job/job_controller_test.go b/test/integration/singlecluster/controller/jobs/job/job_controller_test.go
index a21cdac26..1dfc85f2a 100644
--- a/test/integration/singlecluster/controller/jobs/job/job_controller_test.go
+++ b/test/integration/singlecluster/controller/jobs/job/job_controller_test.go
@@ -2655,4 +2655,56 @@ var _ = ginkgo.Describe("Job controller when TopologyAwareScheduling enabled", g
 			}, util.Timeout, util.Interval).Should(gomega.Succeed())
 		})
 	})
+
+	ginkgo.It("should admit workload with topology unconstrained annotation which fits", func() {
+		job := testingjob.MakeJob("job", ns.Name).
+			Queue(localQueue.Name).
+			PodAnnotation(kueuealpha.PodSetUnconstrainedTopologyAnnotation, "true").
+			Request(corev1.ResourceCPU, "1").
+			Obj()
+		ginkgo.By("creating a job", func() {
+			gomega.Expect(k8sClient.Create(ctx, job)).Should(gomega.Succeed())
+		})
+
+		wl := &kueue.Workload{}
+		wlLookupKey := types.NamespacedName{Name: workloadjob.GetWorkloadNameForJob(job.Name, job.UID), Namespace: ns.Name}
+
+		ginkgo.By("verify the workload is created", func() {
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+				g.Expect(wl.Spec.PodSets).Should(gomega.BeComparableTo([]kueue.PodSet{{
+					Name:  kueue.DefaultPodSetName,
+					Count: 1,
+					TopologyRequest: &kueue.PodSetTopologyRequest{
+						Unconstrained: ptr.To(true),
+						PodIndexLabel: ptr.To(batchv1.JobCompletionIndexAnnotation),
+					},
+				}}, cmpopts.IgnoreFields(kueue.PodSet{}, "Template")))
+			}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		})
+
+		ginkgo.By("verify the workload is admitted", func() {
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+			}, util.Timeout, util.Interval).Should(gomega.Succeed())
+
+			util.ExpectWorkloadsToBeAdmitted(ctx, k8sClient, wl)
+			util.ExpectReservingActiveWorkloadsMetric(clusterQueue, 1)
+		})
+
+		ginkgo.By("verify admission for the workload", func() {
+			wlLookupKey := types.NamespacedName{Name: workloadjob.GetWorkloadNameForJob(job.Name, job.UID), Namespace: ns.Name}
+			gomega.Eventually(func(g gomega.Gomega) {
+				g.Expect(k8sClient.Get(ctx, wlLookupKey, wl)).Should(gomega.Succeed())
+				g.Expect(wl.Status.Admission).ShouldNot(gomega.BeNil())
+				g.Expect(wl.Status.Admission.PodSetAssignments).Should(gomega.HaveLen(1))
+				g.Expect(wl.Status.Admission.PodSetAssignments[0].TopologyAssignment).Should(gomega.BeComparableTo(
+					&kueue.TopologyAssignment{
+						Levels:  []string{tasBlockLabel},
+						Domains: []kueue.TopologyDomainAssignment{{Count: 1, Values: []string{"b1"}}},
+					},
+				))
+			}, util.Timeout, util.Interval).Should(gomega.Succeed())
+		})
+	})
 })