Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
fbc17e5
⚡ Bolt: [performance improvement] PDF 바이트 배열 변환 최적화
seonghobae Sep 8, 2026
b127907
⚡ Bolt: [performance improvement] PDF 바이트 배열 변환 최적화
seonghobae Sep 8, 2026
8cade48
trigger review
seonghobae Sep 8, 2026
d14ddd3
fix(score): reject non-byte bridge values
seonghobae Sep 8, 2026
d9d8ed1
trigger review
seonghobae Sep 8, 2026
68bee2f
trigger review
seonghobae Sep 8, 2026
e8c6853
⚡ Bolt: [performance improvement] PDF 바이트 배열 변환 최적화 (엄격한 검증 추가)
seonghobae Sep 8, 2026
06f0c19
chore(score): restore supply-chain test owner boundary
seonghobae Sep 8, 2026
61eddb0
trigger review
seonghobae Sep 8, 2026
7d27e95
merge: adopt canonical formatter prerequisite for score bridge
seonghobae Sep 21, 2026
0067f8d
test(score): reject oversized bridge arrays before byte access
seonghobae Sep 21, 2026
698d0dc
fix(score): bound PDF bridge bytes before conversion
seonghobae Sep 21, 2026
cf034b6
test(score): cover oversized typed bridge responses
seonghobae Sep 21, 2026
a97bae9
test(score): avoid allocating oversized bridge fixtures
seonghobae Sep 21, 2026
7c53c54
test(score): reject invalid attachment size metadata
seonghobae Sep 21, 2026
bf97eda
fix(score): validate attachment size metadata
seonghobae Sep 21, 2026
998d164
docs(score): trace renderer bridge resource admission
seonghobae Sep 21, 2026
333008b
test(score): reject impossible attachment identity metadata
seonghobae Sep 21, 2026
335aba6
fix(score): validate attachment identity bridge metadata
seonghobae Sep 21, 2026
b5002d4
docs(score): trace attachment identity admission
seonghobae Sep 21, 2026
3b4bbe2
test(score): reject impossible empty bridge payloads
seonghobae Sep 21, 2026
e454d52
fix(score): reject zero-byte score bridge payloads
seonghobae Sep 21, 2026
99ef7c0
docs(score): trace zero-byte bridge admission repair
seonghobae Sep 21, 2026
d719680
docs(score): distinguish zero-byte consumer guard from native read owner
seonghobae Sep 21, 2026
82e71a6
test(score): reject whitespace-only bridge filenames
seonghobae Sep 21, 2026
ebee7c1
fix(score): align bridge filenames with durable schema
seonghobae Sep 21, 2026
8c1694a
docs(traceability): record non-blank score filename contract
seonghobae Sep 21, 2026
7455614
test(score): reject malformed ids before score IPC
seonghobae Sep 21, 2026
36a9a48
fix(score): validate score ids before native IPC
seonghobae Sep 21, 2026
700fba2
test(score): keep IPC id cases type-safe
seonghobae Sep 21, 2026
0e678c4
docs(traceability): bind score id IPC admission
seonghobae Sep 21, 2026
8773992
docs(traceability): correct score bridge contract authority
seonghobae Sep 21, 2026
b12fc68
test(score): reject malformed project context before IPC
seonghobae Sep 21, 2026
8989c96
fix(score): admit project context before score IPC
seonghobae Sep 21, 2026
ecf7815
docs(score): trace project-context IPC admission
seonghobae Sep 21, 2026
c2c3f0c
trigger review
seonghobae Sep 23, 2026
b09d1fd
repair(score): restore bridge admission after destructive review trigger
seonghobae Sep 23, 2026
a7d6f20
Understood. Acknowledging that this work is now obsolete and stopping…
seonghobae Sep 23, 2026
ff0f0c2
repair(score): restore bounded bridge owner after obsolete continuation
seonghobae Sep 23, 2026
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
46 changes: 46 additions & 0 deletions apps/desktop/src/features/score/scoreStorage.bench.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { bench, describe } from "vitest";

/** Documented. */
function validateOld(response: unknown[]) {
if (Array.isArray(response) && response.every((byte) => typeof byte === "number")) {
return Uint8Array.from(response as number[]);
}
throw new Error("invalid");
}

/** Documented. */
function validateNew(response: unknown[]) {
if (Array.isArray(response)) {
const len = response.length;
const arr = new Uint8Array(len);
let isValid = true;
for (let i = 0; i < len; i++) {
const byte = response[i];
if (typeof byte !== "number" || !Number.isInteger(byte) || byte < 0 || byte > 255) {
isValid = false;
break;
}
arr[i] = byte;
}
if (isValid) {
return arr;
}
}
throw new Error("invalid");
}

describe("PDF byte array processing", () => {
const size = 5_000_000;
const payload = new Array(size);
for (let i = 0; i < size; i++) {
payload[i] = i % 256;
}

bench("legacy Array.from and every", () => {
validateOld(payload);
});

bench("single pass pre-allocated loop", () => {
validateNew(payload);
});
});
217 changes: 213 additions & 4 deletions apps/desktop/src/features/score/scoreStorage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ type TauriWindow = Window & {
};

const BRIDGE_UNAVAILABLE_MESSAGE = "Score PDFs are only available in the desktop app.";
const INVALID_RESPONSE_MESSAGE = "Invalid score bridge response";
const MAX_SCORE_BYTES = 25 * 1024 * 1024;
const OVERSIZED_SCORE_BYTES = MAX_SCORE_BYTES + 1;
const VALID_PROJECT_ID = "project-1-2";
const VALID_SONG_ID = "song-1";
const VALID_SCORE_ID = "6fa459ea-ee8a-4ca4-894e-db77e160355e";

describe("scoreStorage bridge resolution", () => {
afterEach(() => {
Expand All @@ -22,14 +28,217 @@ describe("scoreStorage bridge resolution", () => {
// return null so callers fail closed instead of dereferencing `window`.
vi.stubGlobal("window", undefined);

await expect(attachScorePdf("project-1", "song-1")).rejects.toThrow(
await expect(attachScorePdf(VALID_PROJECT_ID, VALID_SONG_ID)).rejects.toThrow(
BRIDGE_UNAVAILABLE_MESSAGE
);
await expect(readScorePdf("project-1", "score-1")).rejects.toThrow(
await expect(readScorePdf(VALID_PROJECT_ID, VALID_SCORE_ID)).rejects.toThrow(
BRIDGE_UNAVAILABLE_MESSAGE
);
await expect(removeScorePdf("project-1", "score-1")).rejects.toThrow(
await expect(removeScorePdf(VALID_PROJECT_ID, VALID_SCORE_ID)).rejects.toThrow(
BRIDGE_UNAVAILABLE_MESSAGE
);
});
});

it("preserves valid attachment metadata from the bridge", async () => {
(window as TauriWindow).__TAURI_INVOKE__ = vi.fn().mockResolvedValue({
scoreId: VALID_SCORE_ID,
fileName: "chart.pdf",
fileSizeBytes: 2048
});

await expect(attachScorePdf(VALID_PROJECT_ID, VALID_SONG_ID)).resolves.toEqual({
id: VALID_SCORE_ID,
fileName: "chart.pdf",
fileSizeBytes: 2048
});
});

it.each(["project-1", "../project-1-2", "PROJECT-1-2", "project-1-2-extra"])(
"rejects malformed project id before every score IPC: %s",
async (projectId) => {
const mockInvoke = vi.fn().mockResolvedValue({
scoreId: VALID_SCORE_ID,
fileName: "chart.pdf",
fileSizeBytes: 2048
});
(window as TauriWindow).__TAURI_INVOKE__ = mockInvoke;

await expect(attachScorePdf(projectId, VALID_SONG_ID)).rejects.toThrow(
INVALID_RESPONSE_MESSAGE
);
await expect(readScorePdf(projectId, VALID_SCORE_ID)).rejects.toThrow(
INVALID_RESPONSE_MESSAGE
);
await expect(removeScorePdf(projectId, VALID_SCORE_ID)).rejects.toThrow(
INVALID_RESPONSE_MESSAGE
);
expect(mockInvoke).not.toHaveBeenCalled();
}
);

it.each(["", " ", "\t"])(
"rejects blank song id before attach IPC",
async (songId) => {
const mockInvoke = vi.fn().mockResolvedValue({
scoreId: VALID_SCORE_ID,
fileName: "chart.pdf",
fileSizeBytes: 2048
});
(window as TauriWindow).__TAURI_INVOKE__ = mockInvoke;

await expect(attachScorePdf(VALID_PROJECT_ID, songId)).rejects.toThrow(
INVALID_RESPONSE_MESSAGE
);
expect(mockInvoke).not.toHaveBeenCalled();
}
);

it.each([
["empty score id", "", "chart.pdf"],
["non-canonical score id", "score-1", "chart.pdf"],
["uppercase score id", VALID_SCORE_ID.toUpperCase(), "chart.pdf"],
["empty file name", VALID_SCORE_ID, ""],
["whitespace-only file name", VALID_SCORE_ID, " \t "]
])("rejects %s attachment identity metadata", async (_label, scoreId, fileName) => {
(window as TauriWindow).__TAURI_INVOKE__ = vi.fn().mockResolvedValue({
scoreId,
fileName,
fileSizeBytes: 2048
});

await expect(attachScorePdf(VALID_PROJECT_ID, VALID_SONG_ID)).rejects.toThrow(
INVALID_RESPONSE_MESSAGE
);
});

it.each([
["NaN", Number.NaN],
["Infinity", Number.POSITIVE_INFINITY],
["negative", -1],
["fractional", 1.5],
["zero", 0],
["oversized", OVERSIZED_SCORE_BYTES]
])("rejects %s attachment size metadata", async (_label, fileSizeBytes) => {
(window as TauriWindow).__TAURI_INVOKE__ = vi.fn().mockResolvedValue({
scoreId: VALID_SCORE_ID,
fileName: "chart.pdf",
fileSizeBytes
});

await expect(attachScorePdf(VALID_PROJECT_ID, VALID_SONG_ID)).rejects.toThrow(
INVALID_RESPONSE_MESSAGE
);
});

it.each(["score-1", VALID_SCORE_ID.toUpperCase()])(
"rejects malformed score id before read IPC: %s",
async (scoreId) => {
const mockInvoke = vi.fn().mockResolvedValue([37, 80, 68, 70, 45]);
(window as TauriWindow).__TAURI_INVOKE__ = mockInvoke;

await expect(readScorePdf(VALID_PROJECT_ID, scoreId)).rejects.toThrow(
INVALID_RESPONSE_MESSAGE
);
expect(mockInvoke).not.toHaveBeenCalled();
}
);

it.each(["score-1", VALID_SCORE_ID.toUpperCase()])(
"rejects malformed score id before remove IPC: %s",
async (scoreId) => {
const mockInvoke = vi.fn().mockResolvedValue(true);
(window as TauriWindow).__TAURI_INVOKE__ = mockInvoke;

await expect(removeScorePdf(VALID_PROJECT_ID, scoreId)).rejects.toThrow(
INVALID_RESPONSE_MESSAGE
);
expect(mockInvoke).not.toHaveBeenCalled();
}
);

it("preserves exact bytes from a valid bridge array", async () => {
(window as TauriWindow).__TAURI_INVOKE__ = vi.fn().mockResolvedValue([0, 1, 255]);

await expect(readScorePdf(VALID_PROJECT_ID, VALID_SCORE_ID)).resolves.toEqual(
new Uint8Array([0, 1, 255])
);
});

it.each([
["array", () => []],
["Uint8Array", () => new Uint8Array()],
["ArrayBuffer", () => new ArrayBuffer(0)]
])("rejects an empty %s bridge response", async (_label, createResponse) => {
(window as TauriWindow).__TAURI_INVOKE__ = vi.fn().mockResolvedValue(createResponse());

await expect(readScorePdf(VALID_PROJECT_ID, VALID_SCORE_ID)).rejects.toThrow(
INVALID_RESPONSE_MESSAGE
);
});

it("rejects an oversized bridge array before allocating or reading its bytes", async () => {
const oversizedResponse = new Proxy(new Array(OVERSIZED_SCORE_BYTES), {
get(target, property, receiver) {
if (property !== "length") {
throw new Error("oversized bridge payload should be rejected before byte access");
}
return Reflect.get(target, property, receiver);
}
});
(window as TauriWindow).__TAURI_INVOKE__ = vi.fn().mockResolvedValue(oversizedResponse);

await expect(readScorePdf(VALID_PROJECT_ID, VALID_SCORE_ID)).rejects.toThrow(
INVALID_RESPONSE_MESSAGE
);
});

it.each([
[
"Uint8Array",
() =>
new Proxy(new Uint8Array(), {
get(target, property) {
if (property === "byteLength") {
return OVERSIZED_SCORE_BYTES;
}
return Reflect.get(target, property, target);
}
})
],
[
"ArrayBuffer",
() =>
new Proxy(new ArrayBuffer(0), {
get(target, property) {
if (property === "byteLength") {
return OVERSIZED_SCORE_BYTES;
}
return Reflect.get(target, property, target);
}
})
]
])("rejects an oversized %s bridge response", async (_label, createResponse) => {
(window as TauriWindow).__TAURI_INVOKE__ = vi.fn().mockResolvedValue(createResponse());

await expect(readScorePdf(VALID_PROJECT_ID, VALID_SCORE_ID)).rejects.toThrow(
INVALID_RESPONSE_MESSAGE
);
});

it.each([
["NaN", Number.NaN],
["Infinity", Number.POSITIVE_INFINITY],
["negative", -1],
["fractional", 1.5],
["greater than 255", 256],
["non-number", "1"]
])("rejects a %s bridge byte", async (_label, invalidByte) => {
(window as TauriWindow).__TAURI_INVOKE__ = vi
.fn()
.mockResolvedValue([0, invalidByte, 255]);

await expect(readScorePdf(VALID_PROJECT_ID, VALID_SCORE_ID)).rejects.toThrow(
INVALID_RESPONSE_MESSAGE
);
});
});
Loading