Reorganize Firefox configuration and repository documentation

- Configure Firefox with privacy settings and extensions (Bitwarden, Plasma Integration, MetaMask, Kagi Search, uBlock Origin)
- Set Kagi as default/only search engine
- Add MOZ_USE_XINPUT2=1 for smooth scrolling
- Create context/ directory for concise unit documentation
- Create tests/ directory for test scripts
- Move test-firefox-config.sh to tests/
- Update agents.md with documentation workflow guidelines
- Fix syntax errors in desktop.nix and dev.nix
This commit is contained in:
Julian Sutter 2026-02-16 23:08:48 -08:00
parent 67581adde6
commit 449510c746
10 changed files with 994 additions and 111 deletions

477
tests/test-firefox-config.sh Executable file
View file

@ -0,0 +1,477 @@
#!/usr/bin/env bash
# Firefox Configuration Test Script
# Tests the Firefox Home Manager configuration for user jsutter
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Test counters
PASSED=0
FAILED=0
SKIPPED=0
TOTAL=0
# Helper functions
print_header() {
echo ""
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${BLUE} $1${NC}"
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
}
print_test() {
echo -e "\n${YELLOW}[TEST]${NC} $1"
((TOTAL++))
}
print_pass() {
echo -e "${GREEN} ✓ PASS${NC}: $1"
((PASSED++))
}
print_fail() {
echo -e "${RED} ✗ FAIL${NC}: $1"
((FAILED++))
}
print_skip() {
echo -e "${YELLOW} ⊘ SKIP${NC}: $1"
((SKIPPED++))
}
print_info() {
echo -e " ${NC}$1"
}
print_report() {
local description="$1"
local pass_count="$2"
local fail_count="$3"
if [[ $fail_count -eq 0 ]]; then
print_pass "$description (passed $pass_count/$pass_count)"
else
local total=$((pass_count + fail_count))
print_fail "$description (passed $pass_count/$total)"
fi
}
# Check if a command exists
command_exists() {
command -v "$1" &> /dev/null
}
# Check if a preference matches expected value
check_pref() {
local profile="$1"
local pref="$2"
local expected="$3"
local actual=$(grep "\"${pref}\"" "$profile/prefs.js" 2>/dev/null | head -1 | sed 's/.*user_pref[^,]*,\s*//;s/);.*$//' 2>/dev/null || echo "")
if [[ "$actual" == *"$expected"* ]]; then
print_pass "$pref = $expected"
return 0
else
print_fail "$pref = $expected (got: $actual)"
return 1
fi
}
# Get Firefox profile directory
get_firefox_profile() {
local firefox_dir="$HOME/.mozilla/firefox"
if [[ -d "$firefox_dir" ]]; then
local profile=$(grep -E "Default=1" "$firefox_dir/profiles.ini" 2>/dev/null | head -1 | cut -d= -f2 -s)
if [[ -n "$profile" ]] && [[ -d "$firefox_dir/$profile" ]]; then
echo "$firefox_dir/$profile"
return 0
fi
# Try to find jsutter profile
profile=$(find "$firefox_dir" -maxdepth 1 -type d -name "*jsutter*" 2>/dev/null | head -1)
if [[ -n "$profile" ]]; then
echo "$profile"
return 0
fi
# Get first available profile
profile=$(ls -1 "$firefox_dir"/*.default* 2>/dev/null | head -1)
if [[ -n "$profile" ]]; then
echo "$profile"
return 0
fi
fi
echo ""
return 1
}
# Get Firefox executable
get_firefox_exec() {
if command_exists firefox-esr &>/dev/null; then
echo firefox-esr
elif command_exists firefox &>/dev/null; then
echo firefox
elif [[ -f "/run/current-system/sw/bin/firefox" ]]; then
echo /run/current-system/sw/bin/firefox
else
echo ""
fi
}
print_header "Firefox Configuration Test Script"
echo "Testing configuration for user: $(whoami)"
echo "Date: $(date '+%Y-%m-%d %H:%M:%S')"
# ============================================
# Environment Variables
# ============================================
print_header "1. Environment Variables"
print_test "Check MOZ_USE_XINPUT2 environment variable"
if [[ -z "$MOZ_USE_XINPUT2" ]]; then
print_fail "MOZ_USE_XINPUT2 not set"
print_info "This should be set in Home Manager sessionVariables"
else
if [[ "$MOZ_USE_XINPUT2" == "1" ]]; then
print_pass "MOZ_USE_XINPUT2 = 1"
else
print_fail "MOZ_USE_XINPUT2 = $MOZ_USE_XINPUT2 (expected: 1)"
fi
fi
print_test "Check session variables in shell config"
if [[ -f "$HOME/.zshrc" ]] || [[ -f "$HOME/.bashrc" ]]; then
print_info "Shell config files found"
else
print_skip "No shell config file found"
fi
# ============================================
# Firefox Installation
# ============================================
print_header "2. Firefox Installation"
FIREFOX=$(get_firefox_exec)
if [[ -n "$FIREFOX" ]]; then
print_test "Firefox executable found"
print_pass "Firefox at: $FIREFOX"
print_test "Firefox version"
VERSION=$($FIREFOX --version 2>/dev/null || echo "unknown")
print_pass "Firefox version: $VERSION"
else
print_fail "Firefox executable not found"
print_info "Check if Firefox is installed via nixos-rebuild switch"
fi
# ============================================
# Policy Configuration
# ============================================
print_header "3. Enterprise Policies"
POLICY_FILE="/run/current-system/sw/lib/firefox/distribution/policies.json"
print_test "Check policy file exists"
if [[ -f "$POLICY_FILE" ]]; then
print_pass "Policy file found: $POLICY_FILE"
else
print_fail "Policy file not found"
print_info "Activate the configuration with: nixos-rebuild switch"
fi
if [[ -f "$POLICY_FILE" ]]; then
print_test "Check policy file is valid JSON"
if jq empty "$POLICY_FILE" 2>/dev/null; then
print_pass "Policy file is valid JSON"
else
print_fail "Policy file is not valid JSON"
fi
print_test "Check extension policies"
EXTENSIONS=$(jq -r '.policies.ExtensionSettings | keys[]' "$POLICY_FILE" 2>/dev/null || echo "")
EXPECTED_EXTENSIONS=(
"uBlock0@raymondhill.net"
"{446900e4-71c2-419f-a6a7-df9c2b2dc922}"
"plasma-browser-integration@kde.org"
"webextension@metamask.io"
"kagi-search@kagi.com"
)
all_found=true
for ext in "${EXPECTED_EXTENSIONS[@]}"; do
if echo "$EXTENSIONS" | grep -q "$ext"; then
print_info "Extension policy found: $ext"
else
print_fail "Extension policy missing: $ext"
all_found=false
fi
done
if $all_found; then
print_pass "All extension policies configured"
fi
print_test "Check privacy settings policies"
PRIVACY_OK=true
if jq -e '.policies.OfferToSaveLogins == false' "$POLICY_FILE" &>/dev/null; then
print_info "Password saving disabled"
else
print_fail "Password saving not disabled"
PRIVACY_OK=false
fi
if jq -e '.policies.PasswordManagerEnabled == false' "$POLICY_FILE" &>/dev/null; then
print_info "Password manager disabled"
else
print_fail "Password manager not disabled"
PRIVACY_OK=false
fi
if jq -e '.policies.DisableTelemetry == true' "$POLICY_FILE" &>/dev/null; then
print_info "Telemetry disabled"
else
print_fail "Telemetry not disabled"
PRIVACY_OK=false
fi
if jq -e '.policies.DisableFirefoxStudies == true' "$POLICY_FILE" &>/dev/null; then
print_info "Firefox Studies disabled"
else
print_fail "Firefox Studies not disabled"
PRIVACY_OK=false
fi
if $PRIVACY_OK; then
print_pass "Privacy settings policies configured correctly"
fi
print_test "Check homepage/new tab policies"
HOME_OK=true
if jq -e '.policies.FirefoxHome.Search == false' "$POLICY_FILE" &>/dev/null; then
print_info "Search on home page disabled"
else
print_fail "Search on home page not disabled"
HOME_OK=false
fi
if jq -e '.policies.FirefoxHome.TopSites == false' "$POLICY_FILE" &>/dev/null; then
print_info "Top Sites disabled"
else
print_fail "Top Sites not disabled"
HOME_OK=false
fi
if jq -e '.policies.FirefoxHome.Pocket == false' "$POLICY_FILE" &>/dev/null; then
print_info "Pocket disabled"
else
print_fail "Pocket not disabled"
HOME_OK=false
fi
if $HOME_OK; then
print_pass "Homepage/new tab policies configured correctly"
fi
fi
# ============================================
# User Profile Configuration
# ============================================
print_header "4. Profile Configuration"
PROFILE=$(get_firefox_profile)
if [[ -n "$PROFILE" ]]; then
print_test "Firefox profile directory found"
print_pass "Profile: $PROFILE"
# Check for user.js
USER_JS="$PROFILE/user.js"
if [[ -f "$USER_JS" ]]; then
print_test "user.js file exists"
print_pass "user.js: $USER_JS"
# Check key settings
print_test "Check key user.js preferences"
cat > /tmp/firefox_check.sh << 'EOF'
#!/bin/bash
PROFILE="$1"
check_pref() {
local pref="$1"
local expected="$2"
local actual=$(grep "\"${pref}\"" "$PROFILE/user.js" 2>/dev/null | head -1 | sed 's/.*user_pref[^,]*,\s*//;s/);.*$//' 2>/dev/null || echo "")
if [[ "$actual" == *"$expected"* ]]; then
echo "PASS: $pref"
return 0
else
echo "FAIL: $pref (got: $actual)"
return 1
fi
}
check_pref "browser.ctrlTab.recentlyUsedOrder" "true"
check_pref "browser.tabs.hoverPreview.enabled" "false"
check_pref "browser.link.preview.enabled" "false"
check_pref "browser.newtabpage.enabled" "false"
check_pref "browser.startup.homepage" "about:blank"
check_pref "browser.search.suggest.enabled" "false"
check_pref "signon.rememberSignons" "false"
check_pref "media.videocontrols.picture-in-picture.allow-multiple" "false"
check_pref "browser.contentblocking.category" "strict"
check_pref "extensions.pocket.enabled" "false"
check_pref "privacy.sanitize.sanitizeOnShutdown" "true"
check_pref "toolkit.legacyUserProfileCustomizations.stylesheets" "true"
check_pref "privacy.userContext.enabled" "true"
EOF
chmod +x /tmp/firefox_check.sh
output=$(/tmp/firefox_check.sh "$PROFILE")
pass_count=$(echo "$output" | grep -c "PASS" || true)
fail_count=$(echo "$output" | grep -c "FAIL" || true)
echo "$output" | while read line; do
if [[ "$line" == "PASS:"* ]]; then
print_pass "${line#PASS: }"
else
print_fail "${line#FAIL: }"
fi
done
print_report "user.js key settings" "$pass_count" "$fail_count"
else
print_fail "user.js not found (Firefox needs to be run once to generate)"
fi
# Check for extensions
print_test "Check installed extensions"
INSTALLED_EXTENSIONS=$(ls -1 "$PROFILE/extensions" 2>/dev/null || echo "")
if [[ -n "$INSTALLED_EXTENSIONS" ]]; then
print_info "Found $(echo "$INSTALLED_EXTENSIONS" | wc -l) extension(s):"
echo "$INSTALLED_EXTENSIONS" | while read ext; do
print_info " - $ext"
done
print_pass "Extensions directory exists"
else
print_skip "No extensions installed yet (start Firefox to install via policy)"
fi
else
print_fail "Firefox profile not found"
print_info "Start Firefox once to create a profile"
print_info "Profile location is typically: ~/.mozilla/firefox/*.default*"
fi
# ============================================
# Manual Verification Checklist
# ============================================
print_header "5. Manual Verification Checklist"
cat << 'MANUAL'
The following items require manual verification in Firefox:
[ ] 1. Open Firefox and check all 4 extensions are installed:
- uBlock Origin
- Privacy Badger
- Facebook Container
- Multi-account Containers
[ ] 2. Open about:preferences#privacy and verify:
- Content blocking is set to "Strict"
- "Clear history when Firefox closes" is checked
- "Remember passwords" is unchecked
- "Autoplay" is set to "Block audio and video"
[ ] 3. Open about:policies and verify:
- All policies are "Active"
- Extensions are listed as "Force Installed"
[ ] 4. Test tab behavior:
- Press Ctrl+Tab and verify it cycles through recent tabs
- Hover over a tab and verify no image preview appears
[ ] 5. Test new tab/homepage:
- Open a new tab (Ctrl+T) - should be blank
- Open a new window (Ctrl+N) - should be blank
- No search bar, shortcuts, or widgets should appear
[ ] 6. Test search:
- Type in the address bar and verify no suggestions appear
- Search results should come from Kagi
- No other search engines should be available
- Sign in to Kagi account via Kagi extension for full features
[ ] 7. Test smooth scrolling:
- Scroll on a long page - should feel smooth and responsive
[ ] 8. Test permissions:
- Visit a site that requests location - should auto-block
- Visit a site that requests notifications - should auto-block
- Play a video with audio - should auto-block
MANUAL
print_info "Manual verification above requires user interaction"
# ============================================
# Troubleshooting Information
# ============================================
print_header "6. Troubleshooting Information"
echo "Useful Firefox URLs:"
print_info "about:policies - View active policies"
print_info "about:preferences - Firefox settings"
print_info "about:config - Advanced preferences"
print_info "about:support - Troubleshooting information"
print_info "about:addons - View/manage extensions"
print_info "about:preferences#privacy - Privacy settings"
echo ""
print_info "Configuration files:"
print_info " Policies: $POLICY_FILE"
print_info " Profile: $PROFILE"
print_info " user.js: $USER_JS"
if [[ -n "$PROFILE" ]]; then
print_info " search.json.mozlz4: $PROFILE/search.json.mozlz4"
fi
echo ""
print_info "To rebuild the configuration:"
print_info " nixos-rebuild switch"
echo ""
print_info "To restart Firefox:"
print_info " pkill firefox"
# ============================================
# Summary
# ============================================
print_header "Test Summary"
echo "Total tests: $TOTAL"
echo -e "${GREEN}Passed: $PASSED${NC}"
echo -e "${RED}Failed: $FAILED${NC}"
echo -e "${YELLOW}Skipped: $SKIPPED${NC}"
if [[ $FAILED -eq 0 ]]; then
echo ""
echo -e "${GREEN}✓ All automated tests passed!${NC}"
echo ""
echo "Please run Firefox once to install extensions via policy,"
echo "then complete the manual verification checklist above."
echo ""
echo "Note: Kagi search is the default and only search engine."
echo " Sign in to your Kagi account via the Kagi extension."
exit 0
else
echo ""
echo -e "${RED}✗ Some tests failed. Review the output above for details.${NC}"
exit 1
fi