Compare commits

...

2 Commits

Author SHA1 Message Date
Xiangzhe
9deb6bf995 fix(i18n): translate readiness banner, sidebar and sidebar-preset strings for pt-BR/vi
en.json gained 22 keys (home readiness onboarding banner, sidebar
trafficInspectorPurpose, and the sidebar-customization preset labels/descs
under settings) that were never propagated to pt-BR.json / vi.json,
turning tests/unit/i18n-pt-br.test.ts (#6695 drift guard) and
tests/unit/i18n-vi-completeness.test.ts red across PRs #11301/#11303/#11304.

Added the missing translations to both locales at the corresponding nested
positions (sidebar / home / settings sections).
2026-08-23 21:52:25 -03:00
Xiangzhe
d861b76b5f fix(tests): drain compression/kiro/memory base-red mini-cluster from 2026-08-24 merges
Three stale unit tests went red across PRs #11301/#11303/#11304 because their
mocks/fixtures predated intentional contract changes merged the same day:

- compression-cli-rest-fallback-6571.test.ts: #10960 moved the CLI's MCP
  transport from the never-mounted /api/mcp/tools/call to the real
  Streamable HTTP endpoint /api/mcp/stream. The REST-fallback trigger in
  this test's fetch mock still targeted the retired path, so mcpCallTool()
  threw on an unmocked fetch instead of exercising the fallback. Updated
  the mock to intercept /api/mcp/stream.

- memory-system-first-6135.test.ts: #11290/#11303 added a Claude-family
  reroute to the leading-system-message placement (Opus 5 rejects a system
  message spliced right after a plain-text assistant turn). The regression
  test used "anthropic" as its NON-Claude-specific example, which is now
  classified as Claude-family and no longer exercises the plain cache-safe
  splice path it targets. Switched the fixture provider to "openai".

- kiro-auto-import-name-dedup-3615.test.ts: #10815/#11287 hardened
  findKiroConnectionByIdentity to require an account-level identifier
  (email/clientId) alongside a matching profileArn before trusting the
  match, since distinct Builder ID accounts can share a CodeWhisperer
  profile ARN. Extended findKiroConnectionByProfileArn (test-only helper)
  with an optional account-identity param, and added a companion test
  documenting the new ARN-alone-is-untrusted safety behavior.

All three are genuine stale-test drift, not production bugs: the code
changes were deliberate fixes from other reviewed PRs; only the tests'
fixtures needed to catch up.
2026-08-23 21:52:17 -03:00
6 changed files with 99 additions and 12 deletions

View File

@@ -439,13 +439,22 @@ type ProviderConnectionLike = {
* whose stored `providerSpecificData.profileArn` matches the given ARN.
* Returns null when profileArn is undefined/null or no match is found.
*
* #10815 hardened `findKiroConnectionByIdentity` to require an account-level
* identifier (email or clientId) alongside a matching profileArn before
* trusting the match — distinct Builder ID accounts (Google/GitHub social
* login) can share the same CodeWhisperer profile ARN, and matching on ARN
* alone let a second social login silently overwrite the first connection.
* `email`/`clientId` here let a caller supply that account identifier; the
* real `saveAndRespond()` call sites already do (see below).
*
* Exported for unit tests (#3615).
*/
export function findKiroConnectionByProfileArn(
connections: ProviderConnectionLike[],
profileArn: string | undefined
profileArn: string | undefined,
accountIdentity?: { email?: string | null; clientId?: string | null }
): ProviderConnectionLike | null {
return findKiroConnectionByIdentity(connections, { profileArn });
return findKiroConnectionByIdentity(connections, { profileArn, ...accountIdentity });
}
// ── Save to OmniRoute DB ──────────────────────────────────────────────────────

View File

@@ -1267,6 +1267,7 @@
"agentBridgeSubtitle": "Interceptar tráfego de agentes IDE",
"trafficInspector": "Inspector de Tráfego",
"trafficInspectorSubtitle": "Monitorar chamadas LLM + debugar tráfego HTTPS",
"trafficInspectorPurpose": "Veja exatamente o que sua aplicação envia e recebe dos provedores de IA. Funciona com qualquer cliente compatível com OpenAI.",
"cliCode": "CLI Code's",
"cliCodeSubtitle": "Ferramentas de código que apontam para o OmniRoute",
"cliAgents": "CLI Agents",
@@ -1868,7 +1869,16 @@
"directDownloadHint": "Ou baixe o formato do instalador respectivo diretamente:",
"releaseNotes": "Notas de Lançamento",
"readMore": "Leia Mais",
"noAuthLabel": "Sem Autenticação"
"noAuthLabel": "Sem Autenticação",
"readinessEyebrow": "Prepare-se para rotear",
"readinessTitle": "Envie sua primeira requisição",
"readinessSubtitle": "Quatro pequenos passos. O OmniRoute verifica a prontidão conforme você avança.",
"readinessStep1": "Conecte um provedor",
"readinessStep2": "Configure a autenticação do endpoint",
"readinessStep3": "Copie seu endpoint",
"readinessStep4": "Envie uma requisição de teste",
"readinessContinue": "Continuar configuração",
"readinessDismiss": "Dispensar por agora"
},
"analytics": {
"title": "Análises",
@@ -6700,6 +6710,18 @@
"sidebarVisibility": "Hide sidebar items",
"sidebarVisibilityDesc": "Hide any sidebar navigation entry to reduce visual clutter.",
"sidebarVisibilityHint": "Any sidebar section is hidden automatically when a...",
"presetAll": "Tudo",
"presetAllDesc": "Mostrar tudo",
"presetEssentials": "Essenciais",
"presetEssentialsDesc": "Caminho para iniciantes - Ferramentas avançadas continuam pesquisáveis",
"presetMinimal": "Mínimo",
"presetMinimalDesc": "Apenas páginas principais",
"presetDeveloper": "Desenvolvedor",
"presetDeveloperDesc": "Ferramentas de dev & proxy",
"presetAdmin": "Admin",
"presetAdminDesc": "Monitoramento & auditoria",
"settingsSidebarTitle": "Personalização da Barra Lateral",
"settingsSidebarDesc": "Escolha quais itens da barra lateral exibir. Essenciais mantém as ferramentas avançadas pesquisáveis.",
"hideHealthLogs": "Ocultar Logs de Health Check",
"hideHealthLogsDesc": "Quando ATIVADO, suprime mensagens [HealthCheck] no console do servidor",
"themeAccent": "Cor do tema",

View File

@@ -1267,6 +1267,7 @@
"agentBridgeSubtitle": "Chặn lưu lượng agent IDE",
"trafficInspector": "Traffic Inspector",
"trafficInspectorSubtitle": "Giám sát lệnh gọi LLM + gỡ lỗi mọi lưu lượng HTTPS",
"trafficInspectorPurpose": "Xem chính xác những gì ứng dụng của bạn gửi đến và nhận từ các nhà cung cấp AI. Hoạt động với bất kỳ ứng dụng khách nào tương thích với OpenAI.",
"cliCode": "CLI Code",
"cliCodeSubtitle": "Các công cụ lập trình trỏ đến OmniRoute",
"cliAgents": "CLI Agents",
@@ -1868,7 +1869,16 @@
"directDownloadHint": "Hoặc tải trực tiếp định dạng trình cài đặt phù hợp:",
"releaseNotes": "Ghi chú phát hành",
"readMore": "Đọc thêm",
"noAuthLabel": "Không xác thực"
"noAuthLabel": "Không xác thực",
"readinessEyebrow": "Chuẩn bị định tuyến",
"readinessTitle": "Gửi yêu cầu đầu tiên của bạn",
"readinessSubtitle": "Bốn bước nhỏ. OmniRoute kiểm tra mức độ sẵn sàng khi bạn thực hiện.",
"readinessStep1": "Kết nối một nhà cung cấp",
"readinessStep2": "Định cấu hình xác thực endpoint",
"readinessStep3": "Sao chép endpoint của bạn",
"readinessStep4": "Gửi một yêu cầu thử nghiệm",
"readinessContinue": "Tiếp tục thiết lập",
"readinessDismiss": "Bỏ qua lúc này"
},
"analytics": {
"title": "Phân tích",
@@ -6700,6 +6710,18 @@
"sidebarVisibility": "Ẩn các mục trên thanh bên",
"sidebarVisibilityDesc": "Ẩn bất kỳ mục điều hướng nào trên thanh bên để giảm bớt sự lộn xộn về mặt trực quan mà không vô hiệu hóa bất kỳ tính năng nào",
"sidebarVisibilityHint": "Bất kỳ phần nào trên thanh bên sẽ tự động bị ẩn khi tất cả các mục bên trong nó đều bị ẩn",
"presetAll": "Tất cả",
"presetAllDesc": "Hiển thị mọi thứ",
"presetEssentials": "Thiết yếu",
"presetEssentialsDesc": "Lộ trình cho người mới bắt đầu - Công cụ nâng cao vẫn có thể tìm kiếm",
"presetMinimal": "Tối giản",
"presetMinimalDesc": "Chỉ các trang cốt lõi",
"presetDeveloper": "Nhà phát triển",
"presetDeveloperDesc": "Công cụ dev & proxy",
"presetAdmin": "Quản trị",
"presetAdminDesc": "Giám sát & kiểm toán",
"settingsSidebarTitle": "Tùy chỉnh thanh bên",
"settingsSidebarDesc": "Chọn các mục trên thanh bên sẽ hiển thị. Thiết yếu giữ cho các công cụ nâng cao vẫn có thể tìm kiếm.",
"hideHealthLogs": "Ẩn nhật ký kiểm tra sức khỏe",
"hideHealthLogsDesc": "Khi BẬT, sẽ chặn các thông báo [HealthCheck] trong bảng điều khiển máy chủ",
"themeAccent": "Màu chủ đề",

View File

@@ -2,9 +2,15 @@ import test from "node:test";
import assert from "node:assert/strict";
// Repro for #6571 — REST-fallback path of `omniroute compression` (hit only when
// /api/mcp/tools/call is not mounted, i.e. mcpCall()'s 404/501 branch) uses the
// the MCP surface is not mounted, i.e. mcpCall()'s 404/501 branch) uses the
// nonexistent `engine` field instead of the canonical `defaultMode` field, and
// the table renderer prints "[object Object]" for nested object cells.
//
// #10960 moved the MCP transport from the never-mounted `/api/mcp/tools/call`
// to the real Streamable HTTP endpoint `/api/mcp/stream` (mcpClient.mjs ->
// callMcpEndpoint()). The REST-fallback trigger in these mocks must match
// that endpoint, not the retired one, or mcpCallTool() throws on an
// unmocked fetch instead of exercising the fallback path this test targets.
type MockResponse = Pick<Response, "ok" | "status" | "headers" | "json" | "text">;
@@ -45,7 +51,7 @@ test("restCompressionStatus (via runCompressionStatus REST fallback) should surf
const origFetch = globalThis.fetch;
globalThis.fetch = (async (url: string | URL | Request) => {
const u = String(url);
if (u.includes("/api/mcp/tools/call")) return makeResp({ error: "not mounted" }, 404);
if (u.includes("/api/mcp/stream")) return makeResp({ error: "not mounted" }, 404);
if (u.includes("/api/settings/compression")) {
// Canonical server payload — NOTE: field is `defaultMode`, there is no `engine` key.
// src/lib/db/compression.ts COMPRESSION_MODES / GET route just returns getCompressionSettings().
@@ -85,7 +91,7 @@ test("restSetEngine (via runCompressionEngineSet REST fallback) should PUT `defa
const putBodies: Record<string, unknown>[] = [];
globalThis.fetch = (async (url: string | URL | Request, init?: RequestInit) => {
const u = String(url);
if (u.includes("/api/mcp/tools/call")) return makeResp({ error: "not mounted" }, 404);
if (u.includes("/api/mcp/stream")) return makeResp({ error: "not mounted" }, 404);
if (u.includes("/api/settings/compression") && init?.method === "PUT") {
const body = init?.body ? JSON.parse(String(init.body)) : {};
putBodies.push(body);

View File

@@ -113,12 +113,18 @@ test("derived name is never empty or null", () => {
const FAKE_PROFILE_ARN = "arn:aws:iam::123456789012:user/sso-user";
const FAKE_CLIENT_ID = "client-abc";
const fakeConnectionWithArn = {
id: "conn-abc",
provider: "kiro",
authType: "oauth",
email: null,
providerSpecificData: { profileArn: FAKE_PROFILE_ARN, region: "us-east-1" },
providerSpecificData: {
profileArn: FAKE_PROFILE_ARN,
region: "us-east-1",
clientId: FAKE_CLIENT_ID,
},
};
const fakeConnectionNoArn = {
@@ -129,13 +135,29 @@ const fakeConnectionNoArn = {
providerSpecificData: { region: "us-east-1" },
};
test("findKiroConnectionByProfileArn returns the matching connection", async () => {
// The function should scan existing kiro connections and match by profileArn.
test("findKiroConnectionByProfileArn returns the matching connection when an account identifier agrees", async () => {
// #10815 — matching on profileArn alone is unsafe (distinct Builder ID
// accounts can share a profile ARN), so the caller must also supply an
// account-level identifier (email or clientId) that does not contradict
// the stored connection, exactly like saveAndRespond()'s real call sites do.
const result = await findKiroConnectionByProfileArn(
[fakeConnectionWithArn, fakeConnectionNoArn],
FAKE_PROFILE_ARN,
{ clientId: FAKE_CLIENT_ID }
);
assert.deepEqual(result, fakeConnectionWithArn);
});
test("findKiroConnectionByProfileArn returns null for a profileArn-only match with no account identifier (#10815)", async () => {
// Guards the #10815 fix: two different Builder ID accounts (Google/GitHub
// social login) can share the same CodeWhisperer profile ARN, so trusting
// an ARN match without any account identifier would let a second social
// login silently overwrite the first connection.
const result = await findKiroConnectionByProfileArn(
[fakeConnectionWithArn, fakeConnectionNoArn],
FAKE_PROFILE_ARN
);
assert.deepEqual(result, fakeConnectionWithArn);
assert.equal(result, null);
});
test("findKiroConnectionByProfileArn returns null when no match exists", async () => {

View File

@@ -111,7 +111,13 @@ describe("injectMemory system-must-be-first (#6135)", () => {
it("regression: a NON-flagged provider keeps the existing cache-safe placement", () => {
const req = multiTurn();
const out = injectMemory(req, [mem("dark mode")], "anthropic", { cacheSafe: true });
// #11290/#11303 added a Claude-family-specific reroute to injectSystemFirst()
// for the mid-array splice (a system message right after a plain-text
// assistant turn is rejected by Claude Opus 5), so "anthropic" no longer
// exercises the plain cache-safe splice path this test targets. Use a
// provider outside both the strict-system-first set AND the Claude family
// to keep testing the original (still-current) cache-safe behavior.
const out = injectMemory(req, [mem("dark mode")], "openai", { cacheSafe: true });
// Existing behavior: memory inserted just before the last user message (index 3).
assert.equal(out.messages[3].role, "system");
assert.ok(out.messages[3].content.includes("Memory context"));