From e6bb0ed2369a782845fa05202c54ca2724ced442 Mon Sep 17 00:00:00 2001 From: hamedmp Date: Sat, 30 May 2026 02:58:52 +0200 Subject: [PATCH 1/2] fix(apps): require shipped default app icons Summary: - Add the Profile manifest icon mapping to the committed profile asset. - Tighten the default app manifest test so missing icon fields fail. - Replace a pre-existing bare catch flagged by the pattern scanner. Rationale: - Default app icons should resolve deterministically from shipped assets instead of relying on per-user regeneration paths. - The previous validation only caught invalid string icons, not missing icon fields. Tests: - node scripts/build-default-apps.mjs home/apps - bun run test -- tests/gateway/apps.test.ts tests/gateway/default-icons.test.ts - bun run typecheck - bun run check:patterns - bun run test --- home/apps/profile/matrix.json | 1 + shell/src/lib/error-boundary-utils.ts | 3 ++- tests/gateway/apps.test.ts | 6 ++++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/home/apps/profile/matrix.json b/home/apps/profile/matrix.json index d54e61f8f..83dba07d4 100644 --- a/home/apps/profile/matrix.json +++ b/home/apps/profile/matrix.json @@ -3,6 +3,7 @@ "description": "Your Matrix profile page", "runtime": "vite", "category": "social", + "icon": "profile", "version": "1.0.0", "slug": "profile", "runtimeVersion": "^1.0.0", diff --git a/shell/src/lib/error-boundary-utils.ts b/shell/src/lib/error-boundary-utils.ts index 9e6398bda..503fd4df1 100644 --- a/shell/src/lib/error-boundary-utils.ts +++ b/shell/src/lib/error-boundary-utils.ts @@ -16,7 +16,8 @@ export function describeUnknownError(error: unknown): string { if (error instanceof globalThis.Error) return `${error.name}: ${error.message}`; try { return String(error); - } catch { + } catch (stringifyError) { + if (stringifyError instanceof globalThis.Error) return stringifyError.name; return typeof error; } } diff --git a/tests/gateway/apps.test.ts b/tests/gateway/apps.test.ts index 5f7b52b42..0a8d61cd9 100644 --- a/tests/gateway/apps.test.ts +++ b/tests/gateway/apps.test.ts @@ -262,7 +262,7 @@ describe("T711: GET /api/apps", () => { expect(names).toContain("Timer"); }); - it("ships icons for every default app manifest", () => { + it("requires every default app manifest to declare a shipped icon", () => { const repoRoot = resolve(fileURLToPath(new URL("../..", import.meta.url))); const appsRoot = join(repoRoot, "home/apps"); const iconsRoot = join(repoRoot, "home/system/icons"); @@ -287,7 +287,9 @@ describe("T711: GET /api/apps", () => { continue; } const manifest = JSON.parse(readFileSync(fullPath, "utf8")) as { icon?: unknown }; - if (typeof manifest.icon === "string" && !shippedIcons.has(manifest.icon)) { + if (typeof manifest.icon !== "string") { + missing.push(`${fullPath.replace(`${repoRoot}/`, "")}: missing icon`); + } else if (!shippedIcons.has(manifest.icon)) { missing.push(`${fullPath.replace(`${repoRoot}/`, "")}: ${manifest.icon}`); } } From 60db1bb781b33e70291e9ac7d86374fd84ba2c3a Mon Sep 17 00:00:00 2001 From: hamedmp Date: Sat, 30 May 2026 03:20:51 +0200 Subject: [PATCH 2/2] fix(shell): keep error fallback tied to original value Summary: - Add a regression test for describeUnknownError when string coercion itself throws. - Return the original value type in that fallback path instead of the stringify failure name. Rationale: - Greptile flagged that returning the stringify failure's Error.name can mislead diagnostics by implying it describes the original thrown value. - The generic typeof fallback preserves the previous agnostic behavior while still satisfying the no-bare-catch scanner rule. Tests: - bun run test -- tests/shell/error-boundary-utils.test.ts - node scripts/build-default-apps.mjs home/apps - bun run test -- tests/gateway/apps.test.ts tests/gateway/default-icons.test.ts tests/shell/error-boundary-utils.test.ts - bun run typecheck - bun run check:patterns - bun run test --- shell/src/lib/error-boundary-utils.ts | 2 +- tests/shell/error-boundary-utils.test.ts | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 tests/shell/error-boundary-utils.test.ts diff --git a/shell/src/lib/error-boundary-utils.ts b/shell/src/lib/error-boundary-utils.ts index 503fd4df1..3d179272a 100644 --- a/shell/src/lib/error-boundary-utils.ts +++ b/shell/src/lib/error-boundary-utils.ts @@ -17,7 +17,7 @@ export function describeUnknownError(error: unknown): string { try { return String(error); } catch (stringifyError) { - if (stringifyError instanceof globalThis.Error) return stringifyError.name; + void stringifyError; return typeof error; } } diff --git a/tests/shell/error-boundary-utils.test.ts b/tests/shell/error-boundary-utils.test.ts new file mode 100644 index 000000000..8e3af142a --- /dev/null +++ b/tests/shell/error-boundary-utils.test.ts @@ -0,0 +1,15 @@ +import { describe, expect, it } from "vitest"; + +import { describeUnknownError } from "../../shell/src/lib/error-boundary-utils"; + +describe("describeUnknownError", () => { + it("falls back to the original value type when string coercion throws", () => { + const errorLikeValue = { + [Symbol.toPrimitive]() { + throw new TypeError("string coercion failed"); + }, + }; + + expect(describeUnknownError(errorLikeValue)).toBe("object"); + }); +});