Clone
1
Architecture
Pavel Baksy edited this page 2026-01-13 17:08:01 +01:00
Architecture
Technical overview of Roster's architecture.
Technology Stack
Core Technologies
- GTK 4 - UI toolkit
- libadwaita - GNOME design patterns and widgets
- Python 3 - Application logic
- libsoup3 - HTTP client (from GNOME Platform)
- libsecret - Credential storage via GNOME Keyring
- GJS - JavaScript runtime for scripts
Build System
- Meson - Build configuration
- GResources - Bundle UI files and assets
Application Structure
Main Components
RosterApplication (main.py)
- Singleton application class inheriting from
Adw.Application - Manages application lifecycle
- Handles global actions (quit, about, preferences)
- Creates and presents main window
RosterWindow (window.py)
- Main application window inheriting from
Adw.ApplicationWindow - GTK template class with UI from
window.ui - Manages tabs, requests, and responses
- Coordinates HTTP operations
UI Architecture
Template-based UI:
- UI defined in XML files (GTK Builder format)
- Loaded via GResources at runtime
@Gtk.Templatedecorator binds Python class to UIGtk.Template.Child()accesses widgets from template
Resource Management:
- UI files defined in
src/roster.gresource.xml - Compiled into binary bundle during build
- Base path:
/cz/bugsy/roster
Data Flow
HTTP Request Flow
User Input → Request Configuration → Variable Substitution →
Preprocessing Script → HTTP Request (libsoup3) → Response →
Postprocessing Script → Display Response → Save to History
Variable Substitution
- User enters
{{variable_name}}in request - Current environment selected from dropdown
- Variable value retrieved (from JSON or Keyring)
- Placeholder replaced with actual value
- Request sent with substituted values
Script Execution
Preprocessing:
- Load script from request
- Create JavaScript context (GJS)
- Inject
request,roster,consoleobjects - Execute script synchronously
- Apply modifications to request object
Postprocessing:
- Load script from request
- Create JavaScript context (GJS)
- Inject
response,roster,consoleobjects - Execute script synchronously
- Variables updated via
roster.setVariable()
Data Storage
File Locations
Native:
~/.local/share/cz.bugsy.roster/
├── requests.json # Projects, environments, regular variables
└── session.json # History, window state
Flatpak:
~/.var/app/cz.bugsy.roster/data/cz.bugsy.roster/
├── requests.json
└── session.json
Data Format
requests.json:
{
"projects": [
{
"id": "uuid",
"name": "Project Name",
"icon": "icon-name",
"environments": [
{
"id": "uuid",
"name": "Production",
"variables": {
"base_url": "https://api.example.com",
"api_key": "" // Empty if sensitive
}
}
],
"requests": [
{
"id": "uuid",
"name": "Get Users",
"method": "GET",
"url": "{{base_url}}/users",
"headers": {},
"body": "",
"preprocessing_script": "",
"postprocessing_script": ""
}
]
}
]
}
Sensitive Variables
Stored in GNOME Keyring with schema:
- Schema:
cz.bugsy.roster.EnvironmentVariable - Attributes:
project_id,environment_id,variable_name - Secret: Variable value (encrypted)
Key Design Patterns
Singleton Application
Single instance ensured by Adw.Application. Attempting to launch a second instance activates the existing window.
Template Classes
UI components use GTK template pattern:
@Gtk.Template(resource_path='/cz/bugsy/roster/window.ui')
class RosterWindow(Adw.ApplicationWindow):
__gtype_name__ = 'RosterWindow'
url_entry = Gtk.Template.Child()
method_dropdown = Gtk.Template.Child()
Actions
Application and window actions follow GNOME conventions:
action = Gio.SimpleAction.new("quit", None)
action.connect("activate", self.on_quit)
self.add_action(action)
self.set_accels_for_action("app.quit", ["<Ctrl>Q"])
HTTP Client
Uses libsoup3 (from GNOME Platform):
- Asynchronous HTTP requests
- Automatic redirect handling
- Cookie management
- SSL/TLS support
- HTTP/2 support
Internationalization
Uses gettext for translations:
- Domain: "roster"
- Template files (
.in) processed by Meson i18n.merge_file()generates localized files- Translations in
po/directory
Security Model
Sandboxing (Flatpak)
Permissions required:
--share=network- HTTP requests--talk-name=org.freedesktop.secrets- GNOME Keyring access--filesystem=xdg-data/cz.bugsy.roster- Data directory
Script Sandboxing
Scripts run in isolated GJS context:
- No file system access
- No network access (except main request)
- No process execution
- Only whitelisted APIs available
Next Steps
- Development - Developer setup and workflow
- Contributing - Contribution guidelines