feat: guided bridge login wizard in TUI via bridgev2 provisioning API

Bootstrap now enables each bridge's provisioning API (persisted shared
secret, matrix-token auth) and publishes /shared/bridges.json. The TUI
bridge screen shows per-bridge login state and launches a step-driven
wizard: flow picker, sequential input prompts (phone/cookies/password),
in-terminal QR rendering with long-poll wait, cancel support. Discord
(legacy bridge, no v3 API) keeps the bot-DM path via 'm'. verify.sh
gains a provisioning API smoke check.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Prad Nukala
2026-07-08 12:36:26 -04:00
co-authored by Claude Fable 5
parent d57086cd00
commit 760d9db800
5 changed files with 355 additions and 33 deletions
+16 -2
View File
@@ -28,6 +28,8 @@ secret_of() {
}
REG_SECRET=$(secret_of registration_shared_secret "${REGISTRATION_SHARED_SECRET:-auto}")
DP_SECRET=$(secret_of doublepuppet_shared_secret "${DOUBLEPUPPET_SHARED_SECRET:-auto}")
PROV_SECRET=$(secret_of provisioning_shared_secret auto)
export PROV_SECRET
MACAROON=$(secret_of macaroon_secret_key auto)
FORM=$(secret_of form_secret auto)
@@ -97,6 +99,8 @@ echo " - /data/appservices/doublepuppet.yaml" >> "$DATA/synapse/homeserver.yaml
# ── bridges ─────────────────────────────────────────────────────────
pg() { PGPASSWORD=$POSTGRES_PASSWORD psql -h postgres -U vortex -d postgres -qtAc "$1"; }
BRIDGES_JSON="{" # network -> provisioning endpoint info, consumed by the TUI
for b in $ALL_BRIDGES; do
enabled "$b" || continue
[ "$b" = telegram ] && [ "$telegram_ok" = false ] && continue
@@ -138,8 +142,7 @@ for b in $ALL_BRIDGES; do
.database.uri = strenv(DB_URI) |
.bridge.permissions = {"*": "relay", strenv(DOMAIN): "user", strenv(ADMIN_MXID): "admin"} |
.double_puppet.servers = {} |
.double_puppet.secrets = {strenv(DOMAIN): ("as_token:" + strenv(DP_SECRET))} |
.provisioning.shared_secret = "disable"
.double_puppet.secrets = {strenv(DOMAIN): ("as_token:" + strenv(DP_SECRET))}
' "$cfg"
fi
if [ "$b" = telegram ]; then
@@ -151,6 +154,12 @@ for b in $ALL_BRIDGES; do
log "rendered $b config"
fi
# applied every run (idempotent) so existing configs pick up changes:
# provisioning API on with matrix-token auth, for the TUI's guided login
if [ "$b" != discord ]; then
yq -i '.provisioning.shared_secret = strenv(PROV_SECRET) | .provisioning.allow_matrix_auth = true' "$cfg"
fi
# registration: regenerated deterministically from persisted tokens.
# Written to the bridge dir too, else the mautrix docker-run.sh entrypoint
# regenerates it with fresh tokens and clobbers the ones in config.yaml.
@@ -173,9 +182,14 @@ namespaces:
EOF
cp "$DATA/bridges/$b/registration.yaml" "$DATA/synapse/appservices/$b.yaml"
echo " - /data/appservices/$b.yaml" >> "$DATA/synapse/homeserver.yaml.new"
kind=v2; [ "$b" = discord ] && kind=legacy
BRIDGES_JSON="$BRIDGES_JSON\"$b\": {\"base_url\": \"http://$b:$port\", \"kind\": \"$kind\"},"
log "bridge $b ready (port $port)"
done
echo "${BRIDGES_JSON%,}}" | yq -p json -o json > "$DATA/shared/bridges.json"
chmod a+r "$DATA/shared/bridges.json"
mv "$DATA/synapse/homeserver.yaml.new" "$DATA/synapse/homeserver.yaml"
chown -R 991:991 "$DATA/synapse" # synapse image runs as uid 991
log "done"