Skip to content

GX_HOME, so both halves can be pointed at the same library - #47

Merged
jpablo merged 1 commit into
viewerfrom
gx-home-override
Aug 21, 2026
Merged

GX_HOME, so both halves can be pointed at the same library#47
jpablo merged 1 commit into
viewerfrom
gx-home-override

Conversation

@jpablo

@jpablo jpablo commented Aug 21, 2026

Copy link
Copy Markdown
Owner

gx and the desktop could not be aimed at a library other than the real one — and worse, they disagreed about how to try.

resolves home via follows $HOME?
desktop dirs::home_dir()
gx user.home (GraalVM native image) ❌ — macOS reads the password database

So launching a desktop under a redirected $HOME and then asking gx about it silently asked about the real desktop.

Not hypothetical: it is what happened while verifying v0.9.4. The "end-to-end" check reported a ready desktop in 0.05s, and the only tell that it had measured the wrong machine was a brand-new sandbox library claiming six diagrams and a watched file it could not possibly have. A plausible number would have been believed.

What it does

GX_HOME replaces ~/.graph-explorer wholesale, and both sides read it. Both is the point — the runtime file names the socket for the library it belongs to, so a half-applied override splits them in a way nobody would think to look for. It also answers "keep a second library" and "use a throwaway one", neither of which had an answer.

GX_HOME=/tmp/scratch graph-explorer-desktop &
GX_HOME=/tmp/scratch gx status

Decisions worth naming

  • The variable names the data directory itself, not a home to nest a dot-directory inside. Putting .graph-explorer under a path you chose explicitly is the opposite of what naming one is for.
  • A blank value reads as unset. export GX_HOME="$SOMETHING" with SOMETHING unset is how a shell passes through an absent value; taken literally it would put the library at /library.
  • A relative value is absolutised. The library store decides whether a name escapes its directory by comparing paths, and gx deliberately takes its CWD from the user's shell.
  • Not a general home override. The access policy's denied roots (~/.ssh, ~/.gnupg, …) keep reading the true home on both sides, so relocating a library can never quietly un-deny a secret.

One resolver per side, both routed through it: LibraryStore.default now takes the GX home rather than the user's, so there is a single definition of where the data lives.

Testing

The decision is a pure function of (env, home) on both sides, so the rule is tested directly rather than through a process-global env var that would race every other test in the binary. Same four cases in GxHomeSpec and in main.rs.

Then verified with the real binaries, both pointed at one GX_HOME, catching the full sequence #46 made possible and this one made observable:

t= 0.03s  desktop: not running (only `gx open` needs it)
t= 0.06s  desktop: starting (its window is not up yet)
t= 0.33s  desktop: running (watching nothing)

— with the real library untouched throughout. That is the test that could not be written before this change.

Local on this exact base: gxCoreJVM 175, gxCli 61, Rust 40.

`gx` and the desktop could not be aimed at a library other than the real
one, and worse, they disagreed about how to try.

The desktop resolves its home through `dirs::home_dir()`, which follows
`$HOME`. `gx` is a GraalVM native image reading `user.home`, which on
macOS comes from the password database and ignores `$HOME` entirely. So
launching a desktop under a redirected `$HOME` and then asking `gx` about
it silently asked about the REAL desktop.

That is not hypothetical: it is what happened while verifying v0.9.4. The
"end-to-end" check reported a ready desktop in 0.05s, and the only tell
that it had measured the wrong machine was a brand-new sandbox library
claiming six diagrams and a watched file it could not possibly have. A
plausible number would have been believed.

`GX_HOME` replaces `~/.graph-explorer` wholesale, and BOTH sides read it.
Both is the point: the runtime file names the socket for the library it
belongs to, so a half-applied override splits them in a way nobody would
think to look for. It also answers "keep a second library" and "use a
throwaway one", neither of which had an answer.

Decisions worth naming:

  - The variable names the data directory itself, not a home to nest a
    dot-directory inside. Putting `.graph-explorer` under a path the
    caller chose explicitly is the opposite of what naming one is for.
  - A blank value reads as UNSET. `export GX_HOME="$SOMETHING"` with
    SOMETHING unset is how a shell passes through an absent value; taken
    literally it would put the library at `/library`.
  - A relative value is absolutised. The library store decides whether a
    name escapes its directory by comparing paths, and `gx` deliberately
    takes its CWD from the user's shell.
  - It is NOT a general home override. The access policy's denied roots
    (`~/.ssh`, `~/.gnupg`, ...) keep reading the true home on both sides,
    so relocating a library can never quietly un-deny a secret.

One resolver per side, both routed through: LibraryStore.default now takes
the GX home rather than the user's, so there is a single definition of
where the data lives.

The decision is a pure function of (env, home) on both sides, so the rule
is tested directly rather than through a process-global env var that would
race every other test in the binary. Same four cases in GxHomeSpec and in
main.rs.

Verified with the real binaries, both pointed at one GX_HOME, catching the
full sequence the previous PR made possible and this one made observable:

    t= 0.03s  desktop: not running (only `gx open` needs it)
    t= 0.06s  desktop: starting (its window is not up yet)
    t= 0.33s  desktop: running (watching nothing)

and the real library untouched throughout. That is the test that could not
be written before this change.
@netlify

netlify Bot commented Aug 21, 2026

Copy link
Copy Markdown

Deploy Preview for graph-explorer-net ready!

Name Link
🔨 Latest commit b631d64
🔍 Latest deploy log https://app.netlify.com/projects/graph-explorer-net/deploys/6a87c1b035882b0007aa4bde
😎 Deploy Preview https://deploy-preview-47--graph-explorer-net.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@jpablo
jpablo merged commit 5c47c36 into viewer Aug 21, 2026
13 checks passed
@jpablo
jpablo deleted the gx-home-override branch August 21, 2026 06:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant