mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-17 10:06:42 +02:00
feat(apps): add Tailscale connector with OAuth client health check
Add the Tailscale catalog entry (rest_api, api_key) that stores an OAuth client in the vault, a server-side API client for token exchange, device listing, and auth key mint/delete, and a health check that proves the client scopes and tag ownership with one ephemeral test key. Store a redacted summary on the connection, map provider failures to actionable codes without echoing provider bodies, refuse credential export, and add brand assets, review registry entry, docs, and fixture tests. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
1c4ce44e13
commit
47bbe1aba4
18 files changed
+1414
-75
No files matched your search
@@ -922,6 +922,29 @@ const apps = [
|
||||
}),
|
||||
{ docsUrl: "https://docs.browser-use.com/cloud/api-v4-overview" },
|
||||
],
|
||||
["tailscale", "Tailscale", "Reach tailnet machines and private services from agent environments.", "developer", "tailscale.com", ["https://login.tailscale.com/*"],
|
||||
method("oauth-client", "rest_api", "api_key", { serverUrl: "https://api.tailscale.com/api/v2" }, "S3",
|
||||
"Create an OAuth client in [Tailscale trust credentials](https://login.tailscale.com/admin/settings/oauth) with the `auth_keys` scope (tags `tag:paperclip-agent` and `tag:paperclip-control`) and the `devices:core` scope, then paste its client ID and secret. Paperclip verifies the client server-side by listing devices and minting one short-lived ephemeral test key that it deletes immediately. The client never leaves the server.", {
|
||||
label: "Tailscale OAuth client",
|
||||
whenToUse: "Connect the tailnet whose machines and services agents should reach.",
|
||||
grantKinds: ["organization"],
|
||||
credentialFields: [
|
||||
{ ...field("oauthClientId", "OAuth client ID", "k1234567CNTRL"), helperMd: "Copy the client ID shown after you create the OAuth client." },
|
||||
{ ...field("oauthClientSecret", "OAuth client secret", "tskey-client-…"), helperMd: "The secret is shown once. It needs the `auth_keys` scope with the tags agents will carry and the `devices:core` scope. Paperclip cannot add scopes or tags to an existing client; create a new client and reconnect when access is insufficient." },
|
||||
],
|
||||
// The client is exchanged for a token in the form body of the token
|
||||
// request; it is never a request header. A non-header placement keeps
|
||||
// the two fields as vault secret refs only, without header projections.
|
||||
keyPlacement: { location: "body_json", name: "client_secret" },
|
||||
tenantFields: [
|
||||
{ key: "tailnet", label: "Tailnet", type: "text", required: false, defaultValue: "-", placeholder: "-", helperMd: "Keep `-` for the tailnet that owns the OAuth client, or enter the tailnet name such as `example.com` or `tail1234.ts.net`.", validation: { pattern: "^(-|[A-Za-z0-9.@_-]+)$", maxLength: 253 } },
|
||||
{ key: "agentTag", label: "Agent tag", type: "text", required: true, advanced: true, defaultValue: "tag:paperclip-agent", placeholder: "tag:paperclip-agent", helperMd: "Tag assigned to machines and sandboxes that join the tailnet for agents. The OAuth client must be allowed to assign it.", validation: { pattern: "^tag:[A-Za-z0-9_-]+$", maxLength: 128 } },
|
||||
],
|
||||
consoleLinks: { keys: "https://login.tailscale.com/admin/settings/oauth", docs: "https://tailscale.com/kb/1215/oauth-clients" },
|
||||
warnings: ["Agents get network reach through this connection; they do not get tools that change the tailnet in this version."],
|
||||
}),
|
||||
{ docsUrl: "https://tailscale.com/kb/1215/oauth-clients" },
|
||||
],
|
||||
].map(
|
||||
([
|
||||
slug,
|
||||
|
||||
Reference in new issue
Block a user