Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions .github/workflows/workstation-keyboard-policy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
name: workstation-keyboard-policy

on:
pull_request:
paths:
- 'profiles/linux-dev/workstation-v0/bin/check-keyboard-policy.sh'
- 'profiles/linux-dev/workstation-v0/gnome/input-install.sh'
- 'profiles/linux-dev/workstation-v0/gnome/README.md'
- 'profiles/linux-dev/workstation-v0/manifest.yaml'
- '.github/workflows/workstation-keyboard-policy.yml'
push:
branches:
- main
paths:
- 'profiles/linux-dev/workstation-v0/bin/check-keyboard-policy.sh'
- 'profiles/linux-dev/workstation-v0/gnome/input-install.sh'
- 'profiles/linux-dev/workstation-v0/gnome/README.md'
- 'profiles/linux-dev/workstation-v0/manifest.yaml'
- '.github/workflows/workstation-keyboard-policy.yml'

jobs:
keyboard-policy-smoke:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Syntax check keyboard policy scripts
run: |
set -euo pipefail
bash -n profiles/linux-dev/workstation-v0/bin/check-keyboard-policy.sh
bash -n profiles/linux-dev/workstation-v0/gnome/input-install.sh

- name: Smoke: keyboard policy helper default backend
run: |
set -euo pipefail
helper='profiles/linux-dev/workstation-v0/bin/check-keyboard-policy.sh'
tmp_home=$(mktemp -d)
out=$(HOME="$tmp_home" XDG_CONFIG_HOME="$tmp_home/.config" bash "$helper")
grep -F 'default_backend=input-remapper' <<<"$out" >/dev/null
grep -F 'primary_backend=input-remapper' <<<"$out" >/dev/null
grep -F 'compatibility_backends=xremap,kinto' <<<"$out" >/dev/null
grep -F 'wayland_first=yes' <<<"$out" >/dev/null
grep -F 'kinto_auto_install=no' <<<"$out" >/dev/null
grep -F 'selected_backend=input-remapper' <<<"$out" >/dev/null
grep -F 'backend_valid=yes' <<<"$out" >/dev/null
grep -F 'selected_backend_available=missing' <<<"$out" >/dev/null
grep -F 'input_installer=present' <<<"$out" >/dev/null
grep -F 'policy_ok=yes' <<<"$out" >/dev/null

- name: Smoke: keyboard policy helper detects selected backend availability
run: |
set -euo pipefail
helper='profiles/linux-dev/workstation-v0/bin/check-keyboard-policy.sh'
tmp_home=$(mktemp -d)
stub_bin=$(mktemp -d)
cat > "$stub_bin/input-remapper-control" <<'EOF'
#!/usr/bin/env bash
exit 0
EOF
chmod +x "$stub_bin/input-remapper-control"
out=$(HOME="$tmp_home" XDG_CONFIG_HOME="$tmp_home/.config" PATH="$stub_bin:$PATH" bash "$helper")
grep -F 'input_remapper=present' <<<"$out" >/dev/null
grep -F 'selected_backend_available=present' <<<"$out" >/dev/null
grep -F 'policy_ok=yes' <<<"$out" >/dev/null

- name: Smoke: keyboard policy helper rejects invalid backend
run: |
set -euo pipefail
helper='profiles/linux-dev/workstation-v0/bin/check-keyboard-policy.sh'
tmp_home=$(mktemp -d)
out=$(HOME="$tmp_home" XDG_CONFIG_HOME="$tmp_home/.config" SOURCEOS_REMAP_BACKEND=invalid bash "$helper")
grep -F 'selected_backend=invalid' <<<"$out" >/dev/null
grep -F 'backend_valid=no' <<<"$out" >/dev/null
grep -F 'selected_backend_available=invalid' <<<"$out" >/dev/null
grep -F 'policy_ok=no' <<<"$out" >/dev/null

- name: Smoke: input installer writes xremap template in compatibility mode
run: |
set -euo pipefail
installer='profiles/linux-dev/workstation-v0/gnome/input-install.sh'
tmp_home=$(mktemp -d)
HOME="$tmp_home" XDG_CONFIG_HOME="$tmp_home/.config" XDG_CURRENT_DESKTOP=GNOME SOURCEOS_REMAP_BACKEND=xremap bash "$installer"
tmpl="$tmp_home/.config/sourceos/input/xremap-macos-compat.yml"
test -s "$tmpl"
grep -F 'CapsLock: Esc' "$tmpl" >/dev/null
grep -F 'Control_L: Super_L' "$tmpl" >/dev/null
grep -F 'Super_L: Alt_L' "$tmpl" >/dev/null
grep -F 'Alt_L: Control_L' "$tmpl" >/dev/null
grep -F 'Control_R: Super_R' "$tmpl" >/dev/null
grep -F 'Super_R: Alt_R' "$tmpl" >/dev/null
grep -F 'Alt_R: Control_R' "$tmpl" >/dev/null
96 changes: 96 additions & 0 deletions profiles/linux-dev/workstation-v0/bin/check-keyboard-policy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#!/usr/bin/env bash
set -euo pipefail

# Validate workstation-v0 keyboard/remap policy without requiring root access.
# Emits key=value lines for doctor/status or CI consumption.

have(){ command -v "$1" >/dev/null 2>&1; }

profile_dir(){
cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd
}

backend(){
printf '%s\n' "${SOURCEOS_REMAP_BACKEND:-input-remapper}"
}

template_path(){
printf '%s/sourceos/input/xremap-macos-compat.yml\n' "${XDG_CONFIG_HOME:-$HOME/.config}"
}

present_or_missing(){
if have "$1"; then
printf 'present\n'
else
printf 'missing\n'
fi
}

main(){
local pdir b tmpl backend_valid input_remapper xremap_bin xkeysnail selected_available policy_ok
pdir="$(profile_dir)"
b="$(backend)"
tmpl="$(template_path)"
backend_valid=no
selected_available=unknown
policy_ok=no

printf 'profile_dir=%s\n' "$pdir"
printf 'default_backend=input-remapper\n'
printf 'primary_backend=input-remapper\n'
printf 'compatibility_backends=xremap,kinto\n'
printf 'wayland_first=yes\n'
printf 'kinto_auto_install=no\n'
printf 'selected_backend=%s\n' "$b"

case "$b" in
input-remapper|xremap|kinto)
backend_valid=yes
;;
esac
printf 'backend_valid=%s\n' "$backend_valid"

input_remapper="$(present_or_missing input-remapper-control)"
xremap_bin="$(present_or_missing xremap)"
xkeysnail="$(present_or_missing xkeysnail)"

printf 'input_remapper=%s\n' "$input_remapper"
printf 'xremap=%s\n' "$xremap_bin"
printf 'xkeysnail=%s\n' "$xkeysnail"

case "$b" in
input-remapper)
selected_available="$input_remapper"
;;
xremap)
selected_available="$xremap_bin"
;;
kinto)
selected_available="$xkeysnail"
;;
*)
selected_available=invalid
;;
esac
printf 'selected_backend_available=%s\n' "$selected_available"

if [[ -f "$tmpl" ]]; then
printf 'xremap_template=present\n'
else
printf 'xremap_template=missing\n'
fi
printf 'xremap_template_path=%s\n' "$tmpl"

if [[ -f "$pdir/gnome/input-install.sh" ]]; then
printf 'input_installer=present\n'
else
printf 'input_installer=missing\n'
fi

if [[ "$backend_valid" == "yes" ]]; then
policy_ok=yes
fi
printf 'policy_ok=%s\n' "$policy_ok"
}

main "$@"
10 changes: 10 additions & 0 deletions profiles/linux-dev/workstation-v0/gnome/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Principles:
./appearance-apply.sh
./files-sidebar.sh
./mac-defaults.sh
./input-install.sh
```

## Current baseline (v0)
Expand Down Expand Up @@ -49,6 +50,15 @@ This lane adds bounded visual/workflow polish without replacing GNOME Shell or l
- `files-sidebar.sh` seeds GTK/Nautilus bookmarks for Desktop, Documents, Downloads, Pictures, Screenshots, Music, Videos, and Public.
- The workstation installer runs both helpers best-effort after the extension pinset and before input/gesture setup.

## Keyboard/remap policy v1

The workstation keeps keyboard remapping explicit and policy-gated:

- `input-remapper` remains the default Fedora/GNOME backend because it is packaged and works at the evdev layer.
- `xremap` is the advanced compatibility lane; the installer writes a template at `$XDG_CONFIG_HOME/sourceos/input/xremap-macos-compat.yml`.
- Kinto remains an explicit compatibility lane for X11/xkeysnail-style workflows and is not auto-installed in the Wayland-first profile.
- `check-keyboard-policy.sh` emits key=value status for CI and future doctor/status integration.

## Follow-on work

- Wayland-safe keyboard remap lane expansion
Expand Down