valija 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +49 -0
- package/dist/program.js +1527 -0
- package/dist/program.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/delivery/cli/program.ts","../src/delivery/container.ts","../src/shared/domain/result.ts","../src/context/domain/errors.ts","../src/context/domain/values/project-name.ts","../src/context/application/export-pack.ts","../src/context/application/get-context-pack.ts","../src/context/application/list-projects.ts","../src/context/domain/entities/context-item.ts","../src/context/domain/values/item-type.ts","../src/context/domain/values/tag.ts","../src/context/application/save-context.ts","../src/context/application/search-context.ts","../src/context/application/show-project.ts","../src/shared/infra/migrations/001-init.ts","../src/shared/infra/migrations.ts","../src/shared/infra/sqlite.ts","../src/vault/domain/errors.ts","../src/vault/infra/vault-header.ts","../src/context/infra/item-repo.ts","../src/context/infra/project-repo.ts","../src/context/infra/session-factory.ts","../src/shared/infra/vault-paths.ts","../src/vault/application/hex.ts","../src/vault/application/ports/crypto.ts","../src/vault/application/create-vault.ts","../src/vault/application/lock-vault.ts","../src/vault/application/unlock-vault.ts","../src/vault/application/vault-status.ts","../src/vault/infra/argon2.ts","../src/vault/infra/file-vault-store.ts","../src/vault/infra/keyring.ts","../src/delivery/mcp/server.ts","../src/delivery/version.ts","../src/delivery/cli/content-commands.ts","../src/delivery/cli/render.ts","../src/delivery/cli/doctor.ts","../src/delivery/cli/installer.ts","../src/vault/infra/recovery-kit.ts","../src/delivery/cli/prompt.ts","../src/delivery/cli/vault-commands.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport { buildContainer } from \"../container.js\";\nimport { runMcpServer } from \"../mcp/server.js\";\nimport { VERSION } from \"../version.js\";\nimport { exportCommand, projectsCommand, searchCommand, showCommand } from \"./content-commands.js\";\nimport { doctorCommand } from \"./doctor.js\";\nimport { CLIENTS, type ClientId, installIntoClient, manualInstructions } from \"./installer.js\";\nimport { initCommand, lockCommand, statusCommand, unlockCommand } from \"./vault-commands.js\";\n\nconst program = new Command();\nconst container = buildContainer();\n\nprogram\n .name(\"valija\")\n .description(\"Encrypted context vault for developers who use several AI tools.\")\n .version(VERSION);\n\nprogram\n .command(\"init\")\n .description(\"Create the encrypted vault (passphrase + recovery kit).\")\n .action(() => initCommand(container));\n\nprogram\n .command(\"unlock\")\n .description(\"Unlock the vault for this session (key goes to the OS keychain).\")\n .option(\"--recovery-key <hex>\", \"unlock with the raw key from your recovery kit\")\n .action((options: { recoveryKey?: string }) => unlockCommand(container, options));\n\nprogram\n .command(\"lock\")\n .description(\"Lock the vault (remove the key from the OS keychain).\")\n .action(() => lockCommand(container));\n\nprogram\n .command(\"status\")\n .description(\"Show vault location and lock state.\")\n .action(() => statusCommand(container));\n\nprogram\n .command(\"projects\")\n .description(\"List projects with item counts and last activity.\")\n .action(() => projectsCommand(container));\n\nprogram\n .command(\"show\")\n .description(\"Print the items of a project.\")\n .argument(\"<project>\", \"project slug\")\n .option(\"--type <type>\", \"filter by type (decision|progress|preference|fact|handoff)\")\n .action((project: string, options: { type?: string }) =>\n showCommand(container, project, options),\n );\n\nprogram\n .command(\"search\")\n .description(\"Full-text search across saved context.\")\n .argument(\"<query>\", \"search terms\")\n .option(\"-p, --project <project>\", \"limit to one project\")\n .action((query: string, options: { project?: string }) =>\n searchCommand(container, query, options),\n );\n\nprogram\n .command(\"export\")\n .description(\"Export a project's context pack (markdown by default).\")\n .argument(\"<project>\", \"project slug\")\n .option(\"--json\", \"export as JSON instead of markdown\")\n .option(\"-o, --output <file>\", \"write to a file instead of stdout\")\n .action((project: string, options: { json?: boolean; output?: string }) =>\n exportCommand(container, project, options),\n );\n\nprogram\n .command(\"install\")\n .description(\"Wire the valija MCP server into an AI tool's config.\")\n .argument(\"<client>\", `one of: ${CLIENTS.join(\", \")}`)\n .action((client: string) => {\n if (!(CLIENTS as readonly string[]).includes(client)) {\n console.error(`error: unknown client \"${client}\". Use one of: ${CLIENTS.join(\", \")}`);\n process.exit(1);\n }\n try {\n const result = installIntoClient(client as ClientId);\n console.log(`valija MCP server added to ${result.configPath}`);\n if (result.backupPath) console.log(`Backup of the previous config: ${result.backupPath}`);\n console.log(`Restart ${client} to pick it up.`);\n } catch (e) {\n console.error(`Could not update the config automatically: ${(e as Error).message}\\n`);\n console.error(manualInstructions(client as ClientId));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"mcp\")\n .description(\"Run the MCP server on stdio (used by AI tools, not by humans).\")\n .action(async () => {\n await runMcpServer(container);\n });\n\nprogram\n .command(\"doctor\")\n .description(\"Check environment, vault, keychain, and client configs.\")\n .action(() => doctorCommand(container));\n\nprogram.parseAsync().catch((error: unknown) => {\n console.error(`error: ${(error as Error).message}`);\n process.exit(1);\n});\n","import { ulid } from \"ulid\";\nimport { ExportPack } from \"../context/application/export-pack.js\";\nimport { GetContextPack } from \"../context/application/get-context-pack.js\";\nimport { ListProjects } from \"../context/application/list-projects.js\";\nimport { SaveContext } from \"../context/application/save-context.js\";\nimport { SearchContext } from \"../context/application/search-context.js\";\nimport { ShowProject } from \"../context/application/show-project.js\";\nimport { SqliteVaultSessionFactory } from \"../context/infra/session-factory.js\";\nimport type { Clock, IdGenerator } from \"../shared/application/ports/clock.js\";\nimport { resolveVaultPaths, type VaultPaths } from \"../shared/infra/vault-paths.js\";\nimport { CreateVault } from \"../vault/application/create-vault.js\";\nimport { LockVault } from \"../vault/application/lock-vault.js\";\nimport { UnlockVault } from \"../vault/application/unlock-vault.js\";\nimport { VaultStatus } from \"../vault/application/vault-status.js\";\nimport { Argon2VaultCrypto } from \"../vault/infra/argon2.js\";\nimport { FileVaultStore } from \"../vault/infra/file-vault-store.js\";\nimport { OsKeychain } from \"../vault/infra/keyring.js\";\n\nconst systemClock: Clock = { now: () => new Date() };\nconst ulidIds: IdGenerator = { next: () => ulid() };\n\nexport interface Container {\n paths: VaultPaths;\n createVault: CreateVault;\n unlockVault: UnlockVault;\n lockVault: LockVault;\n vaultStatus: VaultStatus;\n saveContext: SaveContext;\n listProjects: ListProjects;\n searchContext: SearchContext;\n getContextPack: GetContextPack;\n exportPack: ExportPack;\n showProject: ShowProject;\n}\n\nexport function buildContainer(): Container {\n const paths = resolveVaultPaths();\n const store = new FileVaultStore(paths);\n const crypto = new Argon2VaultCrypto();\n const keychain = new OsKeychain();\n const sessions = new SqliteVaultSessionFactory(paths, keychain);\n const getContextPack = new GetContextPack(sessions, systemClock);\n return {\n paths,\n createVault: new CreateVault(store, crypto, keychain, systemClock, ulidIds),\n unlockVault: new UnlockVault(store, crypto, keychain),\n lockVault: new LockVault(store, keychain),\n vaultStatus: new VaultStatus(store, keychain),\n saveContext: new SaveContext(sessions, systemClock, ulidIds),\n listProjects: new ListProjects(sessions),\n searchContext: new SearchContext(sessions),\n getContextPack,\n exportPack: new ExportPack(sessions, getContextPack),\n showProject: new ShowProject(sessions),\n };\n}\n","export type Result<T, E = DomainError> = { ok: true; value: T } | { ok: false; error: E };\n\nexport const ok = <T>(value: T): Result<T, never> => ({ ok: true, value });\nexport const err = <E>(error: E): Result<never, E> => ({ ok: false, error });\n\n/**\n * Base error shared by every module. Each bounded context narrows `code`\n * through its own constructor (vaultErr / contextErr).\n */\nexport class DomainError extends Error {\n constructor(\n readonly code: string,\n message: string,\n ) {\n super(message);\n this.name = \"DomainError\";\n }\n}\n","import { DomainError, err, type Result } from \"../../shared/domain/result.js\";\n\n/** Error vocabulary of the CONTEXT bounded context (content language). */\nexport type ContextErrorCode =\n | \"INVALID_PROJECT_NAME\"\n | \"INVALID_ITEM_TYPE\"\n | \"INVALID_TAG\"\n | \"CONTENT_TOO_LARGE\"\n | \"CONTENT_EMPTY\"\n | \"TOO_MANY_TAGS\"\n | \"PROJECT_NOT_FOUND\"\n | \"ITEM_NOT_FOUND\";\n\nexport const contextErr = (code: ContextErrorCode, message: string): Result<never, DomainError> =>\n err(new DomainError(code, message));\n","import { type DomainError, ok, type Result } from \"../../../shared/domain/result.js\";\nimport { contextErr } from \"../errors.js\";\n\nconst PATTERN = /^[a-z0-9][a-z0-9-]{0,63}$/;\n\n/** Unique project slug: 1-64 chars, lowercase letters, digits, hyphens (not leading). */\nexport type ProjectName = string & { readonly __brand: \"ProjectName\" };\n\nexport function parseProjectName(raw: string): Result<ProjectName, DomainError> {\n const normalized = raw.trim().toLowerCase();\n if (!PATTERN.test(normalized)) {\n return contextErr(\n \"INVALID_PROJECT_NAME\",\n `Project name must be 1-64 chars of [a-z0-9-], starting with a letter or digit. Got: \"${raw}\"`,\n );\n }\n return ok(normalized as ProjectName);\n}\n","import { type DomainError, ok, type Result } from \"../../shared/domain/result.js\";\nimport { contextErr } from \"../domain/errors.js\";\nimport { parseProjectName } from \"../domain/values/project-name.js\";\nimport type { GetContextPack } from \"./get-context-pack.js\";\nimport type { VaultSessionFactory } from \"./ports/vault-session.js\";\n\nexport type ExportFormat = \"md\" | \"json\";\n\nexport class ExportPack {\n constructor(\n private readonly sessions: VaultSessionFactory,\n private readonly getContextPack: GetContextPack,\n ) {}\n\n execute(project: string, format: ExportFormat): Result<string, DomainError> {\n if (format === \"md\") {\n // Export is the everything-escape-hatch: no budget.\n const pack = this.getContextPack.execute({ project, budgetTokens: Number.MAX_SAFE_INTEGER });\n return pack.ok ? ok(pack.value.markdown) : pack;\n }\n\n const name = parseProjectName(project);\n if (!name.ok) return name;\n const session = this.sessions.open();\n if (!session.ok) return session;\n try {\n const found = session.value.projects.findByName(name.value);\n if (found === null) {\n return contextErr(\"PROJECT_NOT_FOUND\", `No project named \"${name.value}\".`);\n }\n const items = session.value.items.findByProject(found.id).map((item) => ({\n id: item.id,\n type: item.type,\n content: item.content,\n tags: item.tags,\n pinned: item.pinned,\n source: item.source ?? null,\n createdAt: item.createdAt.toISOString(),\n }));\n return ok(JSON.stringify({ project: name.value, items }, null, 2));\n } finally {\n session.value.close();\n }\n }\n}\n","import type { Clock } from \"../../shared/application/ports/clock.js\";\nimport { type DomainError, ok, type Result } from \"../../shared/domain/result.js\";\nimport type { ContextItem } from \"../domain/entities/context-item.js\";\nimport { contextErr } from \"../domain/errors.js\";\nimport { parseProjectName } from \"../domain/values/project-name.js\";\nimport type { VaultSessionFactory } from \"./ports/vault-session.js\";\n\nexport const DEFAULT_BUDGET_TOKENS = 4000;\n\n/** Cheap token estimate: ~4 chars per token. Good enough for a budget, no tokenizer dep. */\nexport const estimateTokens = (text: string): number => Math.ceil(text.length / 4);\n\nconst SECTION_ORDER = [\"decision\", \"preference\", \"progress\", \"fact\"] as const;\n\nconst SECTION_LABELS: Record<(typeof SECTION_ORDER)[number], string> = {\n decision: \"Decisions\",\n preference: \"Preferences\",\n progress: \"Progress\",\n fact: \"Facts\",\n};\n\nexport interface GetContextPackInput {\n project: string;\n budgetTokens?: number;\n}\n\nexport interface ContextPack {\n markdown: string;\n includedCount: number;\n totalCount: number;\n estimatedTokens: number;\n}\n\nconst renderItem = (item: ContextItem): string => {\n const date = item.createdAt.toISOString().slice(0, 10);\n const tags = item.tags.length > 0 ? ` · ${item.tags.map((t) => `#${t}`).join(\" \")}` : \"\";\n return `### ${item.type} · ${date}${tags}\\n\\n${item.content}\\n`;\n};\n\nexport class GetContextPack {\n constructor(\n private readonly sessions: VaultSessionFactory,\n private readonly clock: Clock,\n ) {}\n\n execute(input: GetContextPackInput): Result<ContextPack, DomainError> {\n const name = parseProjectName(input.project);\n if (!name.ok) return name;\n const budget = input.budgetTokens ?? DEFAULT_BUDGET_TOKENS;\n\n const session = this.sessions.open();\n if (!session.ok) return session;\n try {\n const project = session.value.projects.findByName(name.value);\n if (project === null) {\n return contextErr(\"PROJECT_NOT_FOUND\", `No project named \"${name.value}\".`);\n }\n // Newest first, archived excluded — repository contract.\n const all = session.value.items.findByProject(project.id);\n const included = new Set<string>();\n const parts: string[] = [];\n let used = 0;\n\n const header =\n `# Context pack: ${name.value}\\n\\n` +\n `> ${all.length} items in vault · generated ${this.clock.now().toISOString()}\\n`;\n used += estimateTokens(header);\n\n // 1. Pinned: all included, newest first; if they alone bust the budget,\n // the oldest pinned are cut first — but never the newest one.\n const pinned = all.filter((i) => i.pinned);\n const pinnedKept: ContextItem[] = [];\n for (const item of pinned) {\n const cost = estimateTokens(renderItem(item));\n if (pinnedKept.length > 0 && used + cost > budget) break;\n pinnedKept.push(item);\n used += cost;\n }\n if (pinnedKept.length > 0) {\n parts.push(\"\\n## Pinned\\n\");\n for (const item of pinnedKept) {\n parts.push(renderItem(item));\n included.add(item.id);\n }\n }\n\n // 2. Latest handoff, if it fits.\n const handoff = all.find((i) => i.type === \"handoff\" && !included.has(i.id));\n if (handoff) {\n const rendered = renderItem(handoff);\n const cost = estimateTokens(rendered);\n if (used + cost <= budget) {\n parts.push(\"\\n## Latest handoff\\n\", rendered);\n included.add(handoff.id);\n used += cost;\n }\n }\n\n // 3. Recent items by type, in section order, newest first, until the budget is reached.\n for (const type of SECTION_ORDER) {\n const items = all.filter((i) => i.type === type && !included.has(i.id));\n let sectionOpened = false;\n for (const item of items) {\n const rendered = renderItem(item);\n const sectionHeader = sectionOpened ? \"\" : `\\n## ${SECTION_LABELS[type]}\\n`;\n const cost = estimateTokens(sectionHeader + rendered);\n if (used + cost > budget) break;\n if (!sectionOpened) {\n parts.push(sectionHeader);\n sectionOpened = true;\n }\n parts.push(rendered);\n included.add(item.id);\n used += cost;\n }\n }\n\n const markdown = header + parts.join(\"\\n\");\n return ok({\n markdown,\n includedCount: included.size,\n totalCount: all.length,\n estimatedTokens: estimateTokens(markdown),\n });\n } finally {\n session.value.close();\n }\n }\n}\n","import { type DomainError, ok, type Result } from \"../../shared/domain/result.js\";\nimport type { VaultSessionFactory } from \"./ports/vault-session.js\";\n\nexport interface ProjectListEntry {\n name: string;\n description?: string;\n itemCount: number;\n lastActivityAt: string | null;\n}\n\nexport class ListProjects {\n constructor(private readonly sessions: VaultSessionFactory) {}\n\n execute(): Result<ProjectListEntry[], DomainError> {\n const session = this.sessions.open();\n if (!session.ok) return session;\n try {\n const entries = session.value.projects.list().map((summary) => ({\n name: summary.project.name as string,\n ...(summary.project.description === undefined\n ? {}\n : { description: summary.project.description }),\n itemCount: summary.itemCount,\n lastActivityAt: summary.lastActivityAt?.toISOString() ?? null,\n }));\n return ok(entries);\n } finally {\n session.value.close();\n }\n }\n}\n","import { type DomainError, ok, type Result } from \"../../../shared/domain/result.js\";\nimport { contextErr } from \"../errors.js\";\nimport type { ItemType } from \"../values/item-type.js\";\nimport type { Tag } from \"../values/tag.js\";\n\nexport const MAX_CONTENT_BYTES = 32 * 1024;\n\nexport interface ContextItem {\n readonly id: string;\n readonly projectId: string;\n readonly type: ItemType;\n readonly content: string;\n readonly tags: readonly Tag[];\n readonly pinned: boolean;\n readonly source?: string;\n readonly archived: boolean;\n readonly createdAt: Date;\n readonly updatedAt: Date;\n}\n\nexport function validateContent(content: string): Result<string, DomainError> {\n const trimmed = content.trim();\n if (trimmed.length === 0) {\n return contextErr(\"CONTENT_EMPTY\", \"Content must not be empty.\");\n }\n const bytes = new TextEncoder().encode(trimmed).length;\n if (bytes > MAX_CONTENT_BYTES) {\n return contextErr(\n \"CONTENT_TOO_LARGE\",\n `Content is ${bytes} bytes; the maximum is ${MAX_CONTENT_BYTES} (32 KB). Distill it.`,\n );\n }\n return ok(trimmed);\n}\n","import { type DomainError, ok, type Result } from \"../../../shared/domain/result.js\";\nimport { contextErr } from \"../errors.js\";\n\nexport const ITEM_TYPES = [\"decision\", \"progress\", \"preference\", \"fact\", \"handoff\"] as const;\n\nexport type ItemType = (typeof ITEM_TYPES)[number];\n\nexport function parseItemType(raw: string): Result<ItemType, DomainError> {\n if ((ITEM_TYPES as readonly string[]).includes(raw)) {\n return ok(raw as ItemType);\n }\n return contextErr(\n \"INVALID_ITEM_TYPE\",\n `Item type must be one of ${ITEM_TYPES.join(\", \")}. Got: \"${raw}\"`,\n );\n}\n","import { type DomainError, ok, type Result } from \"../../../shared/domain/result.js\";\nimport { contextErr } from \"../errors.js\";\n\nconst PATTERN = /^[a-z0-9][a-z0-9-]{0,31}$/;\n\nexport const MAX_TAGS = 10;\n\n/** Lowercase tag: 1-32 chars of [a-z0-9-]. */\nexport type Tag = string & { readonly __brand: \"Tag\" };\n\nexport function parseTag(raw: string): Result<Tag, DomainError> {\n const normalized = raw.trim().toLowerCase();\n if (!PATTERN.test(normalized)) {\n return contextErr(\"INVALID_TAG\", `Tag must be 1-32 chars of [a-z0-9-]. Got: \"${raw}\"`);\n }\n return ok(normalized as Tag);\n}\n\nexport function parseTags(raw: readonly string[]): Result<Tag[], DomainError> {\n if (raw.length > MAX_TAGS) {\n return contextErr(\"TOO_MANY_TAGS\", `At most ${MAX_TAGS} tags allowed. Got ${raw.length}.`);\n }\n const tags: Tag[] = [];\n for (const r of raw) {\n const parsed = parseTag(r);\n if (!parsed.ok) return parsed;\n if (!tags.includes(parsed.value)) tags.push(parsed.value);\n }\n return ok(tags);\n}\n","import type { Clock, IdGenerator } from \"../../shared/application/ports/clock.js\";\nimport { type DomainError, ok, type Result } from \"../../shared/domain/result.js\";\nimport { validateContent } from \"../domain/entities/context-item.js\";\nimport type { Project } from \"../domain/entities/project.js\";\nimport { type ItemType, parseItemType } from \"../domain/values/item-type.js\";\nimport { parseProjectName } from \"../domain/values/project-name.js\";\nimport { parseTags } from \"../domain/values/tag.js\";\nimport type { VaultSessionFactory } from \"./ports/vault-session.js\";\n\nexport interface SaveContextInput {\n project: string;\n content: string;\n type?: string;\n tags?: string[];\n pinned?: boolean;\n source?: string;\n}\n\nexport interface SaveContextOutput {\n itemId: string;\n project: string;\n type: ItemType;\n projectCreated: boolean;\n}\n\nexport class SaveContext {\n constructor(\n private readonly sessions: VaultSessionFactory,\n private readonly clock: Clock,\n private readonly idGen: IdGenerator,\n ) {}\n\n execute(input: SaveContextInput): Result<SaveContextOutput, DomainError> {\n const name = parseProjectName(input.project);\n if (!name.ok) return name;\n const type = parseItemType(input.type ?? \"fact\");\n if (!type.ok) return type;\n const tags = parseTags(input.tags ?? []);\n if (!tags.ok) return tags;\n const content = validateContent(input.content);\n if (!content.ok) return content;\n\n const session = this.sessions.open();\n if (!session.ok) return session;\n try {\n const now = this.clock.now();\n let project = session.value.projects.findByName(name.value);\n const projectCreated = project === null;\n if (project === null) {\n project = {\n id: this.idGen.next(),\n name: name.value,\n createdAt: now,\n updatedAt: now,\n } satisfies Project;\n session.value.projects.save(project);\n }\n const itemId = this.idGen.next();\n session.value.items.save({\n id: itemId,\n projectId: project.id,\n type: type.value,\n content: content.value,\n tags: tags.value,\n pinned: input.pinned ?? false,\n ...(input.source === undefined ? {} : { source: input.source }),\n archived: false,\n createdAt: now,\n updatedAt: now,\n });\n return ok({ itemId, project: name.value, type: type.value, projectCreated });\n } finally {\n session.value.close();\n }\n }\n}\n","import { type DomainError, ok, type Result } from \"../../shared/domain/result.js\";\nimport { contextErr } from \"../domain/errors.js\";\nimport type { ItemType } from \"../domain/values/item-type.js\";\nimport { parseProjectName } from \"../domain/values/project-name.js\";\nimport type { VaultSessionFactory } from \"./ports/vault-session.js\";\n\nexport interface SearchContextInput {\n query: string;\n project?: string;\n limit?: number;\n}\n\nexport interface SearchHit {\n id: string;\n project: string;\n type: ItemType;\n content: string;\n tags: string[];\n pinned: boolean;\n createdAt: string;\n}\n\nexport class SearchContext {\n constructor(private readonly sessions: VaultSessionFactory) {}\n\n execute(input: SearchContextInput): Result<SearchHit[], DomainError> {\n const session = this.sessions.open();\n if (!session.ok) return session;\n try {\n let projectId: string | undefined;\n if (input.project !== undefined) {\n const name = parseProjectName(input.project);\n if (!name.ok) return name;\n const project = session.value.projects.findByName(name.value);\n if (project === null) {\n return contextErr(\"PROJECT_NOT_FOUND\", `No project named \"${name.value}\".`);\n }\n projectId = project.id;\n }\n const limit = Math.min(Math.max(input.limit ?? 20, 1), 100);\n const hits = session.value.items.search(input.query, projectId, limit).map((result) => ({\n id: result.item.id,\n project: result.projectName as string,\n type: result.item.type,\n content: result.item.content,\n tags: [...result.item.tags],\n pinned: result.item.pinned,\n createdAt: result.item.createdAt.toISOString(),\n }));\n return ok(hits);\n } finally {\n session.value.close();\n }\n }\n}\n","import { type DomainError, ok, type Result } from \"../../shared/domain/result.js\";\nimport { contextErr } from \"../domain/errors.js\";\nimport { type ItemType, parseItemType } from \"../domain/values/item-type.js\";\nimport { parseProjectName } from \"../domain/values/project-name.js\";\nimport type { VaultSessionFactory } from \"./ports/vault-session.js\";\nimport type { SearchHit } from \"./search-context.js\";\n\nexport class ShowProject {\n constructor(private readonly sessions: VaultSessionFactory) {}\n\n execute(project: string, type?: string): Result<SearchHit[], DomainError> {\n const name = parseProjectName(project);\n if (!name.ok) return name;\n let typeValue: ItemType | undefined;\n if (type !== undefined) {\n const parsed = parseItemType(type);\n if (!parsed.ok) return parsed;\n typeValue = parsed.value;\n }\n const session = this.sessions.open();\n if (!session.ok) return session;\n try {\n const found = session.value.projects.findByName(name.value);\n if (found === null) {\n return contextErr(\"PROJECT_NOT_FOUND\", `No project named \"${name.value}\".`);\n }\n const items = session.value.items.findByProject(\n found.id,\n typeValue === undefined ? {} : { type: typeValue },\n );\n return ok(\n items.map((item) => ({\n id: item.id,\n project: name.value as string,\n type: item.type,\n content: item.content,\n tags: [...item.tags],\n pinned: item.pinned,\n createdAt: item.createdAt.toISOString(),\n })),\n );\n } finally {\n session.value.close();\n }\n }\n}\n","export const MIGRATION_001 = `\nCREATE TABLE projects (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL UNIQUE,\n description TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n);\n\nCREATE TABLE context_items (\n id TEXT PRIMARY KEY,\n project_id TEXT NOT NULL REFERENCES projects(id),\n type TEXT NOT NULL CHECK (type IN ('decision','progress','preference','fact','handoff')),\n content TEXT NOT NULL,\n tags TEXT NOT NULL DEFAULT '[]',\n pinned INTEGER NOT NULL DEFAULT 0,\n source TEXT,\n archived INTEGER NOT NULL DEFAULT 0,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n);\n\nCREATE INDEX idx_items_project ON context_items(project_id, created_at DESC);\n\nCREATE VIRTUAL TABLE context_items_fts USING fts5(\n content,\n tags,\n content='context_items',\n content_rowid='rowid'\n);\n\nCREATE TRIGGER items_ai AFTER INSERT ON context_items BEGIN\n INSERT INTO context_items_fts(rowid, content, tags)\n VALUES (new.rowid, new.content, new.tags);\nEND;\n\nCREATE TRIGGER items_ad AFTER DELETE ON context_items BEGIN\n INSERT INTO context_items_fts(context_items_fts, rowid, content, tags)\n VALUES ('delete', old.rowid, old.content, old.tags);\nEND;\n\nCREATE TRIGGER items_au AFTER UPDATE ON context_items BEGIN\n INSERT INTO context_items_fts(context_items_fts, rowid, content, tags)\n VALUES ('delete', old.rowid, old.content, old.tags);\n INSERT INTO context_items_fts(rowid, content, tags)\n VALUES (new.rowid, new.content, new.tags);\nEND;\n`;\n","import type { Database } from \"better-sqlite3-multiple-ciphers\";\nimport { MIGRATION_001 } from \"./migrations/001-init.js\";\n\nconst MIGRATIONS: ReadonlyArray<{ version: number; sql: string }> = [\n { version: 1, sql: MIGRATION_001 },\n];\n\nexport function migrate(db: Database): void {\n db.exec(\"CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)\");\n const row = db.prepare(\"SELECT value FROM meta WHERE key = 'schema_version'\").get() as\n | { value: string }\n | undefined;\n const current = row ? Number(row.value) : 0;\n for (const migration of MIGRATIONS) {\n if (migration.version <= current) continue;\n db.transaction(() => {\n db.exec(migration.sql);\n db.prepare(\n \"INSERT INTO meta (key, value) VALUES ('schema_version', ?) \" +\n \"ON CONFLICT(key) DO UPDATE SET value = excluded.value\",\n ).run(String(migration.version));\n })();\n }\n}\n\nexport function schemaVersion(db: Database): number {\n const row = db.prepare(\"SELECT value FROM meta WHERE key = 'schema_version'\").get() as\n | { value: string }\n | undefined;\n return row ? Number(row.value) : 0;\n}\n","import { mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport SqliteDatabase, { type Database } from \"better-sqlite3-multiple-ciphers\";\n\n/**\n * Open (or create) the SQLCipher vault database with a raw 32-byte key.\n * Throws SqliteError (SQLITE_NOTADB) if the key is wrong for an existing file.\n *\n * The single physical database is the shared persistence kernel: the vault\n * module opens it to verify keys, the context module opens it for repositories.\n */\nexport function openVaultDb(dbPath: string, keyHex: string): Database {\n if (!/^[0-9a-f]{64}$/i.test(keyHex)) {\n throw new Error(\"Vault key must be 64 hex characters (32 bytes).\");\n }\n mkdirSync(dirname(dbPath), { recursive: true });\n const db = new SqliteDatabase(dbPath);\n try {\n db.pragma(\"cipher='sqlcipher'\");\n db.pragma(`key=\"x'${keyHex}'\"`);\n // Touching the schema forces key verification: wrong key -> SQLITE_NOTADB.\n db.prepare(\"SELECT count(*) FROM sqlite_master\").get();\n db.pragma(\"journal_mode = WAL\");\n db.pragma(\"foreign_keys = ON\");\n return db;\n } catch (error) {\n db.close();\n throw error;\n }\n}\n\nexport function isWrongKeyError(error: unknown): boolean {\n return (\n error instanceof Error &&\n \"code\" in error &&\n (error as { code?: string }).code === \"SQLITE_NOTADB\"\n );\n}\n","import { DomainError, err, type Result } from \"../../shared/domain/result.js\";\n\n/** Error vocabulary of the VAULT bounded context (security language). */\nexport type VaultErrorCode =\n | \"VAULT_NOT_FOUND\"\n | \"VAULT_ALREADY_EXISTS\"\n | \"VAULT_LOCKED\"\n | \"WRONG_PASSPHRASE\"\n | \"WEAK_PASSPHRASE\"\n | \"KEYCHAIN_ERROR\"\n | \"STORAGE_ERROR\";\n\nexport const vaultErr = (code: VaultErrorCode, message: string): Result<never, DomainError> =>\n err(new DomainError(code, message));\n","import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { z } from \"zod\";\nimport { type DomainError, ok, type Result } from \"../../shared/domain/result.js\";\nimport type { VaultHeaderData } from \"../application/ports/vault-store.js\";\nimport { vaultErr } from \"../domain/errors.js\";\n\nconst headerSchema = z.object({\n vaultId: z.string().min(1),\n schemaVersion: z.literal(1),\n kdf: z.object({\n algorithm: z.literal(\"argon2id\"),\n memoryKiB: z.number().int().positive(),\n iterations: z.number().int().positive(),\n parallelism: z.number().int().positive(),\n }),\n saltBase64: z.string().min(1),\n createdAt: z.string(),\n});\n\nexport type VaultHeader = VaultHeaderData;\n\nexport function writeVaultHeader(path: string, header: VaultHeader): void {\n const json = {\n vaultId: header.vaultId,\n schemaVersion: header.schemaVersion,\n kdf: header.kdf,\n saltBase64: Buffer.from(header.salt).toString(\"base64\"),\n createdAt: header.createdAt,\n };\n writeFileSync(path, `${JSON.stringify(json, null, 2)}\\n`, \"utf8\");\n}\n\nexport function readVaultHeader(path: string): Result<VaultHeader, DomainError> {\n if (!existsSync(path)) {\n return vaultErr(\"VAULT_NOT_FOUND\", `No vault header found at ${path}. Run \"valija init\".`);\n }\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(path, \"utf8\"));\n } catch {\n return vaultErr(\"STORAGE_ERROR\", `Vault header at ${path} is not valid JSON.`);\n }\n const parsed = headerSchema.safeParse(raw);\n if (!parsed.success) {\n return vaultErr(\n \"STORAGE_ERROR\",\n `Vault header at ${path} is malformed: ${parsed.error.message}`,\n );\n }\n const h = parsed.data;\n return ok({\n vaultId: h.vaultId,\n schemaVersion: h.schemaVersion,\n kdf: h.kdf,\n salt: new Uint8Array(Buffer.from(h.saltBase64, \"base64\")),\n createdAt: h.createdAt,\n });\n}\n","import type { Database } from \"better-sqlite3-multiple-ciphers\";\nimport type {\n ContextItemRepository,\n FindByProjectFilters,\n SearchResult,\n} from \"../application/ports/repositories.js\";\nimport type { ContextItem } from \"../domain/entities/context-item.js\";\nimport type { ItemType } from \"../domain/values/item-type.js\";\nimport type { ProjectName } from \"../domain/values/project-name.js\";\nimport type { Tag } from \"../domain/values/tag.js\";\n\ninterface ItemRow {\n id: string;\n project_id: string;\n type: string;\n content: string;\n tags: string;\n pinned: number;\n source: string | null;\n archived: number;\n created_at: string;\n updated_at: string;\n}\n\nconst toItem = (row: ItemRow): ContextItem => ({\n id: row.id,\n projectId: row.project_id,\n type: row.type as ItemType,\n content: row.content,\n tags: JSON.parse(row.tags) as Tag[],\n pinned: row.pinned === 1,\n ...(row.source === null ? {} : { source: row.source }),\n archived: row.archived === 1,\n createdAt: new Date(row.created_at),\n updatedAt: new Date(row.updated_at),\n});\n\n/** Quote each term so user input cannot break FTS5 query syntax. Terms are ANDed. */\nconst toFtsQuery = (query: string): string =>\n query\n .split(/\\s+/)\n .filter(Boolean)\n .map((term) => `\"${term.replace(/\"/g, '\"\"')}\"`)\n .join(\" \");\n\nexport class SqliteContextItemRepository implements ContextItemRepository {\n constructor(private readonly db: Database) {}\n\n save(item: ContextItem): void {\n this.db\n .prepare(\n `INSERT INTO context_items\n (id, project_id, type, content, tags, pinned, source, archived, created_at, updated_at)\n VALUES (@id, @projectId, @type, @content, @tags, @pinned, @source, @archived, @createdAt, @updatedAt)\n ON CONFLICT(id) DO UPDATE SET\n type = excluded.type,\n content = excluded.content,\n tags = excluded.tags,\n pinned = excluded.pinned,\n source = excluded.source,\n archived = excluded.archived,\n updated_at = excluded.updated_at`,\n )\n .run({\n id: item.id,\n projectId: item.projectId,\n type: item.type,\n content: item.content,\n tags: JSON.stringify(item.tags),\n pinned: item.pinned ? 1 : 0,\n source: item.source ?? null,\n archived: item.archived ? 1 : 0,\n createdAt: item.createdAt.toISOString(),\n updatedAt: item.updatedAt.toISOString(),\n });\n }\n\n findByProject(projectId: string, filters: FindByProjectFilters = {}): ContextItem[] {\n const conditions = [\"project_id = @projectId\"];\n const params: Record<string, unknown> = { projectId };\n if (!filters.includeArchived) conditions.push(\"archived = 0\");\n if (filters.type !== undefined) {\n conditions.push(\"type = @type\");\n params.type = filters.type;\n }\n if (filters.pinned !== undefined) {\n conditions.push(\"pinned = @pinned\");\n params.pinned = filters.pinned ? 1 : 0;\n }\n const limit = filters.limit !== undefined ? ` LIMIT ${Math.max(0, filters.limit)}` : \"\";\n const rows = this.db\n .prepare(\n `SELECT * FROM context_items WHERE ${conditions.join(\" AND \")}\n ORDER BY created_at DESC${limit}`,\n )\n .all(params) as ItemRow[];\n return rows.map(toItem);\n }\n\n search(query: string, projectId?: string, limit = 20): SearchResult[] {\n const fts = toFtsQuery(query);\n if (fts.length === 0) return [];\n const projectFilter = projectId !== undefined ? \"AND i.project_id = @projectId\" : \"\";\n const rows = this.db\n .prepare(\n `SELECT i.*, p.name AS project_name\n FROM context_items_fts f\n JOIN context_items i ON i.rowid = f.rowid\n JOIN projects p ON p.id = i.project_id\n WHERE context_items_fts MATCH @fts AND i.archived = 0 ${projectFilter}\n ORDER BY rank LIMIT @limit`,\n )\n .all({ fts, projectId, limit }) as Array<ItemRow & { project_name: string }>;\n return rows.map((row) => ({\n item: toItem(row),\n projectName: row.project_name as ProjectName,\n }));\n }\n\n archive(itemId: string): boolean {\n const result = this.db\n .prepare(\"UPDATE context_items SET archived = 1 WHERE id = ?\")\n .run(itemId);\n return result.changes > 0;\n }\n}\n","import type { Database } from \"better-sqlite3-multiple-ciphers\";\nimport type { ProjectRepository } from \"../application/ports/repositories.js\";\nimport type { Project, ProjectSummary } from \"../domain/entities/project.js\";\nimport type { ProjectName } from \"../domain/values/project-name.js\";\n\ninterface ProjectRow {\n id: string;\n name: string;\n description: string | null;\n created_at: string;\n updated_at: string;\n}\n\nconst toProject = (row: ProjectRow): Project => ({\n id: row.id,\n name: row.name as ProjectName,\n ...(row.description === null ? {} : { description: row.description }),\n createdAt: new Date(row.created_at),\n updatedAt: new Date(row.updated_at),\n});\n\nexport class SqliteProjectRepository implements ProjectRepository {\n constructor(private readonly db: Database) {}\n\n save(project: Project): void {\n this.db\n .prepare(\n `INSERT INTO projects (id, name, description, created_at, updated_at)\n VALUES (@id, @name, @description, @createdAt, @updatedAt)\n ON CONFLICT(id) DO UPDATE SET\n name = excluded.name,\n description = excluded.description,\n updated_at = excluded.updated_at`,\n )\n .run({\n id: project.id,\n name: project.name,\n description: project.description ?? null,\n createdAt: project.createdAt.toISOString(),\n updatedAt: project.updatedAt.toISOString(),\n });\n }\n\n findByName(name: ProjectName): Project | null {\n const row = this.db.prepare(\"SELECT * FROM projects WHERE name = ?\").get(name) as\n | ProjectRow\n | undefined;\n return row ? toProject(row) : null;\n }\n\n list(): ProjectSummary[] {\n const rows = this.db\n .prepare(\n `SELECT p.*,\n COUNT(i.id) AS item_count,\n MAX(i.updated_at) AS last_activity\n FROM projects p\n LEFT JOIN context_items i ON i.project_id = p.id AND i.archived = 0\n GROUP BY p.id\n ORDER BY last_activity DESC NULLS LAST, p.name ASC`,\n )\n .all() as Array<ProjectRow & { item_count: number; last_activity: string | null }>;\n return rows.map((row) => ({\n project: toProject(row),\n itemCount: row.item_count,\n lastActivityAt: row.last_activity ? new Date(row.last_activity) : null,\n }));\n }\n}\n","import { type DomainError, ok, type Result } from \"../../shared/domain/result.js\";\nimport { migrate } from \"../../shared/infra/migrations.js\";\nimport { isWrongKeyError, openVaultDb } from \"../../shared/infra/sqlite.js\";\nimport type { VaultPaths } from \"../../shared/infra/vault-paths.js\";\nimport type { KeychainPort } from \"../../vault/application/ports/keychain.js\";\nimport { vaultErr } from \"../../vault/domain/errors.js\";\nimport { readVaultHeader } from \"../../vault/infra/vault-header.js\";\nimport type { VaultSession, VaultSessionFactory } from \"../application/ports/vault-session.js\";\nimport { SqliteContextItemRepository } from \"./item-repo.js\";\nimport { SqliteProjectRepository } from \"./project-repo.js\";\n\nconst LOCKED_MESSAGE = 'Vault is locked. Ask the user to run \"valija unlock\" in a terminal.';\n\n/**\n * Implements the context-owned VaultSessionFactory port by wiring vault\n * concerns (keychain, header) to the shared SQLite engine. This is the\n * one place where the context module depends on the vault module.\n */\nexport class SqliteVaultSessionFactory implements VaultSessionFactory {\n constructor(\n private readonly paths: VaultPaths,\n private readonly keychain: KeychainPort,\n ) {}\n\n open(): Result<VaultSession, DomainError> {\n const header = readVaultHeader(this.paths.header);\n if (!header.ok) return header;\n\n const keyHex = this.keychain.getKey(header.value.vaultId);\n if (keyHex === null) return vaultErr(\"VAULT_LOCKED\", LOCKED_MESSAGE);\n\n try {\n const db = openVaultDb(this.paths.db, keyHex);\n migrate(db);\n return ok({\n projects: new SqliteProjectRepository(db),\n items: new SqliteContextItemRepository(db),\n close: () => db.close(),\n });\n } catch (error) {\n if (isWrongKeyError(error)) {\n // Stale key in the keychain (e.g. vault file replaced) — treat as locked.\n this.keychain.deleteKey(header.value.vaultId);\n return vaultErr(\"VAULT_LOCKED\", LOCKED_MESSAGE);\n }\n return vaultErr(\"STORAGE_ERROR\", `Could not open vault: ${(error as Error).message}`);\n }\n }\n}\n","import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport interface VaultPaths {\n root: string;\n header: string;\n db: string;\n}\n\nexport function resolveVaultPaths(rootOverride?: string): VaultPaths {\n const root = rootOverride ?? process.env.VALIJA_HOME ?? join(homedir(), \".valija\");\n return {\n root,\n header: join(root, \"vault.json\"),\n db: join(root, \"vault.db\"),\n };\n}\n","export const bytesToHex = (bytes: Uint8Array): string =>\n Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n\nexport const isKeyHex = (value: string): boolean => /^[0-9a-f]{64}$/i.test(value);\n","export interface KdfParams {\n readonly algorithm: \"argon2id\";\n readonly memoryKiB: number;\n readonly iterations: number;\n readonly parallelism: number;\n}\n\nexport const DEFAULT_KDF_PARAMS: KdfParams = {\n algorithm: \"argon2id\",\n memoryKiB: 64 * 1024,\n iterations: 3,\n parallelism: 1,\n};\n\nexport interface VaultCrypto {\n /** Derive a 32-byte raw key from a passphrase. */\n deriveKey(passphrase: string, salt: Uint8Array, params: KdfParams): Promise<Uint8Array>;\n generateSalt(): Uint8Array;\n}\n","import type { Clock, IdGenerator } from \"../../shared/application/ports/clock.js\";\nimport { type DomainError, ok, type Result } from \"../../shared/domain/result.js\";\nimport { vaultErr } from \"../domain/errors.js\";\nimport { bytesToHex } from \"./hex.js\";\nimport { DEFAULT_KDF_PARAMS, type VaultCrypto } from \"./ports/crypto.js\";\nimport type { KeychainPort } from \"./ports/keychain.js\";\nimport type { VaultStore } from \"./ports/vault-store.js\";\n\nexport const MIN_PASSPHRASE_LENGTH = 8;\n\nexport interface CreateVaultOutput {\n vaultId: string;\n keyHex: string;\n createdAt: string;\n}\n\nexport class CreateVault {\n constructor(\n private readonly store: VaultStore,\n private readonly crypto: VaultCrypto,\n private readonly keychain: KeychainPort,\n private readonly clock: Clock,\n private readonly idGen: IdGenerator,\n ) {}\n\n async execute(passphrase: string): Promise<Result<CreateVaultOutput, DomainError>> {\n if (this.store.headerExists()) {\n return vaultErr(\"VAULT_ALREADY_EXISTS\", \"A vault already exists on this machine.\");\n }\n if (passphrase.length < MIN_PASSPHRASE_LENGTH) {\n return vaultErr(\n \"WEAK_PASSPHRASE\",\n `Passphrase must be at least ${MIN_PASSPHRASE_LENGTH} characters.`,\n );\n }\n const vaultId = this.idGen.next();\n const salt = this.crypto.generateSalt();\n const key = await this.crypto.deriveKey(passphrase, salt, DEFAULT_KDF_PARAMS);\n const keyHex = bytesToHex(key);\n const createdAt = this.clock.now().toISOString();\n\n this.store.writeHeader({ vaultId, schemaVersion: 1, kdf: DEFAULT_KDF_PARAMS, salt, createdAt });\n const init = this.store.initializeDb(keyHex);\n if (!init.ok) return init;\n\n // Convenience: a freshly created vault starts unlocked.\n this.keychain.setKey(vaultId, keyHex);\n return ok({ vaultId, keyHex, createdAt });\n }\n}\n","import { type DomainError, ok, type Result } from \"../../shared/domain/result.js\";\nimport type { KeychainPort } from \"./ports/keychain.js\";\nimport type { VaultStore } from \"./ports/vault-store.js\";\n\nexport class LockVault {\n constructor(\n private readonly store: VaultStore,\n private readonly keychain: KeychainPort,\n ) {}\n\n execute(): Result<{ wasUnlocked: boolean }, DomainError> {\n const header = this.store.readHeader();\n if (!header.ok) return header;\n const wasUnlocked = this.keychain.deleteKey(header.value.vaultId);\n return ok({ wasUnlocked });\n }\n}\n","import { type DomainError, ok, type Result } from \"../../shared/domain/result.js\";\nimport { vaultErr } from \"../domain/errors.js\";\nimport { bytesToHex, isKeyHex } from \"./hex.js\";\nimport type { VaultCrypto } from \"./ports/crypto.js\";\nimport type { KeychainPort } from \"./ports/keychain.js\";\nimport type { VaultStore } from \"./ports/vault-store.js\";\n\nexport interface UnlockInput {\n passphrase?: string;\n recoveryKeyHex?: string;\n}\n\nexport class UnlockVault {\n constructor(\n private readonly store: VaultStore,\n private readonly crypto: VaultCrypto,\n private readonly keychain: KeychainPort,\n ) {}\n\n async execute(input: UnlockInput): Promise<Result<{ vaultId: string }, DomainError>> {\n const header = this.store.readHeader();\n if (!header.ok) return header;\n\n let keyHex: string;\n if (input.recoveryKeyHex !== undefined) {\n if (!isKeyHex(input.recoveryKeyHex)) {\n return vaultErr(\"WRONG_PASSPHRASE\", \"Recovery key must be 64 hex characters.\");\n }\n keyHex = input.recoveryKeyHex.toLowerCase();\n } else if (input.passphrase !== undefined) {\n const key = await this.crypto.deriveKey(\n input.passphrase,\n header.value.salt,\n header.value.kdf,\n );\n keyHex = bytesToHex(key);\n } else {\n return vaultErr(\"WRONG_PASSPHRASE\", \"Provide a passphrase or a recovery key.\");\n }\n\n const verified = this.store.verifyKey(keyHex);\n if (!verified.ok) return verified;\n\n this.keychain.setKey(header.value.vaultId, keyHex);\n return ok({ vaultId: header.value.vaultId });\n }\n}\n","import { type DomainError, ok, type Result } from \"../../shared/domain/result.js\";\nimport type { KeychainPort } from \"./ports/keychain.js\";\nimport type { VaultStore } from \"./ports/vault-store.js\";\n\nexport interface VaultStatusOutput {\n initialized: boolean;\n unlocked: boolean;\n vaultId?: string;\n dbPath: string;\n}\n\nexport class VaultStatus {\n constructor(\n private readonly store: VaultStore,\n private readonly keychain: KeychainPort,\n ) {}\n\n execute(): Result<VaultStatusOutput, DomainError> {\n const dbPath = this.store.dbPath();\n if (!this.store.headerExists()) {\n return ok({ initialized: false, unlocked: false, dbPath });\n }\n const header = this.store.readHeader();\n if (!header.ok) return header;\n\n const keyHex = this.keychain.getKey(header.value.vaultId);\n const unlocked = keyHex !== null && this.store.verifyKey(keyHex).ok;\n return ok({ initialized: true, unlocked, vaultId: header.value.vaultId, dbPath });\n }\n}\n","import { randomBytes } from \"node:crypto\";\nimport argon2 from \"argon2\";\nimport type { KdfParams, VaultCrypto } from \"../application/ports/crypto.js\";\n\nexport const KEY_LENGTH = 32;\nexport const SALT_LENGTH = 16;\n\nexport class Argon2VaultCrypto implements VaultCrypto {\n async deriveKey(passphrase: string, salt: Uint8Array, params: KdfParams): Promise<Uint8Array> {\n const key = await argon2.hash(passphrase, {\n type: argon2.argon2id,\n raw: true,\n salt: Buffer.from(salt),\n memoryCost: params.memoryKiB,\n timeCost: params.iterations,\n parallelism: params.parallelism,\n hashLength: KEY_LENGTH,\n });\n return new Uint8Array(key);\n }\n\n generateSalt(): Uint8Array {\n return new Uint8Array(randomBytes(SALT_LENGTH));\n }\n}\n\nexport const toHex = (bytes: Uint8Array): string => Buffer.from(bytes).toString(\"hex\");\nexport const fromHex = (hex: string): Uint8Array => new Uint8Array(Buffer.from(hex, \"hex\"));\n","import { existsSync, mkdirSync } from \"node:fs\";\nimport { type DomainError, ok, type Result } from \"../../shared/domain/result.js\";\nimport { migrate } from \"../../shared/infra/migrations.js\";\nimport { isWrongKeyError, openVaultDb } from \"../../shared/infra/sqlite.js\";\nimport type { VaultPaths } from \"../../shared/infra/vault-paths.js\";\nimport type { VaultHeaderData, VaultStore } from \"../application/ports/vault-store.js\";\nimport { vaultErr } from \"../domain/errors.js\";\nimport { readVaultHeader, writeVaultHeader } from \"./vault-header.js\";\n\nexport class FileVaultStore implements VaultStore {\n constructor(private readonly paths: VaultPaths) {}\n\n headerExists(): boolean {\n return existsSync(this.paths.header);\n }\n\n readHeader(): Result<VaultHeaderData, DomainError> {\n return readVaultHeader(this.paths.header);\n }\n\n writeHeader(header: VaultHeaderData): void {\n mkdirSync(this.paths.root, { recursive: true });\n writeVaultHeader(this.paths.header, header);\n }\n\n initializeDb(keyHex: string): Result<void, DomainError> {\n try {\n const db = openVaultDb(this.paths.db, keyHex);\n migrate(db);\n db.close();\n return ok(undefined);\n } catch (error) {\n return vaultErr(\"STORAGE_ERROR\", `Could not create vault db: ${(error as Error).message}`);\n }\n }\n\n verifyKey(keyHex: string): Result<void, DomainError> {\n try {\n const db = openVaultDb(this.paths.db, keyHex);\n db.close();\n return ok(undefined);\n } catch (error) {\n if (isWrongKeyError(error)) {\n return vaultErr(\"WRONG_PASSPHRASE\", \"Wrong passphrase (or recovery key) for this vault.\");\n }\n return vaultErr(\"STORAGE_ERROR\", `Could not open vault db: ${(error as Error).message}`);\n }\n }\n\n dbPath(): string {\n return this.paths.db;\n }\n}\n","import { Entry } from \"@napi-rs/keyring\";\nimport type { KeychainPort } from \"../application/ports/keychain.js\";\n\nconst SERVICE = \"valija\";\n\nexport class OsKeychain implements KeychainPort {\n setKey(vaultId: string, keyHex: string): void {\n new Entry(SERVICE, vaultId).setPassword(keyHex);\n }\n\n getKey(vaultId: string): string | null {\n try {\n return new Entry(SERVICE, vaultId).getPassword();\n } catch {\n return null;\n }\n }\n\n deleteKey(vaultId: string): boolean {\n try {\n return new Entry(SERVICE, vaultId).deletePassword();\n } catch {\n return false;\n }\n }\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport { ITEM_TYPES } from \"../../context/domain/values/item-type.js\";\nimport type { DomainError } from \"../../shared/domain/result.js\";\nimport type { Container } from \"../container.js\";\nimport { VERSION } from \"../version.js\";\n\nconst ok = (text: string) => ({ content: [{ type: \"text\" as const, text }] });\nconst err = (error: DomainError) => ({\n content: [{ type: \"text\" as const, text: `${error.message} [${error.code}]` }],\n isError: true,\n});\n\nconst DESCRIPTIONS = {\n save_context:\n \"Save durable context about a project for future sessions in any AI tool. \" +\n \"Use when the user asks to save or remember something, or at the end of a working session. \" +\n \"Write `content` so it is self-contained and specific for a reader with no other context: \" +\n \"decisions made and why, current state, conventions and preferences established, next steps, \" +\n \"unresolved questions. Never include secrets, API keys, or passwords.\",\n save_handoff:\n \"Package the state of THIS conversation so another AI tool or session can continue seamlessly. \" +\n \"Structure `content` as: goal, what was done, current blockers, exact next step, \" +\n \"relevant files or links.\",\n get_context:\n \"Load the saved context pack for a project before starting work on it. Returns pinned and \" +\n \"recent context (decisions, preferences, progress, latest handoff) as markdown within a \" +\n \"token budget. Call this when the user asks to load, resume, or continue a project.\",\n search_context:\n \"Full-text search across saved context. Use for specific recall questions such as \" +\n \"'what did we decide about auth?'. Returns matching items with project, type, and date.\",\n list_projects:\n \"List existing projects with item counts and last activity. Use to disambiguate which \" +\n \"project the user means before saving or loading.\",\n} as const;\n\nexport function buildMcpServer(c: Container): McpServer {\n const server = new McpServer({ name: \"valija\", version: VERSION });\n const clientName = (): string | undefined => server.server.getClientVersion()?.name;\n\n server.registerTool(\n \"save_context\",\n {\n title: \"Save context\",\n description: DESCRIPTIONS.save_context,\n inputSchema: {\n project: z\n .string()\n .describe(\"Project slug, e.g. 'vault-app'. Created if it does not exist.\"),\n content: z.string().describe(\"Self-contained markdown. Max 32 KB.\"),\n type: z.enum(ITEM_TYPES).optional().describe(\"Kind of context. Defaults to 'fact'.\"),\n tags: z.array(z.string()).max(10).optional().describe(\"Lowercase tags for recall.\"),\n },\n },\n async ({ project, content, type, tags }) => {\n const source = clientName();\n const r = c.saveContext.execute({\n project,\n content,\n ...(type === undefined ? {} : { type }),\n ...(tags === undefined ? {} : { tags }),\n ...(source === undefined ? {} : { source }),\n });\n if (!r.ok) return err(r.error);\n return ok(\n `Saved ${r.value.type} to project \"${r.value.project}\"` +\n `${r.value.projectCreated ? \" (project created)\" : \"\"}. Item id: ${r.value.itemId}.`,\n );\n },\n );\n\n server.registerTool(\n \"save_handoff\",\n {\n title: \"Save handoff\",\n description: DESCRIPTIONS.save_handoff,\n inputSchema: {\n project: z.string().describe(\"Project slug. Created if it does not exist.\"),\n content: z\n .string()\n .describe(\"Goal, what was done, blockers, exact next step, relevant files or links.\"),\n },\n },\n async ({ project, content }) => {\n const source = clientName();\n const r = c.saveContext.execute({\n project,\n content,\n type: \"handoff\",\n ...(source === undefined ? {} : { source }),\n });\n if (!r.ok) return err(r.error);\n return ok(`Handoff saved to project \"${r.value.project}\". Item id: ${r.value.itemId}.`);\n },\n );\n\n server.registerTool(\n \"get_context\",\n {\n title: \"Get context pack\",\n description: DESCRIPTIONS.get_context,\n inputSchema: {\n project: z.string().describe(\"Project slug to load.\"),\n budget: z.number().int().positive().optional().describe(\"Token budget. Default 4000.\"),\n },\n },\n async ({ project, budget }) => {\n const r = c.getContextPack.execute({\n project,\n ...(budget === undefined ? {} : { budgetTokens: budget }),\n });\n if (!r.ok) return err(r.error);\n return ok(r.value.markdown);\n },\n );\n\n server.registerTool(\n \"search_context\",\n {\n title: \"Search context\",\n description: DESCRIPTIONS.search_context,\n inputSchema: {\n query: z.string().describe(\"Full-text query, e.g. 'auth decision'.\"),\n project: z.string().optional().describe(\"Limit to one project.\"),\n limit: z.number().int().positive().max(100).optional().describe(\"Max results. Default 20.\"),\n },\n },\n async ({ query, project, limit }) => {\n const r = c.searchContext.execute({\n query,\n ...(project === undefined ? {} : { project }),\n ...(limit === undefined ? {} : { limit }),\n });\n if (!r.ok) return err(r.error);\n if (r.value.length === 0) return ok(\"No matches.\");\n const lines = r.value.map(\n (hit) => `- [${hit.project}] (${hit.type}, ${hit.createdAt.slice(0, 10)}) ${hit.content}`,\n );\n return ok(`${r.value.length} match(es):\\n\\n${lines.join(\"\\n\")}`);\n },\n );\n\n server.registerTool(\n \"list_projects\",\n {\n title: \"List projects\",\n description: DESCRIPTIONS.list_projects,\n inputSchema: {},\n },\n async () => {\n const r = c.listProjects.execute();\n if (!r.ok) return err(r.error);\n if (r.value.length === 0) return ok(\"No projects in the vault yet.\");\n const lines = r.value.map(\n (p) =>\n `- ${p.name}: ${p.itemCount} item(s), last activity ${p.lastActivityAt?.slice(0, 10) ?? \"never\"}`,\n );\n return ok(lines.join(\"\\n\"));\n },\n );\n\n server.registerPrompt(\n \"save-context\",\n {\n title: \"Save session context to valija\",\n description: \"Distill this session into a self-contained context save.\",\n argsSchema: { project: z.string().optional() },\n },\n ({ project }) => ({\n messages: [\n {\n role: \"user\" as const,\n content: {\n type: \"text\" as const,\n text:\n `Review this conversation and save its durable context to valija${project ? ` under the project \"${project}\"` : \"\"}.\\n\\n` +\n \"1. If the project is ambiguous, call list_projects first and confirm with me.\\n\" +\n \"2. Compose content that is self-contained for a reader with no other context: \" +\n \"decisions made and why, current state, conventions/preferences established, \" +\n \"next steps, unresolved questions. No secrets, API keys, or passwords.\\n\" +\n \"3. Pick the right type (decision/progress/preference/fact) and 1-5 tags.\\n\" +\n \"4. Call save_context, then tell me what you saved in one line.\",\n },\n },\n ],\n }),\n );\n\n server.registerPrompt(\n \"load-context\",\n {\n title: \"Load project context from valija\",\n description: \"Load a project's context pack and resume work.\",\n argsSchema: { project: z.string() },\n },\n ({ project }) => ({\n messages: [\n {\n role: \"user\" as const,\n content: {\n type: \"text\" as const,\n text:\n `Call get_context for the project \"${project}\". Then:\\n` +\n \"1. Summarize the current state in 3 lines max.\\n\" +\n \"2. Propose the next step based on the latest handoff or progress.\\n\" +\n \"Do not repeat the whole pack back to me.\",\n },\n },\n ],\n }),\n );\n\n return server;\n}\n\nexport async function runMcpServer(c: Container): Promise<void> {\n const server = buildMcpServer(c);\n await server.connect(new StdioServerTransport());\n}\n","export const VERSION = \"0.1.0\";\n","import { writeFileSync } from \"node:fs\";\nimport type { Container } from \"../container.js\";\nimport { fail, formatDate, truncate } from \"./render.js\";\n\nexport function projectsCommand(c: Container): void {\n const result = c.listProjects.execute();\n if (!result.ok) fail(result.error);\n if (result.value.length === 0) {\n console.log(\n \"No projects yet. Save context from an AI tool, or check back after your first session.\",\n );\n return;\n }\n console.log(\"PROJECT ITEMS LAST ACTIVITY\");\n for (const p of result.value) {\n console.log(\n `${p.name.padEnd(32)} ${String(p.itemCount).padStart(5)} ${formatDate(p.lastActivityAt)}`,\n );\n }\n}\n\nexport function showCommand(c: Container, project: string, options: { type?: string }): void {\n const result = c.showProject.execute(project, options.type);\n if (!result.ok) fail(result.error);\n if (result.value.length === 0) {\n console.log(\"No items.\");\n return;\n }\n for (const item of result.value) {\n const pin = item.pinned ? \" 📌\" : \"\";\n const tags = item.tags.length > 0 ? ` [${item.tags.join(\", \")}]` : \"\";\n console.log(`\\n— ${item.type} · ${formatDate(item.createdAt)}${pin}${tags}`);\n console.log(item.content);\n }\n}\n\nexport function searchCommand(c: Container, query: string, options: { project?: string }): void {\n const result = c.searchContext.execute({\n query,\n ...(options.project === undefined ? {} : { project: options.project }),\n });\n if (!result.ok) fail(result.error);\n if (result.value.length === 0) {\n console.log(\"No matches.\");\n return;\n }\n for (const hit of result.value) {\n console.log(\n `${hit.project} ${hit.type.padEnd(10)} ${formatDate(hit.createdAt)} ${truncate(hit.content)}`,\n );\n }\n}\n\nexport function exportCommand(\n c: Container,\n project: string,\n options: { json?: boolean; output?: string },\n): void {\n const format = options.json ? \"json\" : \"md\";\n const result = c.exportPack.execute(project, format);\n if (!result.ok) fail(result.error);\n if (options.output !== undefined) {\n writeFileSync(options.output, result.value, \"utf8\");\n console.error(`Exported ${project} (${format}) to ${options.output}`);\n } else {\n console.log(result.value);\n }\n}\n","import type { DomainError } from \"../../shared/domain/result.js\";\n\nexport function fail(error: DomainError): never {\n console.error(`error [${error.code}]: ${error.message}`);\n process.exit(1);\n}\n\nexport function truncate(text: string, max = 80): string {\n const oneLine = text.replace(/\\s+/g, \" \").trim();\n return oneLine.length <= max ? oneLine : `${oneLine.slice(0, max - 1)}…`;\n}\n\nexport function formatDate(iso: string | null): string {\n return iso === null ? \"—\" : iso.slice(0, 10);\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { OsKeychain } from \"../../vault/infra/keyring.js\";\nimport type { Container } from \"../container.js\";\nimport { CLIENTS, clientConfigPath } from \"./installer.js\";\n\ninterface Check {\n name: string;\n ok: boolean;\n detail: string;\n fatal?: boolean;\n}\n\nexport async function doctorCommand(c: Container): Promise<void> {\n const checks: Check[] = [];\n\n const [major] = process.versions.node.split(\".\").map(Number);\n checks.push({\n name: \"node\",\n ok: (major ?? 0) >= 22,\n detail: `v${process.versions.node} (need >=22)`,\n fatal: true,\n });\n\n try {\n const { default: Db } = await import(\"better-sqlite3-multiple-ciphers\");\n const db = new Db(\":memory:\");\n db.pragma(\"cipher='sqlcipher'\");\n db.close();\n checks.push({ name: \"sqlcipher\", ok: true, detail: \"native module loads\" });\n } catch (e) {\n checks.push({ name: \"sqlcipher\", ok: false, detail: (e as Error).message, fatal: true });\n }\n\n try {\n const keychain = new OsKeychain();\n keychain.setKey(\"doctor-probe\", \"test\");\n const roundtrip = keychain.getKey(\"doctor-probe\") === \"test\";\n keychain.deleteKey(\"doctor-probe\");\n checks.push({ name: \"keychain\", ok: roundtrip, detail: \"OS keychain read/write\" });\n } catch (e) {\n checks.push({ name: \"keychain\", ok: false, detail: (e as Error).message });\n }\n\n const status = c.vaultStatus.execute();\n if (status.ok) {\n checks.push({\n name: \"vault\",\n ok: status.value.initialized,\n detail: status.value.initialized\n ? `${status.value.unlocked ? \"unlocked\" : \"locked\"} at ${status.value.dbPath}`\n : 'not initialized — run \"valija init\"',\n });\n } else {\n checks.push({ name: \"vault\", ok: false, detail: status.error.message });\n }\n\n for (const client of CLIENTS) {\n const path = clientConfigPath(client);\n let detail = \"config not found\";\n let installed = false;\n if (existsSync(path)) {\n detail = \"config found, valija not installed\";\n try {\n const parsed = JSON.parse(readFileSync(path, \"utf8\")) as {\n mcpServers?: Record<string, unknown>;\n };\n installed = parsed.mcpServers?.valija !== undefined;\n if (installed) detail = \"valija installed\";\n } catch {\n detail = \"config exists but is not valid JSON\";\n }\n }\n checks.push({ name: client, ok: installed, detail });\n }\n\n let fatal = false;\n for (const check of checks) {\n console.log(`${check.ok ? \"✓\" : \"✗\"} ${check.name.padEnd(16)} ${check.detail}`);\n if (!check.ok && check.fatal) fatal = true;\n }\n if (fatal) process.exit(1);\n}\n","import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nexport const CLIENTS = [\"claude-code\", \"claude-desktop\", \"cursor\"] as const;\nexport type ClientId = (typeof CLIENTS)[number];\n\nconst MCP_ENTRY = { command: \"npx\", args: [\"-y\", \"valija\", \"mcp\"] };\n\nexport function clientConfigPath(client: ClientId, platform = process.platform): string {\n const home = homedir();\n switch (client) {\n case \"claude-code\":\n return join(home, \".claude.json\");\n case \"cursor\":\n return join(home, \".cursor\", \"mcp.json\");\n case \"claude-desktop\": {\n if (platform === \"win32\")\n return join(\n process.env.APPDATA ?? join(home, \"AppData\", \"Roaming\"),\n \"Claude\",\n \"claude_desktop_config.json\",\n );\n if (platform === \"darwin\")\n return join(home, \"Library\", \"Application Support\", \"Claude\", \"claude_desktop_config.json\");\n return join(home, \".config\", \"Claude\", \"claude_desktop_config.json\");\n }\n }\n}\n\nexport interface InstallResult {\n configPath: string;\n backupPath: string | null;\n}\n\n/** Merge the valija MCP entry into the client config, backing up the original file first. */\nexport function installIntoClient(client: ClientId): InstallResult {\n const configPath = clientConfigPath(client);\n let existing: Record<string, unknown> = {};\n let backupPath: string | null = null;\n\n if (existsSync(configPath)) {\n const raw = readFileSync(configPath, \"utf8\");\n const parsed: unknown = JSON.parse(raw); // malformed JSON -> throw, never overwrite\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n throw new Error(`${configPath} does not contain a JSON object; not touching it.`);\n }\n existing = parsed as Record<string, unknown>;\n backupPath = `${configPath}.backup-${Date.now()}`;\n copyFileSync(configPath, backupPath);\n } else {\n mkdirSync(dirname(configPath), { recursive: true });\n }\n\n const servers =\n typeof existing.mcpServers === \"object\" && existing.mcpServers !== null\n ? (existing.mcpServers as Record<string, unknown>)\n : {};\n const merged = { ...existing, mcpServers: { ...servers, valija: MCP_ENTRY } };\n writeFileSync(configPath, `${JSON.stringify(merged, null, 2)}\\n`, \"utf8\");\n return { configPath, backupPath };\n}\n\nexport function manualInstructions(client: ClientId): string {\n return (\n `Add this to the \"mcpServers\" object of ${clientConfigPath(client)}:\\n\\n` +\n ` \"valija\": ${JSON.stringify(MCP_ENTRY, null, 2).replace(/\\n/g, \"\\n \")}\\n`\n );\n}\n","export function renderRecoveryKit(vaultId: string, keyHex: string, createdAt: string): string {\n return `================================================================\n VALIJA RECOVERY KIT\n================================================================\n\nCreated: ${createdAt}\nVault id: ${vaultId}\n\nRAW ENCRYPTION KEY (hex):\n\n ${keyHex}\n\n----------------------------------------------------------------\nWHAT THIS IS\n\nThis key decrypts your valija vault (~/.valija/vault.db) WITHOUT\nthe passphrase. It is the only way back in if you forget your\npassphrase. There is no server, no account, no reset email.\n\n passphrase lost + this kit lost = your data is gone. Forever.\n\nWHAT TO DO WITH IT\n\n 1. Print this file or copy it by hand.\n 2. Store it OFFLINE: a drawer, a safe, a password manager you\n trust — anywhere that is not this computer.\n 3. Delete this file from disk once stored.\n\nHOW TO RECOVER\n\n valija unlock --recovery-key <the hex above>\n\nAnyone holding this key can read your vault. Guard it like a key.\n================================================================\n`;\n}\n","import { createInterface, type Interface } from \"node:readline\";\n\nconst CTRL_C = String.fromCharCode(0x03);\nconst BACKSPACE = String.fromCharCode(0x08);\nconst DEL = String.fromCharCode(0x7f);\n\n// Shared line reader for piped stdin: one chunk can carry several lines,\n// so a per-prompt reader would swallow the lines meant for later prompts.\nlet reader: Interface | undefined;\nconst bufferedLines: string[] = [];\nconst waiters: Array<(line: string) => void> = [];\n\nfunction readPipedLine(): Promise<string> {\n if (reader === undefined) {\n reader = createInterface({ input: process.stdin });\n reader.on(\"line\", (line) => {\n const waiter = waiters.shift();\n if (waiter) waiter(line);\n else bufferedLines.push(line);\n if (waiters.length === 0) reader?.pause();\n });\n }\n const queued = bufferedLines.shift();\n if (queued !== undefined) return Promise.resolve(queued);\n reader.resume();\n return new Promise((resolve) => waiters.push(resolve));\n}\n\nfunction readHiddenTtyLine(): Promise<string> {\n return new Promise((resolve) => {\n const { stdin, stdout } = process;\n const chars: string[] = [];\n const onData = (buf: Buffer) => {\n for (const c of buf.toString(\"utf8\")) {\n if (c === \"\\r\" || c === \"\\n\") {\n stdin.setRawMode(false);\n stdin.pause();\n stdin.off(\"data\", onData);\n stdout.write(\"\\n\");\n resolve(chars.join(\"\"));\n return;\n }\n if (c === CTRL_C) {\n stdin.setRawMode(false);\n stdout.write(\"\\n\");\n process.exit(130);\n }\n if (c === BACKSPACE || c === DEL) chars.pop();\n else chars.push(c);\n }\n };\n stdin.setRawMode(true);\n stdin.resume();\n stdin.on(\"data\", onData);\n });\n}\n\n/** Prompt for a secret. Hides input on a TTY; reads plain lines when piped. */\nexport function promptHidden(question: string): Promise<string> {\n process.stdout.write(question);\n return process.stdin.isTTY === true ? readHiddenTtyLine() : readPipedLine();\n}\n","import { renderRecoveryKit } from \"../../vault/infra/recovery-kit.js\";\nimport type { Container } from \"../container.js\";\nimport { promptHidden } from \"./prompt.js\";\nimport { fail } from \"./render.js\";\n\nexport async function initCommand(c: Container): Promise<void> {\n console.log(\"Creating your encrypted vault.\\n\");\n console.log(\"Choose a passphrase (min 8 chars). You will need it to unlock the vault.\");\n console.log(\"If you lose it AND the recovery kit, your data is gone. No reset exists.\\n\");\n\n const passphrase = await promptHidden(\"Passphrase: \");\n const confirmation = await promptHidden(\"Repeat passphrase: \");\n if (passphrase !== confirmation) {\n console.error(\"error: passphrases do not match.\");\n process.exit(1);\n }\n\n console.log(\"\\nDeriving key (Argon2id, ~1s)...\");\n const result = await c.createVault.execute(passphrase);\n if (!result.ok) fail(result.error);\n\n const kit = renderRecoveryKit(result.value.vaultId, result.value.keyHex, result.value.createdAt);\n console.log(`\\nVault created at ${c.paths.root} and unlocked.\\n`);\n console.log(kit);\n console.log(\"^ THIS IS YOUR RECOVERY KIT — it is shown ONCE and never stored.\");\n console.log(\" Copy it somewhere safe (offline) before you close this terminal.\\n\");\n console.log('Next: run \"valija install claude-code\" (or claude-desktop, cursor).');\n}\n\nexport async function unlockCommand(\n c: Container,\n options: { recoveryKey?: string },\n): Promise<void> {\n const input =\n options.recoveryKey !== undefined\n ? { recoveryKeyHex: options.recoveryKey }\n : { passphrase: await promptHidden(\"Passphrase: \") };\n const result = await c.unlockVault.execute(input);\n if (!result.ok) fail(result.error);\n console.log(\"Vault unlocked. MCP tools can now read and write context.\");\n console.log('Lock it again with \"valija lock\".');\n}\n\nexport function lockCommand(c: Container): void {\n const result = c.lockVault.execute();\n if (!result.ok) fail(result.error);\n console.log(result.value.wasUnlocked ? \"Vault locked.\" : \"Vault was already locked.\");\n}\n\nexport function statusCommand(c: Container): void {\n const result = c.vaultStatus.execute();\n if (!result.ok) fail(result.error);\n const s = result.value;\n if (!s.initialized) {\n console.log('No vault on this machine. Run \"valija init\" to create one.');\n return;\n }\n console.log(`vault: ${s.dbPath}`);\n console.log(`vault id: ${s.vaultId}`);\n console.log(`state: ${s.unlocked ? \"UNLOCKED\" : \"LOCKED\"}`);\n}\n"],"mappings":"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","names":["PATTERN","existsSync","mkdirSync","existsSync","mkdirSync","z","ok","err","z","writeFileSync","writeFileSync","existsSync","readFileSync","existsSync","mkdirSync","readFileSync","writeFileSync","homedir","dirname","join","existsSync","readFileSync"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "valija",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Open source, end-to-end encrypted context vault for developers who use several AI tools. Local MCP server + CLI.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=22"
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"valija": "dist/program.js"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"README.md",
|
|
16
|
+
"LICENSE"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup",
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"test:watch": "vitest",
|
|
22
|
+
"lint": "biome check .",
|
|
23
|
+
"format": "biome format --write .",
|
|
24
|
+
"typecheck": "tsc --noEmit"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"mcp",
|
|
28
|
+
"mcp-server",
|
|
29
|
+
"context",
|
|
30
|
+
"vault",
|
|
31
|
+
"encryption",
|
|
32
|
+
"sqlcipher",
|
|
33
|
+
"ai-tools",
|
|
34
|
+
"claude",
|
|
35
|
+
"cursor"
|
|
36
|
+
],
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "git+https://github.com/Akiles94/valija.git"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@biomejs/biome": "^2.5.3",
|
|
43
|
+
"@types/node": "^26.1.1",
|
|
44
|
+
"tsup": "^8.5.1",
|
|
45
|
+
"typescript": "^7.0.2",
|
|
46
|
+
"vitest": "^4.1.10"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
50
|
+
"@napi-rs/keyring": "^1.3.0",
|
|
51
|
+
"argon2": "^0.44.0",
|
|
52
|
+
"better-sqlite3-multiple-ciphers": "^12.11.1",
|
|
53
|
+
"commander": "^15.0.0",
|
|
54
|
+
"ulid": "^3.0.2",
|
|
55
|
+
"zod": "^4.4.3"
|
|
56
|
+
}
|
|
57
|
+
}
|