diff --git a/frontend/src/admin/AdminSatellites.vue b/frontend/src/admin/AdminSatellites.vue index 768e676..d8cc70f 100644 --- a/frontend/src/admin/AdminSatellites.vue +++ b/frontend/src/admin/AdminSatellites.vue @@ -39,11 +39,15 @@ async function load() { } // While an uplink is not connected, poll gently so status goes live -// without a manual refresh (registration and reconnects included). +// without a manual refresh (registration and reconnects included); after +// minting a link URL, poll for a minute to catch the satellite appearing. let pollTimer = null +let mintWatchUntil = 0 function schedulePoll() { clearTimeout(pollTimer) - const watching = uplinks.value.some(u => !u.connected) + const watching = + uplinks.value.some(u => !u.connected) || + links.value.some(l => !l.connected) && Date.now() < mintWatchUntil if (watching) { pollTimer = setTimeout(async () => { await load() @@ -111,6 +115,7 @@ async function submitLinkDialog() { linkDialog.value = null } else { d.minted = await apiJson('/auth/api/admin/satellites/', { method: 'POST', body: { rp_ids } }) + mintWatchUntil = Date.now() + 60_000 // watch for the satellite registering } await refresh() } catch (e) { diff --git a/paskia/db/lifecycle.py b/paskia/db/lifecycle.py index d209e0c..bedbf2e 100644 --- a/paskia/db/lifecycle.py +++ b/paskia/db/lifecycle.py @@ -86,8 +86,9 @@ def _resolve_uuid_label( return None -# The OIDC signing key is stored at oidc.key. -_OIDC_KEY_PATH = re.compile(r"^oidc\.key$") +# The OIDC signing key is stored at oidc.key; satellite link key material +# at uplinks/satellite_links..key. +_SECRET_KEY_PATH = re.compile(r"^(oidc\.key|(uplinks|satellite_links)\.[^.]+\.key)$") @kanta.logfmt @@ -98,10 +99,10 @@ def format_log_uuid( current: Annotated[dict, "post"] | None = None, ) -> Optional[str]: # noqa: UP045 """Format UUID values/keys/actor labels and censor secrets in transaction logs.""" - # Censor sensitive OIDC key material regardless of value type, but only + # Censor sensitive key material regardless of value type, but only # when formatting the value: path components are passed with the component # itself as value and must stay visible ("oidc.key = "). - if _OIDC_KEY_PATH.fullmatch(path) and value != "key": + if _SECRET_KEY_PATH.fullmatch(path) and value != "key": return "" if not isinstance(value, str):