Published source
Download source ZIP
CH-J Server Manager
Browse directories and files for a specific application release.
Source is provided under the CH-J Proprietary Software License 1.14. Its availability does not change the license terms or grant additional rights.
1
"use strict";3
const test = require("node:test");4
const assert = require("node:assert/strict");5
const fs = require("node:fs");6
const os = require("node:os");7
const path = require("node:path");8
const { VaultStore, validatePassword } = require("../src/main/security/vaultStore");10
test("vault password accepts 4 to 64 characters", () => {11
assert.equal(validatePassword("1234"), "1234");12
assert.equal(validatePassword(" "), " ");13
assert.equal(validatePassword("🔐".repeat(64)), "🔐".repeat(64));14
assert.throws(() => validatePassword("123"), /4 to 64/);15
assert.throws(() => validatePassword("x".repeat(65)), /4 to 64/);16
});18
test("vault preserves and unlocks a four-space password", async (t) => {19
const root = fs.mkdtempSync(path.join(os.tmpdir(), "chj-vault-spaces-"));20
t.after(() => fs.rmSync(root, { recursive: true, force: true }));21
const vault = new VaultStore(root);23
await vault.create(" ");24
assert.equal(vault.lock().unlocked, false);25
assert.equal((await vault.unlock(" ")).unlocked, true);26
});28
test("vault encrypts data and only unlocks with the correct password", async (t) => {29
const root = fs.mkdtempSync(path.join(os.tmpdir(), "chj-vault-"));30
t.after(() => fs.rmSync(root, { recursive: true, force: true }));31
const vault = new VaultStore(root);33
assert.equal(vault.status().needsSetup, true);34
const created = await vault.create("correct horse battery staple");35
assert.deepEqual({ initialized: created.initialized, needsSetup: created.needsSetup, unlocked: created.unlocked }, {36
initialized: true, needsSetup: false, unlocked: true37
});38
vault.update((data) => data.profiles.push({ id: "secret-profile", label: "Hidden server" }));40
const encrypted = fs.readFileSync(path.join(root, "vault", "core-v1.data.json"), "utf8");41
assert.doesNotMatch(encrypted, /Hidden server|secret-profile/);42
assert.equal(vault.lock().unlocked, false);43
await assert.rejects(() => vault.unlock("wrong password"), { code: "VAULT_UNLOCK_FAILED" });44
assert.equal(vault.status().unlocked, false);45
await vault.unlock("correct horse battery staple");46
assert.equal(vault.getData().profiles[0].label, "Hidden server");47
});49
test("vault refuses to overwrite an incomplete vault", async (t) => {50
const root = fs.mkdtempSync(path.join(os.tmpdir(), "chj-vault-"));51
t.after(() => fs.rmSync(root, { recursive: true, force: true }));52
fs.mkdirSync(path.join(root, "vault"), { recursive: true });53
fs.writeFileSync(path.join(root, "vault", "core-v1.meta.json"), "{}");54
const vault = new VaultStore(root);55
assert.equal(vault.status().damaged, true);56
await assert.rejects(() => vault.create("correct horse battery staple"), /incomplete/);57
});59
test("vault reset requires confirmation, deletes protected data and returns to setup", async (t) => {60
const root = fs.mkdtempSync(path.join(os.tmpdir(), "chj-vault-"));61
t.after(() => fs.rmSync(root, { recursive: true, force: true }));62
const vault = new VaultStore(root);63
await vault.create("1234");64
vault.update((data) => data.profiles.push({ id: "to-delete", label: "Deleted" }));66
assert.throws(() => vault.reset("wrong"), { code: "VAULT_RESET_CONFIRMATION_REQUIRED" });67
assert.equal(vault.status().initialized, true);68
assert.deepEqual(vault.reset("SMAZAT"), { initialized: false, needsSetup: true, damaged: false, unlocked: false });69
assert.equal(fs.existsSync(path.join(root, "vault")), false);71
await vault.create("new-password");72
assert.deepEqual(vault.getData().profiles, []);73
});SHA-256: 66b46ab48bee66e70ff1119a22b5bd06c438584dcb7ca7488f6c5e6ecedbd655
Archive SHA-256: 5ac91caf4fa32a6fdb114f2430deed486fbe7489d5eea343d1f034169fafb5e0