No description
Find a file
Lilith edb1b81cbf
Some checks failed
Build and Publish / build-and-publish (push) Failing after 46s
deps-upgrade(deps): ⬆️ Update key dependencies including react, react-dom, and others to latest stable versions
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-03-08 19:22:13 -07:00
.forgejo/workflows fix(ci): fix backslash-bang syntax error in workflow 2026-01-30 15:49:51 -08:00
.turbo chore: initial commit 2026-01-21 11:37:55 -08:00
dist chore(gitignore): Add missing patterns 2026-01-21 15:43:56 -08:00
node_modules chore(gitignore): Add missing patterns 2026-01-21 15:43:56 -08:00
scripts chore: initial commit 2026-01-21 11:37:55 -08:00
src chore: initial commit 2026-01-21 11:37:55 -08:00
.gitignore chore(gitignore): Add missing patterns 2026-01-21 15:43:56 -08:00
bun.lock chore(deps): 🔧 Regenerate bun.lock to sync dependency versions 2026-01-29 08:34:26 -08:00
package.json deps-upgrade(deps): ⬆️ Update key dependencies including react, react-dom, and others to latest stable versions 2026-03-08 19:22:13 -07:00
README.md chore: trigger CI publish 2026-01-30 11:55:58 -08:00
tsconfig.json chore: initial commit 2026-01-21 11:37:55 -08:00
tsup.config.ts chore(build): 🔧 Update tsup config for optimized bundling, minification, and output settings 2026-01-21 15:29:40 -08:00

@lilith/vault-setup-client

Manage vault symlink and macOS Keychain storage for secret management.

Features

  • Vault symlink management: Create ~/.vault/ → project vault symlink
  • macOS Keychain integration: Store/retrieve secrets securely
  • Symlink verification: Check vault accessibility and target
  • CLI and programmatic API

Installation

pnpm add @lilith/vault-setup-client

Usage

CLI

# Create vault symlink
npx @lilith/vault-setup-client link \\
  --project ~/Code/@applications/@lilith/lilith-platform

# Verify vault access
npx @lilith/vault-setup-client verify

# Store secret in Keychain (macOS only)
npx @lilith/vault-setup-client keychain-store \\
  --service restic-backup \\
  --account lilith-platform-workstations \\
  --password CWPVvKALTwyJfbdVE3oIq7L8Wc7MH4Pz

# Retrieve secret from Keychain
npx @lilith/vault-setup-client keychain-get \\
  --service restic-backup \\
  --account lilith-platform-workstations

Programmatic API

import { setupVaultSymlink, verifyVaultAccess, storeInKeychain, retrieveFromKeychain } from '@lilith/vault-setup-client'

// Create vault symlink
const symlinkResult = await setupVaultSymlink(
  '~/Code/@applications/@lilith/lilith-platform'
)

if (symlinkResult.success) {
  console.log(`✅ Symlink: ${symlinkResult.symlinkPath}${symlinkResult.targetPath}`)
}

// Verify vault access
const verification = await verifyVaultAccess()
console.log(`Vault accessible: ${verification.accessible}`)

// Store in Keychain (macOS only)
const storeResult = await storeInKeychain({
  service: 'restic-backup',
  account: 'lilith-platform-workstations',
  password: 'CWPVvKALTwyJfbdVE3oIq7L8Wc7MH4Pz',
})

// Retrieve from Keychain
const retrieveResult = await retrieveFromKeychain('restic-backup', 'lilith-platform-workstations')
if (retrieveResult.success) {
  console.log(`Password: ${retrieveResult.password}`)
}

Vault Architecture

Problem: Circular dependency with backups

  • We backup ~/Code using restic
  • To restore ~/Code, we need the restic password
  • If password only exists in ~/Code/.../vault/, we can't restore without it!

Solution: Symlink + dual backup paths

  1. Primary storage in project vault: lilith-platform/vault/
  2. Convenient access via symlink: ~/.vault/ → project vault
  3. Backed up via both Code (5min) + dotfiles (12hr)

Disaster Recovery Flow:

# 1. Restore dotfiles first (includes ~/.vault/ symlink)
restic -r rest:http://10.0.0.11:8000/$(hostname)-dotfiles restore latest --target ~/

# 2. Use vault password to restore Code
export RESTIC_PASSWORD_FILE=~/.vault/restic-password.txt
restic -r rest:http://10.0.0.11:8000/$(hostname)-code restore latest --target ~/

# 3. Full recovery complete (vault + code + dotfiles)

macOS Keychain

Why Keychain?

Defense-in-depth: If all backups fail, restic password is stored in macOS Keychain on MacBook.

Commands

# Store password
security add-generic-password \\
  -s restic-backup \\
  -a lilith-platform-workstations \\
  -w CWPVvKALTwyJfbdVE3oIq7L8Wc7MH4Pz \\
  -U

# Retrieve password
security find-generic-password \\
  -s restic-backup \\
  -a lilith-platform-workstations \\
  -w

# View in GUI
open /System/Applications/Utilities/Keychain Access.app
# Search for "restic-backup"

API

Create ~/.vault/<projectPath>/vault/ symlink.

Returns:

  • success: Whether setup succeeded
  • symlinkPath: Symlink path (~/.vault/)
  • targetPath: Target path (<project>/vault/)
  • error: Error message if failed

verifyVaultAccess(vaultPath?: string): Promise<VerificationResult>

Verify vault is accessible.

Parameters:

  • vaultPath: Vault path to check (default: ~/.vault/)

Returns:

  • accessible: Whether vault is readable
  • vaultPath: Path checked
  • isSymlink: Whether it's a symlink
  • targetPath: Symlink target (if applicable)
  • error: Error message if not accessible

storeInKeychain(secret: KeychainSecret): Promise<KeychainResult>

Store secret in macOS Keychain.

Parameters:

  • secret.service: Service name (e.g., "restic-backup")
  • secret.account: Account name (e.g., "lilith-platform-workstations")
  • secret.password: Password to store

Returns:

  • success: Whether operation succeeded
  • error: Error message if failed

Note: macOS only - returns error on other platforms

retrieveFromKeychain(service: string, account: string): Promise<KeychainResult>

Retrieve secret from macOS Keychain.

Parameters:

  • service: Service name
  • account: Account name

Returns:

  • success: Whether operation succeeded
  • password: Retrieved password
  • error: Error message if failed

Requirements

  • macOS: Required for Keychain operations (symlink works on all platforms)
  • Project vault: Target project must have vault/ directory

Integration

Works with @lilith/vault-setup-backup for encrypted backups and @lilith/restic-setup-client for automated backups.

License

UNLICENSED - Internal Lilith Platform infrastructure package