feat(523): forge-connection tokens are stored sealed under SECRET_KEY, like the backup S3 secret
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 16s
CI & Build / TypeScript typecheck (push) Successful in 56s
CI & Build / integration (push) Successful in 1m8s
CI & Build / Python tests (push) Successful in 1m54s
CI & Build / Build & push image (push) Successful in 36s
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 16s
CI & Build / TypeScript typecheck (push) Successful in 56s
CI & Build / integration (push) Successful in 1m8s
CI & Build / Python tests (push) Successful in 1m54s
CI & Build / Build & push image (push) Successful in 36s
The column becomes token_sealed (migration 0122 seals existing rows with a frozen copy of the v1 key), every reader opens it through connection_token, a row this instance cannot open is skipped with a warning, and Settings asks for that token again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -125,12 +125,17 @@ async def test_search():
|
||||
@login_required
|
||||
async def list_forge_connections_route():
|
||||
from scribe.services.forge import FORGE_KINDS
|
||||
from scribe.services.forge_connections import list_connections
|
||||
from scribe.services.forge_connections import connection_token, list_connections
|
||||
|
||||
uid = get_current_user_id()
|
||||
rows = await list_connections(uid)
|
||||
# Never the token: only whether this instance can still open it, so the
|
||||
# page can ask for it again after a SECRET_KEY change.
|
||||
return jsonify({
|
||||
"connections": [r.to_dict() for r in rows],
|
||||
"connections": [
|
||||
{**r.to_dict(), "token_readable": connection_token(r) is not None}
|
||||
for r in rows
|
||||
],
|
||||
"kinds": list(FORGE_KINDS),
|
||||
})
|
||||
|
||||
@@ -198,13 +203,19 @@ async def test_forge_connection_route(connection_id: int):
|
||||
press, so a misconfiguration is visible now rather than as silent
|
||||
fallbacks later (#2663's lesson, applied per keyring row)."""
|
||||
from scribe.services.forge import ForgeError, build_adapter
|
||||
from scribe.services.forge_connections import get_connection
|
||||
from scribe.services.forge_connections import connection_token, get_connection
|
||||
|
||||
uid = get_current_user_id()
|
||||
row = await get_connection(uid, connection_id)
|
||||
if row is None:
|
||||
return jsonify({"error": "Connection not found"}), 404
|
||||
adapter = build_adapter(row.kind, row.base_url, row.token)
|
||||
token = connection_token(row)
|
||||
if token is None:
|
||||
return jsonify({
|
||||
"error": "This instance can't read the saved token: SECRET_KEY has changed "
|
||||
"since it was saved. Enter the token again."
|
||||
}), 400
|
||||
adapter = build_adapter(row.kind, row.base_url, token)
|
||||
if adapter is None:
|
||||
return jsonify({"error": "Connection is not usable — check kind and base URL"}), 400
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user