15 Commits
Author SHA1 Message Date
arc53-machine 23e7145cee Give a member the account they just connected
Member-mode resolution ranked accounts by last_used_at first, so a
connection added by Connect to continue (never used) lost to any older
used account. Accounts now rank by the later of last use and creation.
2026-09-29 15:09:18 +01:00
arc53-machine a45e369d0f Run a tool only on a connection of the connector that provides it
At run time a tool now refuses a connection whose connector does not list
the tool's type (a Telegram bot token never reaches an ntfy or MCP tool),
and an MCP tool refuses a connection when no server is known for it,
instead of sending the key without checking. Legacy MCP rows still find
their server from the stored provider value.
2026-09-29 14:13:03 +01:00
arc53-machine bdc453eaab Show the model an account only where it tells tools apart
Actions that different services share are described with the service
alone; the account is named only when one service is connected twice.
2026-09-29 10:42:03 +01:00
arc53-machine bdcb88866a Let people name accounts and use the names to tell accounts apart
Connections get an account_name (migration 0039) that the owner sets with
PATCH /api/connections/<id>; the account label stays the account's
identity, so signing in again still finds it. When someone has more than
one account of a service, its tools are listed as "Telegram · <account>"
and the model sees each account's actions under the account's name
(telegram_send_message_alerts_bot) with the account in the description,
instead of _1 and _2. Actions shared by different services are named
after the service. Tools a user renamed keep their name.
2026-09-29 10:41:54 +01:00
arc53-machine c3e83ff9dd Add a default chat to the Telegram connector
A Telegram connection can now hold an optional default chat ID. When it
is set, both Telegram actions send there, the model is no longer asked
for a chat, and a chat it names anyway is ignored. In member mode each
member's own connection supplies their own chat. The same bot with a
different chat is a separate connection.
2026-09-29 10:41:48 +01:00
arc53-machine bbf83f02b2 Skip scheduled sync of a remote source paused for reconnect
S3 and GitHub sources synced from a connection kept being retried on
every schedule after their connection needed reconnecting, failing and
notifying the owner each time. They now wait, like Drive and Confluence
sources, and resume when the connection is reconnected.
2026-09-29 10:41:03 +01:00
arc53-machine 3572d968ec Read private repositories only with the user's own GitHub token
GITHUB_ACCESS_TOKEN belongs to the server, but any user could ingest any
repository it can see, private ones included. It is now used only for
public repositories; the loader checks the repository's visibility first
and asks for a GitHub connection otherwise.

The loader also takes a token from the connection a source syncs from.
Merging a connection's keys into a plain repository URL no longer fails
on json.loads, manual Sync now passes the source's connection, and a
token GitHub rejects pauses the connection's sources for reconnect.
2026-09-29 10:41:03 +01:00
arc53-machine f6c89503d8 Reconnect in place from the chat bar and the health toast
- The Connect card's payload carries connection_id for the caller's own
  connection (never an owner's), so "Reconnect" in chat signs in again
  right there instead of sending the user to Settings. The bar offers
  Continue as soon as the connection works again, also after leaving and
  coming back to the chat.
- The reconnect event carries source and tool counts, and the toast says
  what stopped: "3 sources are paused", "so agents can use it again",
  or both. Reconnect signs in again in place and the toast closes itself
  once the connection works; MCP servers still reconnect from their
  drawer.
2026-09-28 21:37:19 +01:00
arc53-machine a23ace3491 Refuse writes on the owner's accounts from API-key callers unless allowed
An agent called with its API key (widget, API) runs as its owner, and
nobody can approve an action there, so a write set to Always allow ran
on the owner's account for anyone holding the key. A caller is external
when the request carries the key and is not signed in as the owner (an
owner previewing their agent keeps full access).

For external callers, write actions on connection-backed tools are
refused unless listed in the agent config's new api_write_allowlist
(tool_id:action), and a missing connection is refused instead of pausing
on a Connect card the widget cannot show. The flag and list survive a
paused-and-resumed stream. Owners pick the allowed actions under Access
details; a team editor's update keeps the stored list.
2026-09-28 21:33:41 +01:00
arc53-machine 7c6154749a Address review: model metadata, serialized admin saves, member account choice
- models.py: connector_policies.enabled is the nullable column; the
  earlier edit had loosened user_custom_models.enabled instead. A test
  pins both against their migrations.
- Admin > Connectors saves one change at a time, so an older snapshot
  can no longer overwrite a newer one.
- In member mode, a member with several connected accounts of the same
  service uses the one they used (or connected) most recently, not the
  oldest.
2026-09-28 20:59:36 +01:00
arc53-machine 473e8ec15c Validate tool edits before touching the connection; scope kept MCP connections
- Editing a connection-backed tool validates the config before writing
  new credentials, so a rejected edit no longer rotates the connection's
  key and resumes its sources.
- An MCP edit keeps its previous connection only when the caller owns it
  and it signs in the way the tool now does.
2026-09-28 19:31:02 +01:00
arc53-machine fff3e7c904 Never send an MCP connection's secret to a different server
Editing an MCP server's URL kept the previous connection when no new
one could be stored (default encryption key), so its key would reach the
new server. The save route now keeps a previous connection only for the
same server, and the executor refuses an MCP tool whose connection was
stored for another server.
2026-09-28 19:11:54 +01:00
arc53-machine 6b4220d401 Address review: MCP token scope, API-key identity, reconnect lock, setup retries
- An MCP connection's tokens only go to its own server, and a
  connection_id can no longer come from a client: the MCP test/save
  routes drop it and the tool executor uses only the resolved one.
- API-key connections are reused only when they hold the same
  credentials. Two keys that share a hint or a label get separate
  connections ("…abcd (2)"), at runtime and in the 0038 backfill.
- Reconnecting a connection whose secrets cannot be decrypted no longer
  flags it from a second transaction while holding its row lock.
- Connection setup validates the sync request before claiming its
  Idempotency-Key, so a corrected retry is queued.
- A request that names no connection resolves to none without opening
  a database connection; fixes two tests that reached a real database.
2026-09-28 18:45:27 +01:00
arc53-machine d9f823d601 Stop syncing sources of a connector an admin turned off
Scheduled syncs checked the connection's status but not the admin
policy, so a disabled connector kept pulling data. Connector sources now
return "disabled" and S3/Reddit syncs get no credentials until the
connector is turned back on.
2026-09-28 17:59:36 +01:00
arc53-machine 3511004f50 Connections own their credentials
Migration 0038 moves every stored secret (OAuth tokens, MCP OAuth
tokens and client registrations, API keys) into the connection's
encrypted envelope, links API-key tools to one connection per distinct
credential, allows several accounts per provider, and adds
credential_mode to sources and tools. OAuth MCP tools keep resolving
each member's own token, as they did before.

docsgpt.connectors.service is now the only reader of OAuth tokens:
get_valid_token_info refreshes under a row lock and persists rotated
refresh tokens, and a revoked grant flags the connection, pauses its
sources and notifies the owner. Loaders build from a connection
(BaseConnectorLoader.from_connection), so scheduled sync covers Drive,
SharePoint and Confluence sources with no browser. S3 and Reddit keys
stay on the connection instead of in remote_data.

New endpoints: POST /api/connections, /setup, /reconnect,
/picker-token, /claim, DELETE /api/connections/<id>, per-action
permissions and MCP refresh-tools. Upload, file listing, sync and
validate-session take a connection_id; session tokens keep working for
this release. The tool executor reads credentials from the resolved
connection (owner or member mode) and pauses on a Connect card when a
connection needs signing in. docsgpt connectors reencrypt rewrites
stored credentials after a key rotation.
2026-09-28 17:03:09 +01:00