@wolpertingerlabs/drawlatch 1.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/CONNECTIONS.md +197 -0
  2. package/INGESTORS.md +790 -0
  3. package/LICENSE +21 -0
  4. package/README.md +685 -0
  5. package/dist/cli/generate-keys.d.ts +15 -0
  6. package/dist/cli/generate-keys.js +107 -0
  7. package/dist/connections/anthropic.json +16 -0
  8. package/dist/connections/bluesky.json +26 -0
  9. package/dist/connections/devin.json +15 -0
  10. package/dist/connections/discord-bot.json +24 -0
  11. package/dist/connections/discord-oauth.json +16 -0
  12. package/dist/connections/github.json +25 -0
  13. package/dist/connections/google-ai.json +15 -0
  14. package/dist/connections/google.json +28 -0
  15. package/dist/connections/hex.json +14 -0
  16. package/dist/connections/lichess.json +15 -0
  17. package/dist/connections/linear.json +29 -0
  18. package/dist/connections/mastodon.json +25 -0
  19. package/dist/connections/notion.json +33 -0
  20. package/dist/connections/openai.json +16 -0
  21. package/dist/connections/openrouter.json +16 -0
  22. package/dist/connections/reddit.json +28 -0
  23. package/dist/connections/slack.json +23 -0
  24. package/dist/connections/stripe.json +25 -0
  25. package/dist/connections/telegram.json +26 -0
  26. package/dist/connections/trello.json +25 -0
  27. package/dist/connections/twitch.json +28 -0
  28. package/dist/connections/x.json +27 -0
  29. package/dist/mcp/server.d.ts +13 -0
  30. package/dist/mcp/server.js +258 -0
  31. package/dist/remote/ingestors/base-ingestor.d.ts +65 -0
  32. package/dist/remote/ingestors/base-ingestor.js +132 -0
  33. package/dist/remote/ingestors/discord/discord-gateway.d.ts +58 -0
  34. package/dist/remote/ingestors/discord/discord-gateway.js +341 -0
  35. package/dist/remote/ingestors/discord/index.d.ts +3 -0
  36. package/dist/remote/ingestors/discord/index.js +3 -0
  37. package/dist/remote/ingestors/discord/types.d.ts +56 -0
  38. package/dist/remote/ingestors/discord/types.js +68 -0
  39. package/dist/remote/ingestors/index.d.ts +16 -0
  40. package/dist/remote/ingestors/index.js +20 -0
  41. package/dist/remote/ingestors/manager.d.ts +65 -0
  42. package/dist/remote/ingestors/manager.js +201 -0
  43. package/dist/remote/ingestors/poll/index.d.ts +2 -0
  44. package/dist/remote/ingestors/poll/index.js +2 -0
  45. package/dist/remote/ingestors/poll/poll-ingestor.d.ts +78 -0
  46. package/dist/remote/ingestors/poll/poll-ingestor.js +283 -0
  47. package/dist/remote/ingestors/registry.d.ts +32 -0
  48. package/dist/remote/ingestors/registry.js +46 -0
  49. package/dist/remote/ingestors/ring-buffer.d.ts +33 -0
  50. package/dist/remote/ingestors/ring-buffer.js +62 -0
  51. package/dist/remote/ingestors/slack/index.d.ts +3 -0
  52. package/dist/remote/ingestors/slack/index.js +3 -0
  53. package/dist/remote/ingestors/slack/socket-mode.d.ts +48 -0
  54. package/dist/remote/ingestors/slack/socket-mode.js +267 -0
  55. package/dist/remote/ingestors/slack/types.d.ts +70 -0
  56. package/dist/remote/ingestors/slack/types.js +72 -0
  57. package/dist/remote/ingestors/types.d.ts +138 -0
  58. package/dist/remote/ingestors/types.js +13 -0
  59. package/dist/remote/ingestors/webhook/base-webhook-ingestor.d.ts +112 -0
  60. package/dist/remote/ingestors/webhook/base-webhook-ingestor.js +119 -0
  61. package/dist/remote/ingestors/webhook/github-types.d.ts +45 -0
  62. package/dist/remote/ingestors/webhook/github-types.js +65 -0
  63. package/dist/remote/ingestors/webhook/github-webhook-ingestor.d.ts +43 -0
  64. package/dist/remote/ingestors/webhook/github-webhook-ingestor.js +86 -0
  65. package/dist/remote/ingestors/webhook/index.d.ts +8 -0
  66. package/dist/remote/ingestors/webhook/index.js +12 -0
  67. package/dist/remote/ingestors/webhook/stripe-types.d.ts +57 -0
  68. package/dist/remote/ingestors/webhook/stripe-types.js +108 -0
  69. package/dist/remote/ingestors/webhook/stripe-webhook-ingestor.d.ts +47 -0
  70. package/dist/remote/ingestors/webhook/stripe-webhook-ingestor.js +90 -0
  71. package/dist/remote/ingestors/webhook/trello-types.d.ts +90 -0
  72. package/dist/remote/ingestors/webhook/trello-types.js +81 -0
  73. package/dist/remote/ingestors/webhook/trello-webhook-ingestor.d.ts +60 -0
  74. package/dist/remote/ingestors/webhook/trello-webhook-ingestor.js +126 -0
  75. package/dist/remote/server.d.ts +103 -0
  76. package/dist/remote/server.js +536 -0
  77. package/dist/shared/config.d.ts +213 -0
  78. package/dist/shared/config.js +269 -0
  79. package/dist/shared/connections.d.ts +72 -0
  80. package/dist/shared/connections.js +103 -0
  81. package/dist/shared/crypto/channel.d.ts +95 -0
  82. package/dist/shared/crypto/channel.js +175 -0
  83. package/dist/shared/crypto/index.d.ts +3 -0
  84. package/dist/shared/crypto/index.js +3 -0
  85. package/dist/shared/crypto/keys.d.ts +92 -0
  86. package/dist/shared/crypto/keys.js +143 -0
  87. package/dist/shared/logger.d.ts +30 -0
  88. package/dist/shared/logger.js +74 -0
  89. package/dist/shared/protocol/handshake.d.ts +116 -0
  90. package/dist/shared/protocol/handshake.js +214 -0
  91. package/dist/shared/protocol/index.d.ts +3 -0
  92. package/dist/shared/protocol/index.js +2 -0
  93. package/dist/shared/protocol/messages.d.ts +46 -0
  94. package/dist/shared/protocol/messages.js +8 -0
  95. package/package.json +105 -0
package/CONNECTIONS.md ADDED
@@ -0,0 +1,197 @@
1
+ # Connections (Pre-built Route Templates)
2
+
3
+ Instead of manually configuring connectors for popular APIs, you can use **connections** — pre-built route templates that ship with the package. Reference them by name in a caller's `connections` list in `remote.config.json`:
4
+
5
+ ```json
6
+ {
7
+ "host": "0.0.0.0",
8
+ "port": 9999,
9
+ "localKeysDir": "~/.drawlatch/keys/remote",
10
+ "callers": {
11
+ "my-laptop": {
12
+ "peerKeyDir": "~/.drawlatch/keys/peers/my-laptop",
13
+ "connections": ["github", "stripe"]
14
+ }
15
+ },
16
+ "rateLimitPerMinute": 60
17
+ }
18
+ ```
19
+
20
+ Connection templates are loaded when a caller's session is established. Custom connectors (defined in the top-level `connectors` array) with a matching `alias` take precedence over built-in templates — you can override any connection by defining a custom connector with the same alias.
21
+
22
+ ## Available Connections
23
+
24
+ | Connection | API | Required Environment Variable(s) | Auth Method |
25
+ | --------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------ | ------------------------------------- |
26
+ | `anthropic` | [Anthropic Claude API](https://docs.anthropic.com/en/api) | `ANTHROPIC_API_KEY` | x-api-key header (see note) |
27
+ | `bluesky` | [Bluesky API (AT Protocol)](https://docs.bsky.app/) | `BLUESKY_ACCESS_TOKEN` | Bearer token header (see note) |
28
+ | `devin` | [Devin AI API](https://docs.devin.ai/api-reference/overview) | `DEVIN_API_KEY` | Bearer token header |
29
+ | `discord-bot` | [Discord Bot API](https://discord.com/developers/docs/intro) | `DISCORD_BOT_TOKEN` | Bot token header (see note) |
30
+ | `discord-oauth` | [Discord OAuth2 API](https://discord.com/developers/docs/topics/oauth2) | `DISCORD_OAUTH_TOKEN` | Bearer token header (see note) |
31
+ | `github` | [GitHub REST API](https://docs.github.com/en/rest) | `GITHUB_TOKEN`, `GITHUB_WEBHOOK_SECRET` | Bearer token header (see note) |
32
+ | `google` | [Google APIs](https://developers.google.com/apis-explorer) | `GOOGLE_API_TOKEN` | Bearer token header (see note) |
33
+ | `google-ai` | [Google AI Gemini API](https://ai.google.dev/api) | `GOOGLE_AI_API_KEY` | x-goog-api-key header (see note) |
34
+ | `hex` | [Hex API](https://learn.hex.tech/docs/api/api-overview) | `HEX_TOKEN` | Bearer token header |
35
+ | `lichess` | [Lichess API](https://lichess.org/api) | `LICHESS_API_TOKEN` | Bearer token header (see note) |
36
+ | `linear` | [Linear GraphQL API](https://developers.linear.app/docs/graphql/working-with-the-graphql-api) | `LINEAR_API_KEY` | API key header (see note) |
37
+ | `mastodon` | [Mastodon API](https://docs.joinmastodon.org/api/) | `MASTODON_ACCESS_TOKEN` | Bearer token header (see note) |
38
+ | `notion` | [Notion API](https://developers.notion.com/reference) | `NOTION_API_KEY` | Bearer token header (see note) |
39
+ | `openai` | [OpenAI API](https://platform.openai.com/docs/api-reference) | `OPENAI_API_KEY` | Bearer token header |
40
+ | `openrouter` | [OpenRouter API](https://openrouter.ai/docs/api-reference) | `OPENROUTER_API_KEY` | Bearer token header |
41
+ | `reddit` | [Reddit API](https://www.reddit.com/dev/api/) | `REDDIT_ACCESS_TOKEN`, `REDDIT_USER_AGENT` | Bearer token header (see note) |
42
+ | `slack` | [Slack Web API](https://docs.slack.dev/apis/web-api) | `SLACK_BOT_TOKEN`, `SLACK_APP_TOKEN` | Bearer token header (see note) |
43
+ | `stripe` | [Stripe Payments API](https://docs.stripe.com/api) | `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET` | Bearer token header (see note) |
44
+ | `telegram` | [Telegram Bot API](https://core.telegram.org/bots/api) | `TELEGRAM_BOT_TOKEN` | URL path token (see note) |
45
+ | `trello` | [Trello Boards API](https://developer.atlassian.com/cloud/trello/rest/) | `TRELLO_API_KEY`, `TRELLO_TOKEN`, `TRELLO_API_SECRET`, `TRELLO_CALLBACK_URL` | Query parameters (see note) |
46
+ | `twitch` | [Twitch Helix API](https://dev.twitch.tv/docs/api/reference/) | `TWITCH_ACCESS_TOKEN`, `TWITCH_CLIENT_ID` | Bearer + Client-Id headers (see note) |
47
+ | `x` | [X (Twitter) API v2](https://developer.x.com/en/docs/x-api) | `X_BEARER_TOKEN` | Bearer token header (see note) |
48
+
49
+ > **Anthropic note:** The Anthropic API uses a custom `x-api-key` header instead of the standard `Authorization: Bearer` pattern. The `anthropic-version` header is pinned to `2023-06-01`. To use a different API version, override with a custom route.
50
+
51
+ > **GitHub note:** The `github` connection includes a **webhook ingestor** for real-time events (push, pull_request, issues, etc.). Set `GITHUB_WEBHOOK_SECRET` to the webhook signing secret configured in your GitHub repository's webhook settings, then point the webhook URL to `https://<your-server>/webhooks/github`. Events are buffered and retrievable via `poll_events`. The server must be publicly accessible (or behind a tunnel like ngrok/Cloudflare Tunnel) to receive webhook POSTs. If you don't need webhook ingestion, the `GITHUB_WEBHOOK_SECRET` env var can be left unset — the REST API functionality works independently.
52
+
53
+ > **Discord note:** Discord has two connection types. `discord-bot` uses the `Bot` authorization prefix for bot tokens, which have full access to most API routes (guilds, channels, messages, etc.). `discord-oauth` uses a standard `Bearer` token obtained via OAuth2, which provides user-scoped access limited to the authorized scopes (identity, guilds list, email, etc.). Both target the same v10 API base URL.
54
+
55
+ > **Google AI note:** The Google AI (Gemini) API uses a custom `x-goog-api-key` header instead of the standard `Authorization: Bearer` pattern. This is separate from the `google` connection — use `google` for Workspace APIs (Sheets, Drive, etc.) and `google-ai` for Gemini LLM endpoints. The endpoint is not version-pinned (`generativelanguage.googleapis.com/**`) to allow access to both `v1` and `v1beta` paths.
56
+
57
+ > **Google APIs note:** Google Workspace APIs span many subdomains (sheets.googleapis.com, drive.googleapis.com, etc.). The `google` connection allowlists the most common domains. If you need additional subdomains, add a custom route with the same `GOOGLE_API_TOKEN` secret. For Google AI / Gemini, use the `google-ai` connection instead.
58
+
59
+ > **Linear note:** Linear is a GraphQL-only API. All requests should be POST requests to `https://api.linear.app/graphql` with a JSON body containing your GraphQL query. The connection uses the `Authorization: <API_KEY>` format (no "Bearer" prefix) which is correct for Linear personal API keys. If you use OAuth tokens instead, override with a custom route that includes the "Bearer" prefix.
60
+
61
+ > **Notion note:** The Notion API requires a `Notion-Version` header. This connection pins it to `2022-06-28` (the last stable version before breaking multi-source changes). To use a newer version, override with a custom route.
62
+
63
+ > **Slack note:** The `slack` connection uses `SLACK_BOT_TOKEN` (starts with `xoxb-`) for API requests. For real-time events via Socket Mode, also set `SLACK_APP_TOKEN` (starts with `xapp-`) — an App-Level Token with `connections:write` scope, generated from your app's settings in the [Slack API dashboard](https://api.slack.com/apps). Socket Mode must be enabled in the app settings. If you don't need real-time event ingestion, `SLACK_APP_TOKEN` can be left unset — the Web API functionality works independently.
64
+
65
+ > **Stripe note:** The `stripe` connection includes a **webhook ingestor** for real-time payment events (charges, invoices, subscriptions, etc.). Set `STRIPE_WEBHOOK_SECRET` to the `whsec_...` signing secret from Stripe Dashboard → Developers → Webhooks, then point the webhook URL to `https://<your-server>/webhooks/stripe`. Stripe signature verification includes replay protection with a 5-minute timestamp tolerance. If you don't need webhook ingestion, `STRIPE_WEBHOOK_SECRET` can be left unset — the API functionality works independently.
66
+
67
+ > **Trello note:** The Trello API uses query parameter authentication rather than headers. Include `?key=${TRELLO_API_KEY}&token=${TRELLO_TOKEN}` in your request URLs — the `${VAR}` placeholders are resolved automatically from the route's secrets. The Trello connection includes a **webhook ingestor** for real-time events (card updates, list changes, board activity). Set `TRELLO_API_SECRET` and `TRELLO_CALLBACK_URL`, then point the Trello webhook to `https://<your-server>/webhooks/trello`. Trello uses HMAC-SHA1 signature verification with a unique scheme that includes the callback URL in the HMAC computation. If you don't need webhook ingestion, `TRELLO_API_SECRET` and `TRELLO_CALLBACK_URL` can be left unset.
68
+
69
+ > **Bluesky note:** Bluesky uses the AT Protocol. Obtain an access token by POSTing to `https://bsky.social/xrpc/com.atproto.server.createSession` with `{ "identifier": "your.handle", "password": "your-app-password" }`. Use an [App Password](https://bsky.app/settings/app-passwords) rather than your main password. Access tokens expire after ~2 hours — rotate externally using the `refreshJwt` from the session response. Both `bsky.social` (authenticated PDS) and `public.api.bsky.app` (public read-only API) are allowlisted. For self-hosted PDS instances, override with a custom connector. Rate limit: 3,000 requests per 5 minutes. The AT Protocol firehose (`wss://bsky.network/xrpc/com.atproto.sync.subscribeRepos`) provides real-time events but is not yet supported as an ingestor type.
70
+
71
+ > **Mastodon note:** This template targets the `mastodon.social` instance. Mastodon is a federated network — each instance has its own API URL. To use a different instance, define a custom connector with the same auth pattern but replace `mastodon.social` in `allowedEndpoints` with your instance domain (e.g., `hachyderm.io`, `fosstodon.org`). Obtain an access token from your instance's Development settings (Preferences > Development > New Application). Rate limit: 300 requests per 5 minutes per token (default, may vary by instance).
72
+
73
+ > **Reddit note:** The Reddit API requires a descriptive `User-Agent` header — set `REDDIT_USER_AGENT` to something like `platform:myapp:v1.0 (by /u/yourusername)`. Obtain an OAuth2 token by registering a "script" application at [reddit.com/prefs/apps](https://www.reddit.com/prefs/apps), then POSTing to `https://www.reddit.com/api/v1/access_token` with HTTP Basic Auth (`client_id:client_secret`) and `grant_type=client_credentials` (or `password` for user context). Tokens expire after 1 hour — rotate externally using the refresh token. The poll ingestor monitors a subreddit for new posts — set `REDDIT_SUBREDDIT` to the subreddit name without the `r/` prefix (e.g., `programming`). If unset, the poll will fail; disable the ingestor via `ingestorOverrides` if not needed. Rate limit: 100 requests per minute per OAuth2 token.
74
+
75
+ > **Telegram note:** The Telegram Bot API embeds the bot token in the URL path rather than in headers. Include `/bot${TELEGRAM_BOT_TOKEN}/` in your request URLs (e.g., `https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage`) — the `${VAR}` placeholder is resolved automatically from the route's secrets. Create a bot via [@BotFather](https://t.me/BotFather) on Telegram to obtain a token. The poll ingestor uses `getUpdates` to fetch new messages and events. Note: if you set up a webhook externally, `getUpdates` will not work — Telegram only supports one delivery method at a time.
76
+
77
+ > **Twitch note:** Twitch requires both `Authorization: Bearer` and `Client-Id` headers on every API request. Register an application at the [Twitch Developer Console](https://dev.twitch.tv/console/apps) to get a Client ID, then obtain an access token via OAuth2 (client credentials for app tokens, or authorization code for user tokens). App tokens cannot access user-specific endpoints like followed streams — the poll ingestor requires a user access token and `TWITCH_USER_ID`. Get your user ID via `GET /helix/users` with your token. If the poll ingestor is not needed, `TWITCH_USER_ID` can be left unset. Rate limit: 800 requests per minute with a valid token.
78
+
79
+ > **X (Twitter) note:** The `x` connection uses the v2 API with an App-only Bearer token (available from the [X Developer Portal](https://developer.x.com/en/portal/dashboard)). Both `api.x.com` and `api.twitter.com` (legacy domain) are allowlisted. The poll ingestor searches recent tweets matching a configurable query — set `X_SEARCH_QUERY` to a search query string (e.g., `#programming -is:retweet`). If unset, the poll will fail; disable the ingestor via `ingestorOverrides` if not needed. API access tiers vary significantly — the Free tier allows 1 app and read-only access with low rate limits; Basic ($200/month) adds write access and higher limits. X also supports filtered streams (`GET /2/tweets/search/stream`) for real-time tweet delivery, but this requires an active HTTP streaming connection not currently supported by the poll ingestor.
80
+
81
+ > **Lichess note:** The Lichess API supports both public and authenticated endpoints. Public endpoints (Opening Explorer on `explorer.lichess.ovh`, Cloud Eval on `lichess.org/api/cloud-eval`) work without a token. For authenticated routes (account info, game history, player-specific opening analysis, challenges, etc.), set `LICHESS_API_TOKEN` to a [personal API access token](https://lichess.org/account/oauth/token). The token is sent as a Bearer header on all requests — public endpoints simply ignore it. Two domains are allowlisted: `explorer.lichess.ovh` for opening statistics and `lichess.org/api` for everything else.
82
+
83
+ ## Example: Connections with environment variables
84
+
85
+ Set the required environment variables on the remote server (via `.env` file, shell export, or your deployment platform), then reference the connections in a caller's config:
86
+
87
+ ```bash
88
+ # .env on the remote server
89
+ GITHUB_TOKEN=ghp_your_github_token_here
90
+ STRIPE_SECRET_KEY=sk_live_your_stripe_key_here
91
+ ```
92
+
93
+ ```json
94
+ {
95
+ "callers": {
96
+ "my-laptop": {
97
+ "peerKeyDir": "/keys/peers/my-laptop",
98
+ "connections": ["github", "stripe"]
99
+ }
100
+ }
101
+ }
102
+ ```
103
+
104
+ That's it — the connection templates handle endpoint patterns, auth headers, docs URLs, and OpenAPI specs automatically.
105
+
106
+ ## Example: Mixing connections and custom connectors
107
+
108
+ You can use built-in connections alongside custom connectors. Custom connectors are defined in the top-level `connectors` array with an `alias`, then referenced by name in caller `connections` lists:
109
+
110
+ ```json
111
+ {
112
+ "connectors": [
113
+ {
114
+ "alias": "internal-api",
115
+ "name": "Internal API",
116
+ "allowedEndpoints": ["http://localhost:4567/**"],
117
+ "headers": { "Authorization": "Bearer ${INTERNAL_TOKEN}" },
118
+ "secrets": { "INTERNAL_TOKEN": "${INTERNAL_TOKEN}" }
119
+ }
120
+ ],
121
+ "callers": {
122
+ "my-laptop": {
123
+ "peerKeyDir": "/keys/peers/my-laptop",
124
+ "connections": ["github", "internal-api"]
125
+ }
126
+ }
127
+ }
128
+ ```
129
+
130
+ Custom connectors with an `alias` that matches a built-in connection name take precedence over the built-in template.
131
+
132
+ ## Example: Per-caller env overrides
133
+
134
+ When multiple callers share the same connection but need different credentials, use the `env` field to redirect environment variable resolution per caller:
135
+
136
+ ```json
137
+ {
138
+ "callers": {
139
+ "alice": {
140
+ "peerKeyDir": "/keys/peers/alice",
141
+ "connections": ["github"],
142
+ "env": { "GITHUB_TOKEN": "${ALICE_GITHUB_TOKEN}" }
143
+ },
144
+ "bob": {
145
+ "peerKeyDir": "/keys/peers/bob",
146
+ "connections": ["github"],
147
+ "env": { "GITHUB_TOKEN": "${BOB_GITHUB_TOKEN}" }
148
+ }
149
+ }
150
+ }
151
+ ```
152
+
153
+ Both callers use the same `github` built-in connection, but Alice's requests resolve `GITHUB_TOKEN` from `process.env.ALICE_GITHUB_TOKEN` while Bob's resolve from `process.env.BOB_GITHUB_TOKEN`. Values can also be literal strings for direct injection (e.g., `"STRIPE_SECRET_KEY": "sk_test_hardcoded"`).
154
+
155
+ Connection templates are stored as JSON files in `src/connections/`. You can inspect them to see exactly what headers, endpoints, and secrets each connection configures.
156
+
157
+ ## Planned Connections
158
+
159
+ The following connections are on the roadmap to be added:
160
+
161
+ ### Tier 1 — High Priority
162
+
163
+ - [ ] **Jira** — Project management (Atlassian)
164
+ - [ ] **HubSpot** — CRM platform
165
+ - [ ] **Twilio / SendGrid** — Messaging & email APIs
166
+ - [ ] **Microsoft Graph** — Teams, Outlook, OneDrive, SharePoint (Azure AD OAuth2)
167
+
168
+ ### Tier 2 — Developer & Productivity
169
+
170
+ - [ ] **GitLab** — Git hosting & CI/CD
171
+ - [ ] **Bitbucket** — Git hosting (Atlassian ecosystem)
172
+ - [ ] **Asana** — Project management
173
+ - [ ] **Confluence** — Wiki & docs (Atlassian ecosystem)
174
+ - [ ] **Datadog** — Monitoring & observability
175
+ - [ ] **PagerDuty** — Incident management
176
+
177
+ ### Tier 3 — Popular SaaS & Business Tools
178
+
179
+ - [ ] **Airtable** — Spreadsheet/database hybrid
180
+ - [ ] **Shopify** — E-commerce platform
181
+ - [ ] **Intercom** — Customer support
182
+ - [ ] **Zendesk** — Customer support
183
+ - [ ] **Salesforce** — Enterprise CRM
184
+ - [ ] **Monday.com** — Project management
185
+ - [ ] **Figma** — Design platform
186
+
187
+ ### Tier 4 — Infrastructure & AI
188
+
189
+ - [ ] **AWS** — S3, Lambda, etc.
190
+ - [ ] **Cloudflare** — Edge, DNS, Workers
191
+
192
+ ### Tier 5 — Social & Content Platforms
193
+
194
+ - [ ] **YouTube Data API** — Video search, channels, playlists (API key auth, complements `google` connection)
195
+ - [ ] **LinkedIn** — Professional networking (OAuth2)
196
+ - [ ] **Pinterest** — Visual discovery (OAuth2)
197
+ - [ ] **Tumblr** — Blogging platform (OAuth2)