1. Overview
BastionGuard Secure GUI is a GTK4/gtkmm front-end that allows the user to select a trusted payment/e-commerce domain from a configuration allowlist and launch the BastionGuard-secure sandboxed browsing flow as a subprocess. The GUI is designed as a lightweight selector/launcher and intentionally delegates security enforcement to the underlying secure entry point.
2. Primary Responsibilities
- Render a minimal GUI with consistent BastionGuard styling (sidebar + content).
- Load the payment allowlist from
~/.config/BastionGuard/payments.json("list"array). - Offer a dropdown selector for trusted domains.
- Launch the secure browsing flow by running
BastionGuard-secure <url>viaGio::Subprocess. - Terminate the sandbox subprocess on window close/cancel (best-effort SIGTERM).
- Initialize i18n early by loading language environment from
~/.config/BastionGuard/lang.conf.
3. Key Dependencies
- GTK4 / gtkmm:
Gtk::Window,Gtk::Box,Gtk::HeaderBar,Gtk::DropDown,Gtk::MessageDialogGtk::ApplicationGtk::StringList
- GIO / giomm:
Gio::Subprocessfor launching the secure sandbox entry point.wait_check_asyncfor non-blocking completion handling.
- gettext/glib i18n:
bindtextdomain,textdomain,_()
- nlohmann/json for parsing
payments.json. - Internal project utilities:
StyleProvider.hpp→load_style()Resource.hpp→resource(...)used to load embedded assets (icons, sidebar logo).
4. File/Config Contracts
4.1 Payments allowlist
The GUI loads payment domains from:
~/.config/BastionGuard/payments.json
Expected schema (minimum):
{
"list": [
"paypal.com",
"stripe.com"
]
}
If the file is missing or invalid, the GUI falls back to a default entry (paypal.com) to avoid an empty dropdown.
4.2 Language environment configuration
The GUI loads environment variables from:
~/.config/BastionGuard/lang.conf
Format:
LANG=it_IT.UTF-8
LC_ALL=it_IT.UTF-8
Each valid line is applied via setenv(key, val, 1) before calling setlocale() and initializing gettext.
5. UI Structure
5.1 Window characteristics
- Fixed-size window: 640×300 default
- Non-resizable
- Custom header bar with minimize/close icons
- Sidebar layout consistent with other BastionGuard windows
5.2 Widgets and layout
- Sidebar:
- Logo image:
resource("logo-sidebar.png") - Brand label: “BastionGuard”
- Logo image:
- Content area:
- Instruction label (translated via
_()) Gtk::DropDownpopulated byGtk::StringList- Hint label describing the config source (
payments.json) - Action buttons:
- Cancel
- Open in Secure Browser
- Instruction label (translated via
6. Domain Loading Logic
6.1 Path resolution
The payments config path is derived from:
Glib::get_user_config_dir() + "/BastionGuard/payments.json"
6.2 JSON validation rules
The loader enforces these conditions:
- The file must exist and be readable.
- The JSON root must be an object.
- The object must contain
"list"as an array. - Each element in
"list"must be a string.
If any validation step fails, the GUI logs warnings to stderr and returns an empty list (triggering fallback).
7. Secure Sandbox Launch Flow
7.1 Selection → URL construction
When the user clicks Open in Secure Browser:
- Read selected index from the dropdown.
- Validate index bounds.
- Read domain string and validate non-empty.
- Build URL as:
https://<domain>.
7.2 Subprocess execution
The secure flow is started via:
Gio::Subprocess::create({"BastionGuard-secure", url}, Gio::Subprocess::Flags::NONE)
Behavioral notes:
- The GUI disables itself (
set_sensitive(false)) during execution to avoid multiple launches. wait_check_asyncis used to avoid blocking the UI thread.- When the subprocess completes, the GUI hides itself (current behavior: close-on-finish).
8. Process Termination and Cleanup
8.1 Cancel button
- Calls
terminate_sandbox() - Hides the window
8.2 Window close path
on_close_request() overrides the close behavior and ensures:
terminate_sandbox()is called before returning control to GTK.
8.3 Termination strategy
The termination routine uses a best-effort approach:
- If a subprocess exists, send
SIGTERMviasend_signal(SIGTERM). - If this fails, attempt
force_exit()as fallback.
This is intended to avoid leaving orphaned secure browsing processes after the user closes the launcher UI.
9. Internationalization (i18n) Initialization Order
The program intentionally loads language configuration before gettext setup:
- Load
lang.confand callsetenv()for each key/value. - Apply locale via
std::setlocale(LC_ALL, ""). - Initialize gettext via:
bindtextdomain("BastionGuard", LOCALEDIR)bind_textdomain_codeset("BastionGuard", "UTF-8")textdomain("BastionGuard")
This prevents inconsistent translations caused by locale being applied after gettext initialization.
10. Styling and Assets
load_style()is called during application startup to apply the BastionGuard CSS theme.- Assets are loaded through the internal
resource()helper:logo-sidebar.pngicon-minimize.pngicon-close.png
11. Error Handling Strategy
- Non-fatal issues (missing icons, missing config, JSON errors) are logged to stderr and the UI continues with fallback behaviors.
- Launch errors (
Gio::Subprocess::createexceptions) show a modal warning dialog and re-enable the window. - Validation errors for selection/domain show a warning dialog and do not launch the subprocess.
12. Execution Summary
- Load language environment overrides (
lang.conf). - Initialize locale + gettext.
- Create GTK application and load global style.
- Show
SecureGuiWindow. - Load allowlisted domains from
payments.jsonand populate dropdown. - On Open: spawn
BastionGuard-securefor the selected domain viaGio::Subprocess. - On Cancel/Close: terminate subprocess best-effort and exit.