{# SETTINGS · System page (R4a, FUNCTIONAL). A schema-driven editor over the console-local settings store (app-DB canonical; gitignored JSON seed/fallback only when degraded). NOT the real Cortex/system .env: this never reads or writes any real secret file. The whole page is one
that POSTs to /settings/system (urlencoded) via HTMX, swapping the result banner (#sys-save-result) in place. Fields are grouped into collapsible cards built from `groups` (app.settings.view_groups()): - text/number → editable .set-input - bool → .set-switch (a hidden mirror input carries true/false) - secret → masked field showing "•••• set" when stored, empty otherwise, with a reveal/replace affordance (the stored secret is NEVER sent to the client — reveal just unlocks the input to TYPE a replacement; leaving it masked/blank keeps the stored value) - readonly → locked, non-editable display Context: groups : [{id,title,sub,icon,open,secret_count,field_count,fields:[...]}] saved : optional post-save flag — when truthy, render the confirmation banner saved_count / saved_error : confirmation detail (see _settings_saved.html) #}
System
Console configuration — Cortex connection, harness, and app preferences. Provider keys live in the Providers surface when it is enabled for this edition. Stored locally in the console app-DB, applied on reload. This is the console's own store, not the real Cortex .env.
Secrets live only in the local console settings store — never committed, never rendered back into the page. A stored key shows as •••• set; use Replace to enter a new one. Local single-user store.
{# Save target: the result banner swaps in here after POST /settings/system. #}
{% if saved is defined and (saved or saved_error) %} {% include "_settings_saved.html" %} {% endif %}
{# collapsible groups, schema-driven #} {% for g in groups %}
{{ g.icon | safe }} {{ g.title }} {{ g.sub }} {% if g.secret_count %} {{ g.secret_count }} secret{{ 's' if g.secret_count > 1 else '' }} {% else %} {{ g.field_count }} field{{ 's' if g.field_count > 1 else '' }} {% endif %}
{% for f in g.fields %}
{% if f.type == "readonly" %} {% endif %} {{ f.label }} {% if f.type == "secret" %} {# Masked secret. The visible input is readonly + shows the mask placeholder ("•••• set") when a secret is stored, empty otherwise. "Replace" unlocks it (clears + makes it editable) so the operator can TYPE a new value; "Hide" re-masks. The stored secret is never placed in the DOM — only the placeholder is. A blank/unchanged submit means "keep the stored secret". #} {# Test — server-side probe of THIS key against the provider (a cheap read-only model-list / key-info call, never a completion). Sends the field name + the current input value (a freshly-typed key tests as-is for pre-save feedback; a still-masked field falls back to the stored key). Result swaps into the per-row slot. #} {% elif f.type == "bool" %} {# Boolean flag → switch. The checkbox is presentational; a hidden text input mirrors true/false so the urlencoded POST carries the value reliably (an unchecked checkbox would otherwise be omitted). #} {{ 'true' if f.value else 'false' }} {% elif f.type == "readonly" %} {% elif f.type == "number" %} {% else %} {% endif %} {% if f.hint %}{{ f.hint }}{% endif %}
{% endfor %}
{% endfor %} {# footer actions — Save posts the form; Reset re-pulls the System tab. #}
{# CUSTOM PROVIDERS — operator-added provider credentials (name + base URL + masked API key) beyond the fixed built-in keys above. Kept OUTSIDE the main #sys-form (it has its own HTMX POSTs to /settings/system/custom-provider), so it never interferes with the System save. The region self-swaps on add/remove (#sys-custom-providers). #}
Custom providers Add an extra provider with its own base URL + API key. Stored locally + masked, separate from the System save above.
{% include "_settings_custom_providers.html" %}