Login Dialog Label Filter

Table of Contents

Problem

The login dialog's saved-connections combo is a flat list that shows every server bookmark and every connection, making it hard to find what you need when there are many entries spanning different servers.

In practice a developer running from a local1 checkout is almost exclusively interested in connections pointing at local1. The same concept applies to any end-user context: a prod user wants prod connections, a barclays user wants Barclays-tagged connections. Surfacing everything at once adds friction.

A second gap: there is no reliable signal telling the application which checkout it was started from, so no automatic pre-selection is possible.

Both problems share a root: connections and environments have no first-class label that the login dialog can filter on. The tag system already exists in the database; it just needs a filter surface in the dialog, auto-population at startup, and an env-var hook to pre-select the right label.

Terminology

Term Meaning
Environment A server bookmark (host + port, no credentials).
  Unchanged from current domain model.
Connection Saved credentials linked to an environment.
Tag / Label An arbitrary string attached to environments.
  Used here as the filter axis.
Checkout label The ORES_CHECKOUT_LABEL env var — identifies the current
  development checkout (e.g. local1, local2).

The domain model (environment, connection, folder, tag) is not renamed or restructured in this story. The terminology clean-up proposed in the original plan (environment → instance, new tier concept) is deferred to a later story.

Current State

Database

The tags and environment_tags tables already exist. Typical content:

tags dev, local, acme, example
env tags all environments tagged "dev" and "local"

What is missing: each environment has no label identifying which checkout it belongs to (e.g. local1, local2). There are no tags at that granularity.

ORES_CHECKOUT_LABEL

.env (generated by init-environment.sh) sets ORES_CHECKOUT_LABEL=local1. The variable is already exported and available to child processes launched from start-client.sh, but the Qt application does not currently read it.

Connection browser

Tags are already visible in the connection browser. The browser can be used to add or remove tags manually. This story automates the checkout-label tagging.

Login dialog

The quick-connect combo is a flat, unfiltered list. No filter control exists.

Design

Auto-tag environments at startup

When ORES_CHECKOUT_LABEL is set (e.g. local1), the application automatically ensures that:

  1. A tag named local1 exists in the tags table (created if absent).
  2. Every environment whose subject_prefix ends with .local1 is tagged with local1. The subject prefix format is ores.{tier}.{instance}, so the last dot-separated component is the instance/checkout name.

This is idempotent — restarting the app with the same label is safe. It requires a new connection_manager method:

/**
 * Ensure tag @p label exists and is applied to every environment whose
 * subject_prefix ends with ".{label}".  No-op if @p label is empty.
 */
void auto_tag_environments_by_label(const std::string& label);

Login dialog filter combo

A Label filter row appears above the quick-connect combo:

Label: [ All ▼ ]    ← hidden when fewer than 2 tags exist
Quick connect: [ ── ▼ ]

Filter options: "All", then each tag sorted alphabetically. An entry appears only when at least one environment carries that tag.

When a label is selected:

  • Environments section: only environments carrying that tag are shown.
  • Connections section: only connections whose linked environment carries that tag are shown.

The filter is purely a narrowing control; it does not fill form fields.

QuickConnectItem additions

struct QuickConnectItem {
    enum class Type { Environment, Connection };
    Type    type;
    QString name;
    QString subtitle;
    // ── new ──
    QStringList tags;   // tags on the linked environment
};

MainWindow populates tags for each item by calling get_tags_for_environment(environment_id) when building the combo list.

ORES_CHECKOUT_LABEL env-var pre-selection

MainWindow reads std::getenv("ORES_CHECKOUT_LABEL") after the connection manager is initialised:

  1. Call auto_tag_environments_by_label(label) to ensure the tag exists.
  2. Call login_dialog.setActiveLabel(QString::fromStdString(label)) to pre-select the filter.
  3. Store the label for display purposes (see window title, below).

If the variable is unset or empty, the filter defaults to "All" and no auto-tagging occurs.

Window label display

When a checkout label is active, append it in curly braces to the window title and toolbar (optional, can be done in the same or a follow-up PR):

ORE Studio v1.2.3              (no label)
ORE Studio v1.2.3 {local1}    (ORES_CHECKOUT_LABEL=local1)

start-client.sh env-var check

After sourcing .env, the script checks that ORES_CHECKOUT_LABEL is set. Because the variable was introduced in a specific version of init-environment.sh, its absence signals a stale .env:

if [[ -z "${ORES_CHECKOUT_LABEL:-}" ]]; then
    echo "warning: ORES_CHECKOUT_LABEL is not set in .env"
    echo "         Your .env may be out of date — consider re-running:"
    echo "           ./build/scripts/init-environment.sh --preset <preset>"
fi

The variable reaches ores.qt automatically via the exported environment; no extra CLI flag is needed.

Non-goals

  • Renaming environmentinstance in the domain model (deferred).
  • Introducing a first-class deployment-tier concept (deferred).
  • Rebuilding the connection browser tree (deferred).
  • Persisting the last-used filter across sessions.
  • CLI flag for the label (the env var is sufficient; a flag can be added later).

Implementation

Item 1 — start-client.sh: add env-var check

File: build/scripts/start-client.sh. After sourcing .env and resolving PRESET, warn if ORES_CHECKOUT_LABEL is unset.

Item 2 — connection_manager: auto_tag_environments_by_label()

Files: connection_manager.hpp, connection_manager.cpp. Implementation:

  • If label is empty, return immediately.
  • Call get_tag_by_name(label); create tag if absent.
  • Call get_all_environments(); for each environment whose subject_prefix ends with ".{label}", call add_tag_to_environment(env.id, tag.id) (no-op if already tagged).

Item 3 — QuickConnectItem: add tags field

File: LoginDialog.hpp. Add QStringList tags to the struct.

Item 4 — MainWindow: populate tags and read env var

File: MainWindow.cpp.

  • In the method that builds the quick-connect list, call get_tags_for_environment() for each environment and populate the tags field.
  • After initializeConnectionManager() succeeds, read ORES_CHECKOUT_LABEL, call auto_tag_environments_by_label(), and pass the label to the login dialog.

Item 5 — LoginDialog: add filter combo

Files: LoginDialog.hpp, LoginDialog.cpp.

  • Add QLabel* labelFilterLabel_ and QComboBox* labelFilterCombo_.
  • Both hidden when the tag list has fewer than 2 entries.
  • setActiveLabel(const QString& label) public method — selects the entry in the combo (or "All" if not found).
  • onLabelFilterChanged() private slot — rebuilds the visible quick-connect list from the cached full list.
  • Full item list cached; visible list filtered in the slot.

Item 6 — Tests

Update service_connection_manager_tests.cpp with a test for auto_tag_environments_by_label: create environments with known subject_prefix values, call the method, verify tags are applied.

Date: 2026-05-15

Emacs 29.1 (Org mode 9.6.6)