chore: prettier format all files, brotli, Sentry release tagging, CI gates

Prettier: auto-formatted 103 files to fix baseline. Prettier check in CI
  is now a hard gate (removed continue-on-error).

Brotli: installed libnginx-mod-http-brotli-filter/static. Enabled in nginx
  with brotli_static on for pre-compressed assets and comp_level 6.

Sentry releases: deploy script now exports VITE_APP_VERSION=<git-short-sha>
  before building so each Sentry release maps to an exact commit.
  CI also passes github.sha as VITE_APP_VERSION.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lotus Bot
2026-05-21 20:49:33 -04:00
parent 408fc1b846
commit 42b9cc2b64
105 changed files with 2749 additions and 1850 deletions
+37 -46
View File
@@ -37,7 +37,7 @@ async function deriveKeys(salt, iterations, password) {
new TextEncoder().encode(password),
{ name: 'PBKDF2' },
false,
['deriveBits'],
['deriveBits']
);
} catch (e) {
throw friendlyError(`subtleCrypto.importKey failed: ${e}`, cryptoFailMsg());
@@ -53,40 +53,38 @@ async function deriveKeys(salt, iterations, password) {
hash: 'SHA-512',
},
key,
512,
512
);
} catch (e) {
throw friendlyError(`subtleCrypto.deriveBits failed: ${e}`, cryptoFailMsg());
}
const now = new Date();
console.log(`E2e import/export: deriveKeys took ${(now - start)}ms`);
console.log(`E2e import/export: deriveKeys took ${now - start}ms`);
const aesKey = keybits.slice(0, 32);
const hmacKey = keybits.slice(32);
const aesProm = subtleCrypto.importKey(
'raw',
aesKey,
{ name: 'AES-CTR' },
false,
['encrypt', 'decrypt'],
).catch((e) => {
throw friendlyError(`subtleCrypto.importKey failed for AES key: ${e}`, cryptoFailMsg());
});
const aesProm = subtleCrypto
.importKey('raw', aesKey, { name: 'AES-CTR' }, false, ['encrypt', 'decrypt'])
.catch((e) => {
throw friendlyError(`subtleCrypto.importKey failed for AES key: ${e}`, cryptoFailMsg());
});
const hmacProm = subtleCrypto.importKey(
'raw',
hmacKey,
{
name: 'HMAC',
hash: { name: 'SHA-256' },
},
false,
['sign', 'verify'],
).catch((e) => {
throw friendlyError(`subtleCrypto.importKey failed for HMAC key: ${e}`, cryptoFailMsg());
});
const hmacProm = subtleCrypto
.importKey(
'raw',
hmacKey,
{
name: 'HMAC',
hash: { name: 'SHA-256' },
},
false,
['sign', 'verify']
)
.catch((e) => {
throw friendlyError(`subtleCrypto.importKey failed for HMAC key: ${e}`, cryptoFailMsg());
});
// eslint-disable-next-line no-return-await
return await Promise.all([aesProm, hmacProm]);
@@ -177,7 +175,6 @@ function unpackMegolmKeyFile(data) {
return decodeBase64(fileStr.slice(dataStart, dataEnd));
}
/**
* ascii-armour a megolm key file
*
@@ -189,20 +186,20 @@ function unpackMegolmKeyFile(data) {
function packMegolmKeyFile(data) {
// we split into lines before base64ing, because encodeBase64 doesn't deal
// terribly well with large arrays.
const LINE_LENGTH = ((72 * 4) / 3);
const LINE_LENGTH = (72 * 4) / 3;
const nLines = Math.ceil(data.length / LINE_LENGTH);
const lines = new Array(nLines + 3);
lines[0] = HEADER_LINE;
let o = 0;
let i;
for (i = 1; i <= nLines; i += 1) {
lines[i] = encodeBase64(data.subarray(o, o+LINE_LENGTH));
lines[i] = encodeBase64(data.subarray(o, o + LINE_LENGTH));
o += LINE_LENGTH;
}
lines[i] = TRAILER_LINE;
i += 1;
lines[i] = '';
return (new TextEncoder().encode(lines.join('\n'))).buffer;
return new TextEncoder().encode(lines.join('\n')).buffer;
}
export async function decryptMegolmKeyFile(data, password) {
@@ -225,7 +222,7 @@ export async function decryptMegolmKeyFile(data, password) {
const salt = body.subarray(1, 1 + 16);
const iv = body.subarray(17, 17 + 16);
const iterations = body[33] << 24 | body[34] << 16 | body[35] << 8 | body[36];
const iterations = (body[33] << 24) | (body[34] << 16) | (body[35] << 8) | body[36];
const ciphertext = body.subarray(37, 37 + ciphertextLength);
const hmac = body.subarray(-32);
@@ -234,12 +231,7 @@ export async function decryptMegolmKeyFile(data, password) {
let isValid;
try {
isValid = await subtleCrypto.verify(
{ name: 'HMAC' },
hmacKey,
hmac,
toVerify,
);
isValid = await subtleCrypto.verify({ name: 'HMAC' }, hmacKey, hmac, toVerify);
} catch (e) {
throw friendlyError(`subtleCrypto.verify failed: ${e}`, cryptoFailMsg());
}
@@ -256,7 +248,7 @@ export async function decryptMegolmKeyFile(data, password) {
length: 64,
},
aesKey,
ciphertext,
ciphertext
);
} catch (e) {
throw friendlyError(`subtleCrypto.decrypt failed: ${e}`, cryptoFailMsg());
@@ -302,34 +294,33 @@ export async function encryptMegolmKeyFile(data, password, options) {
length: 64,
},
aesKey,
encodedData,
encodedData
);
} catch (e) {
throw friendlyError('subtleCrypto.encrypt failed: ' + e, cryptoFailMsg());
}
const cipherArray = new Uint8Array(ciphertext);
const bodyLength = (1+salt.length+iv.length+4+cipherArray.length+32);
const bodyLength = 1 + salt.length + iv.length + 4 + cipherArray.length + 32;
const resultBuffer = new Uint8Array(bodyLength);
let idx = 0;
resultBuffer[idx++] = 1; // version
resultBuffer.set(salt, idx); idx += salt.length;
resultBuffer.set(iv, idx); idx += iv.length;
resultBuffer.set(salt, idx);
idx += salt.length;
resultBuffer.set(iv, idx);
idx += iv.length;
resultBuffer[idx++] = kdfRounds >> 24;
resultBuffer[idx++] = (kdfRounds >> 16) & 0xff;
resultBuffer[idx++] = (kdfRounds >> 8) & 0xff;
resultBuffer[idx++] = kdfRounds & 0xff;
resultBuffer.set(cipherArray, idx); idx += cipherArray.length;
resultBuffer.set(cipherArray, idx);
idx += cipherArray.length;
const toSign = resultBuffer.subarray(0, idx);
let hmac;
try {
hmac = await subtleCrypto.sign(
{ name: 'HMAC' },
hmacKey,
toSign,
);
hmac = await subtleCrypto.sign({ name: 'HMAC' }, hmacKey, toSign);
} catch (e) {
throw friendlyError('subtleCrypto.sign failed: ' + e, cryptoFailMsg());
}