fix(storage): address CI and review feedback

This commit is contained in:
2026-08-18 22:42:26 -07:00
parent 06b21a68fa
commit 80ffa26400
8 changed files with 75 additions and 18 deletions
+2
View File
@@ -89,6 +89,7 @@ test('runtime guard blocks a profile downgrade before rewriting its safety recor
if (result.ok) return;
assert.equal(result.title, 'Electron downgrade blocked');
assert.match(result.details, /destroy Yomitan dictionaries/);
assert.equal(result.details.includes(statePath), true);
assert.deepEqual(JSON.parse(fs.readFileSync(statePath, 'utf8')), {
highestElectronMajor: 44,
lastElectronVersion: '44.1.0',
@@ -114,6 +115,7 @@ test('runtime guard blocks a downgrade within the supported Electron major', ()
assert.equal(result.ok, false);
if (result.ok) return;
assert.equal(result.title, 'Electron downgrade blocked');
assert.equal(result.details.includes(statePath), true);
assert.deepEqual(JSON.parse(fs.readFileSync(statePath, 'utf8')), {
highestElectronMajor: 43,
lastElectronVersion: '43.4.1',
+1
View File
@@ -137,6 +137,7 @@ export function enforceElectronRuntimeGuard(options: {
details: [
`This profile was previously opened with Electron ${previousState.state.lastElectronVersion}.`,
`The current runtime is Electron ${options.electronVersion}.`,
`Runtime safety record: ${statePath}.`,
'',
'Opening Chromium storage with an older Electron version can destroy Yomitan dictionaries. Upgrade SubMiner before using this profile.',
].join('\n'),
@@ -27,12 +27,15 @@ test('dictionary integrity observation establishes and updates a non-empty basel
safe: true,
previousCount: 5,
});
assert.deepEqual(
JSON.parse(
fs.readFileSync(path.join(userDataPath, 'yomitan-dictionary-integrity.json'), 'utf8'),
),
{ lastKnownNonEmptyCount: 3 },
);
const statePath = path.join(userDataPath, 'yomitan-dictionary-integrity.json');
const unchangedTimestamp = new Date('2000-01-01T00:00:00.000Z');
fs.utimesSync(statePath, unchangedTimestamp, unchangedTimestamp);
assert.deepEqual(observeYomitanDictionaryCount(userDataPath, 3), {
safe: true,
previousCount: 3,
});
assert.equal(fs.statSync(statePath).mtimeMs, unchangedTimestamp.getTime());
assert.deepEqual(JSON.parse(fs.readFileSync(statePath, 'utf8')), { lastKnownNonEmptyCount: 3 });
assert.deepEqual(fs.readdirSync(userDataPath), ['yomitan-dictionary-integrity.json']);
});
});
@@ -114,11 +117,17 @@ test('dictionary integrity blocks automatic mutation after a non-empty profile b
test('dictionary integrity fails closed when its state is malformed', () => {
withTempDir((userDataPath) => {
fs.writeFileSync(path.join(userDataPath, 'yomitan-dictionary-integrity.json'), '{}', 'utf8');
const statePath = path.join(userDataPath, 'yomitan-dictionary-integrity.json');
fs.writeFileSync(statePath, '{}', 'utf8');
assert.throws(
() => assertYomitanDictionaryMutationSafe(userDataPath, 2),
/could not verify Yomitan dictionary storage/,
(error: unknown) => {
assert.ok(error instanceof Error);
assert.match(error.message, /could not verify Yomitan dictionary storage/);
assert.equal(error.message.includes(statePath), true);
return true;
},
);
});
});
@@ -70,7 +70,7 @@ export function observeYomitanDictionaryCount(
return {
safe: false,
previousCount: null,
message: `SubMiner could not verify Yomitan dictionary storage: ${(error as Error).message}`,
message: `SubMiner could not verify Yomitan dictionary storage at ${statePath}: ${(error as Error).message}`,
};
}
@@ -86,7 +86,7 @@ export function observeYomitanDictionaryCount(
};
}
if (normalizedCount > 0) {
if (normalizedCount > 0 && normalizedCount !== state?.lastKnownNonEmptyCount) {
try {
writeState(statePath, { lastKnownNonEmptyCount: normalizedCount });
} catch (error) {