detached b200f6b

fix(runtime): make dev IPC checks CI-safe

commit
b200f6b1e2a559bf3c31857064d780107255fb24
author
brice · · 2026-06-26 15:39 UTC
parent
b13ad36
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
2 files · +14 -5
M internal/infrastructure/config/xdg_test.go +7 -0
@@ -1,6 +1,7 @@
11 package config
22
33 import (
4+ "os"
45 "path/filepath"
56 "testing"
67
@@ -29,6 +30,12 @@ func TestGetXDGDirs_DevUsesSharedSandboxLayout(t *testing.T) {
2930 t.Chdir(wd)
3031
3132 t.Setenv("ENV", "dev")
33+ runtimeDir, err := os.MkdirTemp("", "dbr-")
34+ require.NoError(t, err)
35+ t.Cleanup(func() {
36+ _ = os.RemoveAll(runtimeDir)
37+ })
38+ t.Setenv("XDG_RUNTIME_DIR", runtimeDir)
3239 dirs, err := GetXDGDirs()
3340 require.NoError(t, err)
3441 require.Equal(t, filepath.Join(wd, ".dev", appName, "config"), dirs.ConfigHome)
@@ -1,6 +1,7 @@
1 package config1 package config
2 2
3 import (3 import (
4+ "os"
4 "path/filepath"5 "path/filepath"
5 "testing"6 "testing"
6 7
@@ -29,6 +30,12 @@ func TestGetXDGDirs_DevUsesSharedSandboxLayout(t *testing.T) {
29 t.Chdir(wd)30 t.Chdir(wd)
30 31
31 t.Setenv("ENV", "dev")32 t.Setenv("ENV", "dev")
33+ runtimeDir, err := os.MkdirTemp("", "dbr-")
34+ require.NoError(t, err)
35+ t.Cleanup(func() {
36+ _ = os.RemoveAll(runtimeDir)
37+ })
38+ t.Setenv("XDG_RUNTIME_DIR", runtimeDir)
32 dirs, err := GetXDGDirs()39 dirs, err := GetXDGDirs()
33 require.NoError(t, err)40 require.NoError(t, err)
34 require.Equal(t, filepath.Join(wd, ".dev", appName, "config"), dirs.ConfigHome)41 require.Equal(t, filepath.Join(wd, ".dev", appName, "config"), dirs.ConfigHome)
M internal/infrastructure/desktop/browser_launch_relay.go +7 -5
@@ -187,7 +187,8 @@ func setBrowserLaunchConnDeadline(ctx context.Context, conn net.Conn) error {
187187 }
188188
189189 func validateBrowserLaunchSocketDirOwned(socketPath string, expectedUID uint32) error {
190- for dir := filepath.Dir(socketPath); ; dir = filepath.Dir(dir) {
190+ socketDir := filepath.Dir(socketPath)
191+ for dir := socketDir; ; dir = filepath.Dir(dir) {
191192 info, err := os.Stat(dir)
192193 if err != nil {
193194 return fmt.Errorf("stat browser launch dir: %w", err)
@@ -196,13 +197,14 @@ func validateBrowserLaunchSocketDirOwned(socketPath string, expectedUID uint32)
196197 if !ok {
197198 return nil
198199 }
200+
201+ isSocketDir := dir == socketDir
199202 if stat.Uid != expectedUID {
200- if stat.Uid == 0 {
201- return nil
203+ if isSocketDir || stat.Uid != 0 {
204+ return fmt.Errorf("browser launch dir owner mismatch: %s owned by uid %d, want uid %d", dir, stat.Uid, expectedUID)
202205 }
203- return fmt.Errorf("browser launch dir owner mismatch: %s owned by uid %d, want uid %d", dir, stat.Uid, expectedUID)
204206 }
205- if info.Mode().Perm()&0o022 != 0 {
207+ if info.Mode().Perm()&0o022 != 0 && (isSocketDir || info.Mode()&os.ModeSticky == 0) {
206208 return fmt.Errorf("browser launch dir permissions too broad: %s has mode %04o", dir, info.Mode().Perm())
207209 }
208210 if parent := filepath.Dir(dir); parent == dir {
@@ -187,7 +187,8 @@ func setBrowserLaunchConnDeadline(ctx context.Context, conn net.Conn) error {
187 }187 }
188 188
189 func validateBrowserLaunchSocketDirOwned(socketPath string, expectedUID uint32) error {189 func validateBrowserLaunchSocketDirOwned(socketPath string, expectedUID uint32) error {
190- for dir := filepath.Dir(socketPath); ; dir = filepath.Dir(dir) {190+ socketDir := filepath.Dir(socketPath)
191+ for dir := socketDir; ; dir = filepath.Dir(dir) {
191 info, err := os.Stat(dir)192 info, err := os.Stat(dir)
192 if err != nil {193 if err != nil {
193 return fmt.Errorf("stat browser launch dir: %w", err)194 return fmt.Errorf("stat browser launch dir: %w", err)
@@ -196,13 +197,14 @@ func validateBrowserLaunchSocketDirOwned(socketPath string, expectedUID uint32)
196 if !ok {197 if !ok {
197 return nil198 return nil
198 }199 }
200+
201+ isSocketDir := dir == socketDir
199 if stat.Uid != expectedUID {202 if stat.Uid != expectedUID {
200- if stat.Uid == 0 {203+ if isSocketDir || stat.Uid != 0 {
201- return nil204+ return fmt.Errorf("browser launch dir owner mismatch: %s owned by uid %d, want uid %d", dir, stat.Uid, expectedUID)
202 }205 }
203- return fmt.Errorf("browser launch dir owner mismatch: %s owned by uid %d, want uid %d", dir, stat.Uid, expectedUID)
204 }206 }
205- if info.Mode().Perm()&0o022 != 0 {207+ if info.Mode().Perm()&0o022 != 0 && (isSocketDir || info.Mode()&os.ModeSticky == 0) {
206 return fmt.Errorf("browser launch dir permissions too broad: %s has mode %04o", dir, info.Mode().Perm())208 return fmt.Errorf("browser launch dir permissions too broad: %s has mode %04o", dir, info.Mode().Perm())
207 }209 }
208 if parent := filepath.Dir(dir); parent == dir {210 if parent := filepath.Dir(dir); parent == dir {

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close