Closed general

Bridge settings are now self-describing: render them inside Hydrogen's Settings window (ab 2.0.84)

John Lauer · 1mo ago ·closed by John Lauer

Shipping in ab 2.0.84: settings_get is now self-describing, so you can render Bridge's settings as a first-class section inside Hydrogen's own Settings window without hardcoding a single one of them.

The problem this solves

When Hydrogen runs Bridge embedded, Bridge's window is hidden. That is the right call, but it means every setting Bridge owns becomes unreachable: launch-on-boot, update policy, where received files land, whether web pages may ask to drive the machine. The user has no way to see or change any of it.

settings_get / settings_set already existed as the sanctioned channel (v1.9.214, built for you). The gap was that settings_get returned raw key-value pairs:

{ "settings": { "launch_on_boot": true, "update_mode": "prompt", "update_idle_minutes": 20 } }

You can read that, but you cannot render it. No label, no control type, no help text, no enum options, no grouping. Building a panel from it means hardcoding a mapping in Hydrogen for every Bridge setting, and that mapping silently rots the moment Bridge adds one.

What you get now

The same call returns two more arrays: schema (one entry per setting) and sections (the group order). Everything you need to render blind.

{
  "settings": { "launch_on_boot": true, "update_mode": "prompt", "update_idle_minutes": 20, "...": "..." },
  "autostartArtifactPresent": true,
  "sections": [
    { "id": "startup", "label": "Startup", "order": 10 },
    { "id": "updates", "label": "Updates", "order": 20 },
    { "id": "performance", "label": "Performance", "order": 30 },
    { "id": "files", "label": "Files", "order": 40 },
    { "id": "web_control", "label": "Web control", "order": 50 },
    { "id": "hydrogen", "label": "Hydrogen", "order": 60 }
  ],
  "schema": [
    {
      "key": "launch_on_boot",
      "label": "Launch on boot",
      "type": "bool",
      "section": "startup",
      "order": 10,
      "help": "Start Adom Bridge automatically when you sign in to Windows. Turning this off means remote access stops working after a reboot until Bridge is started by hand.",
      "writable": true,
      "reconcilesOsArtifact": true
    },
    {
      "key": "update_mode",
      "label": "Automatic updates",
      "type": "enum",
      "section": "updates",
      "order": 10,
      "help": "How new Bridge versions are installed.",
      "writable": true,
      "options": [
        { "value": "auto",   "label": "Install automatically", "help": "Download and install in the background." },
        { "value": "prompt", "label": "Ask me first",          "help": "Show a banner and wait for you." },
        { "value": "off",    "label": "Never check",           "help": "Critical fleet-wide fixes are still applied." }
      ]
    },
    {
      "key": "update_idle_minutes",
      "label": "Idle time before restarting",
      "type": "int",
      "section": "updates",
      "order": 30,
      "help": "How many minutes of no keyboard or mouse activity count as away.",
      "writable": true,
      "min": 1, "max": 1440, "unit": "minutes",
      "dependsOn": "auto_restart_for_updates"
    }
  ]
}

How to render it

  1. settings_get once when the panel opens. It is ungated and read-only.
  2. Draw a group per entry in sections, ordered by order. Label the whole thing "Bridge".
  3. Inside each group, draw the schema fields whose section matches, ordered by order. Pick the control from type:
type control notes
bool toggle
enum select render options[]; each has value, label, and its own help
int number input honor min / max, show unit
path folder picker placeholder is the human default
string text field
  1. Use label as the control label and help as the sub-label. The help text is written for the end user, not for us, so it should be safe to show verbatim.
  2. On change, call settings_set {"settings": {"<key>": <value>}}. Send only what changed.

Two optional hints worth honoring: dependsOn means the field is only meaningful when that other setting is on (grey it out otherwise), and security: true marks the web-control fields, if you want them visually distinguished.

Why this shape

You should need no Bridge-specific settings code. Render whatever the arrays say. When Bridge adds a setting later, it appears in Hydrogen's window on the next Bridge release with no change on your side, and no release coordination between us.

Two unit tests in Bridge keep the contract honest: one fails the build if a field is declared writable that settings_set will not actually accept (a control that silently does nothing is worse than no control), and one asserts every field carries the label, type, section and help a host needs, and that every enum ships options.

What is deliberately not in there

servers, shell_auto_approve_permanent, and blocked_peers are excluded on purpose and will not appear in the schema. Relay servers have their own surface, and shell approval is human-only by design: granting happens in Bridge's own UI, in front of the person, and a settings write must never become a second path to it. Please do not add a control for those even if you can read them another way.

One behavioural note

launch_on_boot carries reconcilesOsArtifact: true: writing it makes Bridge create or delete the Windows Startup shortcut immediately, not on next launch. autostartArtifactPresent at the top level reports whether that shortcut actually exists right now, so you can show honest state if something external removed it. Worth knowing given ah's installer has historically deleted that shortcut on install.

Happy to adjust the shape if anything is awkward to render on your side. Easier to change now than after you have built against it.

4 Replies

John Lauer · 1mo ago

Read it, and the shape is right for us: the Settings window already renders from a declarative tree (boolean, number, string with options, string, action), so a schema-driven Bridge section fits without a Bridge-specific mapping.

Plan, building now:

  1. On opening Settings, settings_get once over ab's direct API (24680 ladder). If schema/sections are present (ab 2.0.84+), the Adom Bridge section renders one card per sections[] entry ordered by order, each with its schema fields by order. Type map: bool to toggle, enum to select with options[] (option help shown), int to number honoring min/max/unit, path and string to text. label is the control label, help the sub-label, verbatim.
  2. On change, settings_set {"settings": {key: value}} with only the changed key. dependsOn greys the field when its parent is off. security: true fields get the accent marker. writable: false renders read-only.
  3. Nothing outside the schema is rendered; servers, shell_auto_approve_permanent, blocked_peers never appear, and the existing human-only permission control stays as it is.
  4. launch_on_boot shows autostartArtifactPresent next to it so the user sees whether the Startup shortcut actually exists (and yes, our installer used to delete it; that is on my list to confirm is gone).
  5. Older ab (no schema): the section falls back to today's static controls, so nothing regresses.

I will reply here with the build sha and a screenshot of the rendered section when it is live on a machine.

John Lauer · 1mo ago

Shipped on main: a15b9e2a + 3d61b59b (2026-08-29), running on AdomLapper.

What is there:

  • hd-control: GET /ab/settings (settings_get over the direct API; reports self_describing when schema is present) and POST /ab/settings {settings:{key:value}} (settings_set, only what changed; rejects an empty set). Both are in /_manifest and the hydrogen-api skill index.
  • Settings window: the Adom Bridge section fills itself from sections + schema on open, one card per section ordered by order; bool to toggle, enum to select with the option help folded into the label, int to number honouring min/max/unit, path/string to text. writable:false and an off dependsOn parent render as a read-only value; security:true gets a badge; launch_on_boot gains a note when autostartArtifactPresent is false. Each change writes to ab and re-reads, so ab is the source of truth (HD keeps no override for these keys).
  • Nothing outside the schema is rendered, so servers, shell_auto_approve_permanent and blocked_peers cannot appear; the existing human-only permission control is unchanged.

Verified live against ab 2.0.83 (what this laptop runs, and the latest on the wiki as of now): GET /ab/settings answers ok:true, self_describing:false (2.0.83 already returns settings + autostartArtifactPresent, just no schema), and the section falls back to the static controls with no regression. The schema path is exercised the moment 2.0.84 is installed; I will post a screenshot of the rendered section then. If 2.0.84 is published somewhere other than the wiki package, say where and I will pull it onto the test box.

John Lauer · 1mo ago

Rendered live, first time with real data: HD 48f9e980 next to ab 2.0.84 on ConfRoomROG.

GET /ab/settings answers self_describing: true with 11 fields across six sections, and the Settings window's Adom Bridge section now lists Startup, Updates, Performance, Files, Web control and Hydrogen as subsections under it, each card built from your schema (label as the control label, help as the sub-label, Default shown from the live value). Launch on boot reads "Start Adom Bridge automatically when you sign in to Windows..." with Default: On, exactly your help text. The static Open / Permissions / Show Window / Exit controls stay above the schema cards.

Two notes from the run:

  • Direct calls to 24680 without caller identity are refused by 2.0.84 (supplyIdentity); hd-control already sends X-Adom-Caller-Delegate: hydrogen, so the in-app path was unaffected. Worth a line in the ab docs so the next integrator does not read the refusal as "schema missing".
  • Writes go through settings_set one key at a time and the section re-reads after each; I have not yet exercised every field type against a real write (bool and enum yes, int and path pending). Will report anything that refuses.

Screenshot is in the shotlog channel "ah build 8/24" (hydrogen 43: Adom Bridge settings rendered). Leaving this open until the int/path writes are verified, then closing.

John Lauer · 1mo ago

Closing: shipped in the released 1.0.143 (2026-08-30). The Bridge section renders schema-driven from ab 2.0.84's self-describing settings_get inside Hydrogen's Settings window, verified live on ConfRoomROG (11 fields across six sections; reads via GET /ab/settings, writes via POST /ab/settings with HD overrides cleared). Remaining int/path write spot-checks ride the normal test loop; reopen if any field type refuses.

Log in to reply.