Render manually authored Windows profile names verbatim

This commit is contained in:
omar
2026-09-23 17:57:15 +03:00
parent a5a6bd0087
commit cf8c5007f1
8 changed files with 14 additions and 15 deletions
+4
View File
@@ -5,3 +5,7 @@ This repository is authoritative only for its owned component. Use sibling clone
Edit here, prove the affected behavior, audit the explicit file allowlist, commit/push normally, then fetch reviewed full commits into the deployment host clones. Deploy through otche-deploy/update.py and its documented protected external env/override. No archive-based source deployment, force/reset, dirty-work overwrite or unreviewed latest-branch activation. Coordinate quiescence before activation; retain the exact existing Compose project, external named volumes, private secrets/TLS/config/proofs and held evidence. Verify live commit IDs, health, old-data continuity and requested acceptance after rollout.
Never commit real secrets, tokens, runtime output, sample payloads, proof logs, private certificates or live host inventory. No credentials in remote URLs or persistent helpers. Windows signing remains operator-supplied. Do not weaken VM/network/Windows protections to pass acceptance.
## Windows display names
The complete Windows display label, including build/version text, is explicitly authored in editable `Profile.name`. NEVER derive or append the display build from environment telemetry, qualification, a revision lookup or a frontend formatter. Each Run stores an immutable `profile_name` snapshot; profile renames do not rewrite historical names. Technical `environment.os_build` telemetry and source fingerprints remain separate and unchanged.
+1 -1
View File
@@ -27,4 +27,4 @@ npm run dev
Vite listens on loopback port 5173 and proxies `/api` to `http://127.0.0.1:8080`. Override that target with `OTCHE_API_PROXY` if needed; retain the exact browser origin at the API. Production nginx talks to Compose service `api:8080`; use the sibling deploy repository for the actual app, not a standalone frontend container with no API.
See the backend [API contract](https://git.qomar.pw/otche/otche-backend/src/branch/main/docs/API.md). Session cookies and CSRF checks are enforced by the API. Missing configuration/qualification is displayed as a blocker, never converted into fake successful analysis. Build labels come from verified revision evidence, not release-name guesses. Grub archives are authenticated private downloads, not public static assets.
See the backend [API contract](https://git.qomar.pw/otche/otche-backend/src/branch/main/docs/API.md). Session cookies and CSRF checks are enforced by the API. Missing configuration/qualification is displayed as a blocker, never converted into fake successful analysis. Profile labels render the complete manually edited name verbatim, including any build/version text the operator chooses; no build is automatically derived or appended. Historical Runs display their stored name snapshot. Actual report OS/build telemetry remains separate and unchanged. Grub archives are authenticated private downloads, not public static assets.
-3
View File
@@ -56,9 +56,6 @@ const labels: Record<string, string> = {
online: "С интернетом",
disabled: "Отключено",
};
export function windowsLabel(name: string, osBuild: string | null) {
return `${name} — build ${osBuild ?? "не определён"}`;
}
export function Status({ value, label }: { value: string; label?: string }) {
const tone = [
-2
View File
@@ -56,7 +56,6 @@ export interface Profile {
name: string;
os: string;
architecture: string;
os_build: string | null;
enabled: boolean;
qualification: "unqualified" | "qualified" | "drifted";
state: "maintenance" | "published";
@@ -102,7 +101,6 @@ export interface Run {
revision_id: string;
antivirus: "defender";
status: string;
os_build: string | null;
attempts: Attempt[];
}
export interface Job {
+5 -2
View File
@@ -38,7 +38,6 @@ import {
PageHeader,
Panel,
Status,
windowsLabel,
} from "../components";
function UsersAdmin() {
@@ -351,7 +350,7 @@ function ProfileEditor({
};
return (
<Panel
title={windowsLabel(profile.name, profile.os_build)}
title={profile.name}
subtitle={`${profile.os} · ${profile.architecture}`}
action={<Status value={profile.qualification} />}
>
@@ -382,6 +381,10 @@ function ProfileEditor({
value={name}
onChange={(event) => setName(event.target.value)}
/>
<small className="field-hint">
Укажите версию Windows вручную в названии профиля, например
«Windows 11 Pro 25H2 — build 26200.6584 — VM7001». Она не определяется автоматически.
</small>
</Field>
<label className="checkbox-field">
<input
+1 -2
View File
@@ -36,7 +36,6 @@ import {
PageHeader,
Panel,
Status,
windowsLabel,
} from "../components";
const phases = [
@@ -685,7 +684,7 @@ export function JobDetailPage() {
{job.runs.map((run) => (
<div className="run-card" key={run.id}>
<div className="run-heading">
<h2 className="windows-label">{windowsLabel(run.profile_name, run.os_build)}</h2>
<h2 className="windows-label">{run.profile_name}</h2>
<Status value={run.status} />
</div>
<p className="muted small-text">
+1 -2
View File
@@ -36,7 +36,6 @@ import {
PageHeader,
Panel,
Status,
windowsLabel,
} from "../components";
const initialSettings: Settings = {
@@ -360,7 +359,7 @@ export function NewAnalysisPage() {
<i />
</span>
<span className="profile-choice-copy">
<strong className="windows-label">{windowsLabel(profile.name, profile.os_build)}</strong>
<strong className="windows-label">{profile.name}</strong>
<small>
{profile.os} · {profile.architecture}
</small>
+2 -3
View File
@@ -29,7 +29,6 @@ import {
PageHeader,
Panel,
Status,
windowsLabel,
} from "../components";
export function JobsTable({
@@ -73,7 +72,7 @@ export function JobsTable({
<td>
<div className="table-environments">
{(job.runs ?? []).map((run) => (
<span className="windows-label" key={run.id}>{windowsLabel(run.profile_name, run.os_build)}</span>
<span className="windows-label" key={run.id}>{run.profile_name}</span>
))}
{!job.runs?.length && (
<span className="muted">Не назначены</span>
@@ -455,7 +454,7 @@ export function EnvironmentsPage() {
</div>
<div className="panel-padding">
<div className="environment-title">
<h2 className="windows-label">{windowsLabel(profile.name, profile.os_build)}</h2>
<h2 className="windows-label">{profile.name}</h2>
<Status value={profile.qualification} />
</div>
<p className="muted">{profile.os}</p>