Render manually authored Windows profile names verbatim
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user