Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 59 additions & 3 deletions tests/console_cockpit_decision_validation.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,19 @@ try {
effective_tier: 'BALANCED_COMPOUNDING', effective_policy_id: 'demo-balanced-v3',
effective_policy_revision: 'r7', effective_observed_at: '2026-11-01T09:10:00Z',
temporary_restriction: { active: true, reason: 'Reduction only', until: null },
values: [{ key: 'max_gross_exposure', label_key: null, value: 45, unit: 'percent', status: 'known', source: 'server' }],
values: [
{ key: 'max_gross_exposure', label_key: null, value: 45, unit: 'percent', status: 'known', source: 'server' },
{ key: 'cash_floor', label_key: null, value: 100, unit: 'USD', status: 'known', source: 'mystery' },
{ key: 'mystery_limit', label_key: 'some.label.key', value: 2, unit: null, status: 'known', source: 'server' },
],
};
export const policy = (language) => wrap(language, h(EffectivePolicyPanel, { binding }));
export const policyKnownCode = (language) => wrap(language, h(EffectivePolicyPanel, {
binding: { ...binding, temporary_restriction: { active: true, reason: 'reduction_only', until: null } },
}));
export const policyNoReason = (language) => wrap(language, h(EffectivePolicyPanel, {
binding: { ...binding, temporary_restriction: { active: true, reason: null, until: null } },
}));
const base = {
operation_id: 'op-1', request_id: 'req-1', decision_id: 'decision-1', decision_revision: 3,
action: 'approve', title_key: null, account_alias: null, platform: null, release_id: null,
Expand Down Expand Up @@ -80,6 +90,18 @@ try {
export const pauseBlocked = (language) => wrap(language, h(PauseControl, {
operatingState: 'running', canPause: false, canResume: true, pending: false, reason: 'Platform does not allow pausing here',
}));
export const pauseKnownCode = (language) => wrap(language, h(PauseControl, {
operatingState: 'running', canPause: false, canResume: true, pending: false, reason: 'runtime_control_pending',
}));
export const failedKnownReason = (language) => wrap(language, h(ApplicationStatus, {
operation: { ...base, state: 'failed', failure_reason: 'runtime_control_pending' }, status: 'ready',
}));
export const failedFreeText = (language) => wrap(language, h(ApplicationStatus, {
operation: { ...base, state: 'failed', failure_reason: 'platform exploded at 03:00' }, status: 'ready',
}));
export const unknownFreeText = (language) => wrap(language, h(ApplicationStatus, {
operation: { ...base, state: 'unknown', applied_at: null, unknown_reason: 'weird thing happened' }, status: 'ready',
}));
export const confirmed = (language) => wrap(language, h(ApplicationStatus, {
operation: { ...base, runtime_confirmed_at: '2026-11-01T10:05:00Z', runtime_state: 'running' }, status: 'ready',
}));
Expand Down Expand Up @@ -323,7 +345,30 @@ try {
const policyEn = ui.policy("en");
assert.match(policyEn, /Growth compounding/, "the selected preference is shown");
assert.match(policyEn, /Balanced compounding/, "the observed policy is not overwritten by the selection");
assert.match(policyEn, /Reduction only/, "a temporary restriction is shown separately");
assert.match(policyEn, /Risk reduction only/, "the legacy restriction string shows its bilingual product label");
assert.doesNotMatch(policyEn.replace(/ data-[a-z-]+="[^"]*"/g, ''), /Reduction only/, "the raw restriction string is suppressed");
assert.match(ui.policyKnownCode("zh"), /仅允许降低风险/);
assert.match(ui.policyKnownCode("en"), /Risk reduction only/);
assert.match(ui.policyNoReason("zh"), /已启用临时限制,原因未知/);
assert.match(ui.policyNoReason("en"), /Temporary restriction active; reason unknown/);
// P03: limit keys, sources and units are copy-driven; unknowns never render raw.
const policyVisible = policyEn.replace(/ data-[a-z-]+="[^"]*"/g, '');
assert.match(policyEn, /Maximum gross exposure/);
assert.match(policyEn, /45%/, "percent renders as the symbol in both languages");
assert.match(policyEn, /Cash floor/);
assert.match(policyEn, /Other limit/);
assert.match(policyEn, /Source: Server/);
assert.match(policyEn, /Unknown source/);
assert.doesNotMatch(policyVisible, /max_gross_exposure|cash_floor|mystery_limit|some\.label\.key|45 percent|percent|USD/,
"raw limit keys, dotted label keys and unknown units never reach visible text");
assert.doesNotMatch(policyVisible, /Source: mystery|Source: server|Source: null/);
const policyZh = ui.policy("zh");
assert.match(policyZh, /最大总敞口/);
assert.match(policyZh, /现金下限/);
assert.match(policyZh, /其他限制/);
assert.match(policyZh, /来源:服务端/);
assert.match(policyZh, /来源未知/);
assert.match(ui.policy("zh"), /临时限制/);
assert.match(policyEn, /Policy mapping unavailable/, "a missing approved mapping stays unavailable");

// Applied is not runtime-confirmed, and the caveat follows the server capability flag.
Expand Down Expand Up @@ -363,8 +408,19 @@ try {
assert.match(ui.pause("zh"), /暂停不会平仓/);
assert.doesNotMatch(ui.pause("en"), /aria-describedby/, "an enabled control needs no reason link");
const pauseBlocked = ui.pauseBlocked("en");
assert.match(pauseBlocked, /Platform does not allow pausing here/);
assert.match(pauseBlocked, /This action is not supported right now\./, "free-form pause reasons fall back to the safe copy");
assert.doesNotMatch(pauseBlocked, /Platform does not allow pausing here/);
assert.match(pauseBlocked, /aria-describedby=/);
assert.match(ui.pauseBlocked("zh"), /当前不支持该操作/);
assert.match(ui.pauseKnownCode("en"), /The previous action is awaiting confirmation/, "known pause reason codes keep their copy");
assert.match(ui.pauseKnownCode("zh"), /上次操作仍待确认/);
// P06: application reasons render through copy; free-form failure text is suppressed.
assert.match(ui.failedKnownReason("en"), /The previous action is awaiting confirmation/);
const failedTextEn = ui.failedFreeText("en");
assert.match(failedTextEn, /Operation outcome pending confirmation/);
assert.doesNotMatch(failedTextEn, /platform exploded/);
assert.match(ui.failedFreeText("zh"), /操作结果待确认/);
assert.doesNotMatch(ui.unknownFreeText("en"), /weird thing happened/);

// Accepted delivery is not delivered, and coverage stays visible.
const digest = ui.digestAccepted("en");
Expand Down
128 changes: 128 additions & 0 deletions tests/console_frontend_i18n_validation.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// Frontend text-leak regression: M01/M02/M05/M06 translate fallbacks and P01/P02/P04 rendering.
import assert from "node:assert/strict";
import { mkdtemp, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { createRequire } from "node:module";
import { fileURLToPath } from "node:url";
import { build } from "../web/strategy-switch-console/frontend/node_modules/esbuild/lib/main.js";

const root = fileURLToPath(new URL("../web/strategy-switch-console/frontend/", import.meta.url));
const directory = await mkdtemp(join(tmpdir(), "frontend-i18n-"));
const visible = (html) => html.replace(/ data-[a-z-]+="[^"]*"/g, "");
try {
const outfile = join(directory, "i18n.cjs");
await build({
stdin: {
resolveDir: root,
contents: `
import { createElement as h } from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import { I18nProvider, translate, useT } from './src/i18n';
import { AuditTimeline, regimeLabel } from './src/components/cockpit';
import { loadAuditEvents } from './src/api/cockpit';
export { translate, loadAuditEvents };
export const tr = (language, key, fallback) => translate(language, key, {}, fallback);
const RegimeText = ({ value }) => { const t = useT(); return h('p', { className: 'regime-text' }, regimeLabel(value, t)); };
export const regime = (language, value) => renderToStaticMarkup(h(I18nProvider, { language }, h(RegimeText, { value })));
const events = [
{ event_id: 'e1', occurred_at: '2026-11-01T10:00:00Z', actor: 'owner', action: 'record_owner_decision',
subject: { kind: 'owner_decision', id: 'demo' }, revision: 7, decision_id: 'd-1', operation_id: null, outcome: 'decided' },
{ event_id: 'e2', occurred_at: '2026-11-01T10:00:01Z', actor: null, action: 'some_new_action',
subject: { kind: 'mystery_kind', id: 'x-1' }, revision: null, decision_id: null, operation_id: null, outcome: 'weird_outcome' },
];
export const audit = (language) => renderToStaticMarkup(h(I18nProvider, { language },
h(AuditTimeline, { events, status: 'ready' })));
`,
},
bundle: true,
platform: "node",
format: "cjs",
outfile,
jsx: "automatic",
loader: { ".css": "empty" },
define: { "import.meta.env": "{}" },
logLevel: "silent",
});
const ui = createRequire(import.meta.url)(outfile);

// M05/M01/M02/M04/M06/M07: dynamic keys fall back to localized copy, never the raw key.
assert.equal(ui.tr("zh", "decisions.action.some_action"), "未知操作");
assert.equal(ui.tr("en", "decisions.action.some_action"), "Unknown action");
assert.equal(ui.tr("zh", "some.label.key"), "未知");
assert.equal(ui.tr("en", "some.label.key"), "Unknown");
assert.equal(ui.tr("zh", "constructor"), "未知", "prototype keys never resolve as functions");
assert.equal(ui.tr("zh", "reason.mystery_code"), "原因未知");
assert.equal(ui.tr("en", "reason.mystery_code"), "Unknown reason");
assert.equal(ui.tr("zh", "state.mystery_status"), "未知状态");
assert.equal(ui.tr("zh", "research.state.mystery"), "未知状态");
assert.equal(ui.tr("zh", "research.source.synthetic-source"), "其他研究来源");
assert.equal(ui.tr("en", "research.source.synthetic-source"), "Other research source");
assert.equal(ui.tr("en", "research.source.research-mirror"), "Research mirror");
assert.equal(ui.tr("zh", "research.source.quant-advisor-research"), "量化研究信号");
// M02/M06: known machine values keep their vetted copy; unknown modes never render the raw enum.
assert.equal(ui.tr("zh", "strategies.execution.paper"), "模拟");
assert.equal(ui.tr("zh", "strategies.execution.live"), "实盘");
assert.equal(ui.tr("zh", "strategies.execution.legacy_live"), "实盘");
assert.equal(ui.tr("en", "strategies.execution.dry_run"), "Dry run");
assert.equal(ui.tr("zh", "strategies.execution.mystery_mode"), "执行模式未知");
assert.equal(ui.tr("en", "strategies.execution.mystery_mode"), "Execution mode unknown");
assert.equal(ui.tr("en", "reason.runtime_control_pending"), "The previous action is awaiting confirmation");
assert.equal(ui.tr("zh", "accounts.field.mystery_field"), "其他参数");
assert.equal(ui.tr("en", "accounts.field.mystery_field"), "Other parameter");
assert.equal(ui.tr("zh", "initial_enrollment.fact.some_field"), "其他字段");
assert.equal(ui.tr("zh", "initial_enrollment.scope_kind.mystery"), "未知");

// P04: regime effects render through copy only.
const regimeZhKnown = visible(ui.regime("zh", "risk_reduction_only"));
assert.match(regimeZhKnown, /仅允许降低风险/);
assert.match(visible(ui.regime("en", "risk_reduction_only")), /Risk reduction only/);
const regimeUnknown = visible(ui.regime("zh", "mystery_effect"));
assert.match(regimeUnknown, /市场状态影响未知/);
assert.match(visible(ui.regime("en", "mystery_effect")), /Regime effect unknown/);
assert.doesNotMatch(regimeUnknown, /mystery effect|mystery_effect/, "unknown regimes are never humanized or raw");

// P01/P02: audit actions, outcomes and structured subjects are labeled, not machine text.
const auditZh = visible(ui.audit("zh"));
assert.match(auditZh, /记录负责人决定/);
assert.match(auditZh, /对象:负责人决定 · demo/);
assert.match(auditZh, /结果 已决定/);
assert.match(auditZh, /记录修订 7/);
assert.match(auditZh, /其他操作/);
assert.match(auditZh, /其他对象/);
assert.match(auditZh, /结果 未知/, "unknown outcomes render the exact localized value");
assert.doesNotMatch(auditZh, /结果未知|weird_outcome/);
const auditEn = visible(ui.audit("en"));
assert.match(auditEn, /Owner decision recorded/);
assert.match(auditEn, /Subject: Owner decision · demo/);
assert.match(auditEn, /Outcome Decided/);
assert.match(auditEn, /Record revision 7/);
assert.match(auditEn, /Other action/);
assert.match(auditEn, /Other subject/);
assert.match(auditEn, /Outcome Unknown/, "unknown outcomes render the exact localized value");
assert.doesNotMatch(auditEn, /Outcome unknown/);
assert.doesNotMatch(auditEn, /record owner decision|owner_decision:|some new action|mystery kind|weird outcome/,
"raw action, kind and outcome codes never reach visible text");

// P02 adapter: subjects stay structured; a legacy "kind: id" string splits instead of concatenating.
const realFetch = globalThis.fetch;
try {
const jsonResponse = (payload) => ({ status: 200, ok: true, json: async () => payload });
globalThis.fetch = async () => jsonResponse({ events: [
{ event_id: "e1", occurred_at: "2026-11-01T10:00:00Z", action: "approval_recorded", subject: { kind: "strategy_promotion", id: "p-1" }, outcome: "applied", revision: 2 },
{ event_id: "e2", occurred_at: "2026-11-01T10:00:01Z", action: "approval_recorded", subject: "owner_decision: d-9", outcome: null, revision: null },
{ event_id: "e3", occurred_at: "2026-11-01T10:00:02Z", action: "approval_recorded", subject: "plain-id", outcome: null, revision: null },
] });
const read = await ui.loadAuditEvents();
assert.equal(read.status, "ready");
assert.deepEqual(read.data[0].subject, { kind: "strategy_promotion", id: "p-1" });
assert.deepEqual(read.data[1].subject, { kind: "owner_decision", id: "d-9" });
assert.deepEqual(read.data[2].subject, { kind: "unknown", id: "plain-id" });
assert.equal(read.data[0].action, "approval_recorded");
} finally {
globalThis.fetch = realFetch;
}
} finally {
await rm(directory, { recursive: true, force: true });
}
console.log("console_frontend_i18n_validation: ok");
34 changes: 34 additions & 0 deletions tests/initial_enrollment_ui_validation.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -110,5 +110,39 @@ try {
assert.ok(html.includes(`class="decision-ref">${language==='zh'?'编号':'Ref'} IN-TEST`),`${language}: that one occurrence is the header ref`);
assert.doesNotMatch(html,/class="reconciliation-ref"/,`${language}: the material row reuses the header ref instead of repeating the number`);
}
// Leak regressions M02-M04/M07: enrollment enums, unknown fact fields, scope enums and
// diff field names render only vetted bilingual copy; raw machine values never reach visible text or title.
// (M02 execution-mode copy and its unknown fallback are exercised via translate in console_frontend_i18n_validation.mjs.)
const strip=(h)=>h.replace(/ data-[a-z-]+="[^"]*"/g,'');
const positionsItem={symbol:'AAPL',action:'BUY',quantity:'10',status:'WeirdState',order_type:'LMT',sec_type:'STK',right:'CALL',currency:'USD'};
const openOrderItem={status:'Submitted',action:'SELL',side:'SELL',order_type:'MKT',price:'3.5'};
const filledItem={status:'Filled',legs:[{right:'P',sec_type:'OPT'}]};
const facts2={observed_at:'2026-10-29T00:00:00Z',surfaces:Object.fromEntries(names.map((n,i)=>[n,{status:'complete',
items:n==='positions'?[positionsItem,openOrderItem,filledItem]:[],
scope:n==='positions'?{kind:'mystery_kind',currency:'USD',window_start:'2026-10-01T00:00:00Z',window_end:null,limit_per_namespace:'50',gateway_availability:'weird',truncated:'maybe'}:{kind:kinds[i],currency:null,window_start:null,window_end:null,limit_per_namespace:null,gateway_availability:null,truncated:null}}]))};
const leakItem={...item,diff:[
{field:'some_field',label_key:'unknown.label.key',before:'1',after:'2',affects_live:false},
{field:'dca_mode',label_key:'accounts.field.dca_mode',before:'fixed',after:'smart',affects_live:false},
],initial_enrollment:{...item.initial_enrollment,facts:facts2}};
for (const language of ['zh','en']) {
const html=strip(ui.renderLang(leakItem,language));
const known=language==='zh'
? ['买入','卖出','已提交','已成交','限价','市价','股票','期权','看涨','看跌']
: ['Buy','Sell','Submitted','Filled','Limit','Market','Stock','Option','Call','Put'];
for (const label of known) assert.ok(html.includes(`>${label}<`),`${language}: enum value renders as ${label}`);
assert.ok(html.includes(`>${language==='zh'?'未知':'Unknown'}<`),`${language}: unknown enum falls back to safe copy`);
assert.ok(html.includes(language==='zh'?'其他参数':'Other parameter'),`${language}: unknown diff field is labeled`);
assert.ok(html.includes(language==='zh'?'定投模式':'DCA mode'),`${language}: known diff field keeps its label`);
const forbidden=language==='zh'
? ['>BUY<','>SELL<','>Submitted<','>Filled<','>LMT<','>MKT<','>STK<','>OPT<','>CALL<','>P<','>WeirdState<','mystery_kind','>weird<','>maybe<','some_field','unknown.label.key','>current_broker_day<']
: ['>BUY<','>SELL<','>LMT<','>MKT<','>STK<','>OPT<','>CALL<','>P<','>WeirdState<','mystery_kind','>weird<','>maybe<','some_field','unknown.label.key'];
for (const raw of forbidden) assert.ok(!html.includes(raw),`${language}: raw value ${raw} never appears in visible markup`);
assert.doesNotMatch(html,/title="[^"]*(some_field|unknown\.label\.key|BUY|SELL|LMT|STK|CALL)/,`${language}: no raw value hides in a title attribute`);
// Allowed business values survive verbatim.
assert.ok(html.includes('>AAPL<'),`${language}: symbol stays verbatim`);
assert.ok(html.includes('>USD<'),`${language}: currency stays verbatim`);
assert.ok(html.includes('>2026-10-01T00:00:00Z<'),`${language}: window timestamp stays verbatim`);
assert.ok(html.includes('>50<'),`${language}: numeric limit stays verbatim`);
}
console.log('initial_enrollment_ui_validation: PASS');
} finally {await rm(dir,{recursive:true,force:true});}
Loading
Loading