@viraatdas/rudder 3.9.1 → 3.9.4
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.
- package/assets/skills/google-cloud/SKILL.md +70 -6
- package/assets/skills/google-cloud/scripts/gcp.mjs +9 -3
- package/assets/skills/namecheap/SKILL.md +130 -0
- package/assets/skills/namecheap/scripts/__pycache__/namecheapcpython-314.pyc +0 -0
- package/assets/skills/namecheap/scripts/namecheap +785 -0
- package/dist/agent-skills.d.ts +2 -0
- package/dist/agent-skills.js +18 -2
- package/dist/agent-skills.js.map +1 -1
- package/dist/attach-session.d.ts +8 -0
- package/dist/attach-session.js +28 -1
- package/dist/attach-session.js.map +1 -1
- package/dist/cloud.js +14 -2
- package/dist/cloud.js.map +1 -1
- package/dist/native/darwin-arm64/rudder-native +0 -0
- package/dist/native/darwin-x64/rudder-native +0 -0
- package/dist/native/linux-x64/rudder-native +0 -0
- package/dist/terminal-theme.d.ts +21 -0
- package/dist/terminal-theme.js +64 -0
- package/dist/terminal-theme.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: rudder-google-cloud
|
|
3
|
-
description: Use for any Google Cloud or Google API setup — creating or naming a GCP project, enabling APIs (Gmail, Calendar, Drive, Gemini, …), "Sign in with Google" / Google OAuth clients, the consent screen (app name, logo, domains, scopes, verification, test users), redirect_uri_mismatch and other OAuth errors, gcloud auth, service accounts and keys, and storing the resulting secrets. Makes sure users see the product's own name on Google's screens, never a stray project like "My First Project".
|
|
3
|
+
description: Use for any Google Cloud or Google API setup — creating or naming a GCP project, enabling APIs (Gmail, Calendar, Drive, Gemini, …), "Sign in with Google" / Google OAuth clients, the consent screen (app name, logo, domains, scopes, brand verification, test users), moving sign-in to another domain, redirect_uri_mismatch and other OAuth errors, gcloud auth, service accounts and keys, and storing the resulting secrets. Makes sure users see the product's own name on Google's screens, never a stray project like "My First Project".
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Google Cloud, done properly
|
|
@@ -14,6 +14,15 @@ Helper: `node <this skill dir>/scripts/gcp.mjs <command>` (Node 18+, no deps).
|
|
|
14
14
|
It finds credentials from `gcloud`, gcloud's stored login, or ADC; run
|
|
15
15
|
`whoami` first.
|
|
16
16
|
|
|
17
|
+
**Google's official skills cover the rest.** This skill is the product layer
|
|
18
|
+
(project naming, consent screen, OAuth client, what a user sees). For general
|
|
19
|
+
`gcloud` work use Google's `gcloud` skill (check leaf syntax with `gcloud help
|
|
20
|
+
<command>` before running it, `--limit`/`--filter`/`--format` on every list,
|
|
21
|
+
`--quiet`, dry-run where supported) and `google-cloud-recipe-auth` for IAM,
|
|
22
|
+
service accounts and ADC. Both are in the `google-cloud-developer` plugin; if
|
|
23
|
+
they are not loaded: `claude plugin marketplace add google/skills && claude
|
|
24
|
+
plugin install google-cloud-developer@google-plugins`.
|
|
25
|
+
|
|
17
26
|
## The rules
|
|
18
27
|
|
|
19
28
|
1. **One project per product, named after the product.** Display name = the
|
|
@@ -25,7 +34,11 @@ It finds credentials from `gcloud`, gcloud's stored login, or ADC; run
|
|
|
25
34
|
2. **The consent screen's App name is what users read**, not the project name
|
|
26
35
|
and not the client name. Set it on the Branding page to the product name,
|
|
27
36
|
with the product's own support email, home page, privacy and terms URLs, and
|
|
28
|
-
the product's domain as an authorized domain.
|
|
37
|
+
the product's domain as an authorized domain. **It only shows once the
|
|
38
|
+
branding is verified.** Until then Google shows the redirect URI's domain:
|
|
39
|
+
the registrable domain for your own (`app.rudder.exla.ai` → "exla.ai"), the
|
|
40
|
+
whole host for a platform one ("rudder-cloud-control.fly.dev"). See "Brand
|
|
41
|
+
verification" below.
|
|
29
42
|
3. **Ask for the narrowest scopes that work.** Basic (openid/email/profile) can go
|
|
30
43
|
straight to production. Sensitive (Calendar, gmail.send) need verification.
|
|
31
44
|
Restricted (Gmail read/modify/compose, Drive full) need verification **and**
|
|
@@ -94,8 +107,8 @@ real sign-in in a browser and say in your report what the screen showed.
|
|
|
94
107
|
- **Testing vs production**: in Testing only listed test users can sign in and
|
|
95
108
|
refresh tokens expire after 7 days — fine for a demo, wrong for real users.
|
|
96
109
|
Publish as soon as the scopes allow it.
|
|
97
|
-
- **Logo**: uploading one
|
|
98
|
-
|
|
110
|
+
- **Logo**: uploading one adds a logo review to verification; leave it off
|
|
111
|
+
unless the user wants it, since basic scopes verify faster without one.
|
|
99
112
|
- **Internal user type** restricts sign-in to the org's Workspace accounts — only
|
|
100
113
|
right for internal tools.
|
|
101
114
|
- **Verification** (sensitive/restricted scopes): needs the home page on the
|
|
@@ -113,9 +126,60 @@ real sign-in in a browser and say in your report what the screen showed.
|
|
|
113
126
|
again) and the consent App name (Branding page). The project ID can never
|
|
114
127
|
change — choose it once, deliberately.
|
|
115
128
|
|
|
129
|
+
## Brand verification (getting the App name on screen)
|
|
130
|
+
|
|
131
|
+
Branding page → **Verify branding**. Google checks that every **authorized
|
|
132
|
+
domain** is verified in Search Console by an owner of the project, that the
|
|
133
|
+
home page and privacy policy live on those domains and name the app, and that
|
|
134
|
+
the support email belongs to the owner. Basic scopes: usually a few days.
|
|
135
|
+
|
|
136
|
+
- **Redirect URIs must be on a domain the user owns.** Platform hosts
|
|
137
|
+
(`*.fly.dev`, `*.vercel.app`, `*.run.app`, `*.awsapprunner.com`,
|
|
138
|
+
`*.netlify.app`) can never be verified, and while they are authorized
|
|
139
|
+
domains verification fails. Serve the auth callback from the product's own
|
|
140
|
+
domain (e.g. `app.<domain>`), then remove the platform redirect URIs and
|
|
141
|
+
their authorized domains.
|
|
142
|
+
- **Search Console**: add a Domain property for the apex and verify it with
|
|
143
|
+
the DNS TXT record it gives (through the DNS host's API if you have it,
|
|
144
|
+
otherwise ask the user), signed in as the same account that owns the project.
|
|
145
|
+
|
|
146
|
+
## Moving sign-in to another domain
|
|
147
|
+
|
|
148
|
+
Order matters. Switching the app first breaks sign-in for everyone.
|
|
149
|
+
|
|
150
|
+
1. Point the new host at the app (DNS + TLS) and check it serves.
|
|
151
|
+
2. Add the new redirect URI (and JS origin if used) to the Google client **and**
|
|
152
|
+
to every other provider on the same auth base URL (GitHub OAuth/App callback
|
|
153
|
+
URLs, Slack, Linear …). `check-client` must show it accepted.
|
|
154
|
+
3. Make every page that STARTS a sign-in redirect to the new host before
|
|
155
|
+
starting it: the OAuth state cookie is set on the host that starts the flow
|
|
156
|
+
and must be there when the callback lands. Native shells and old CLIs keep
|
|
157
|
+
using the old address, so bounce their login pages; don't strand them.
|
|
158
|
+
4. Flip the auth base URL (`BETTER_AUTH_URL`, `NEXTAUTH_URL`, …) and deploy.
|
|
159
|
+
5. Real sign-in on the new host for each provider; then remove the old redirect
|
|
160
|
+
URIs and authorized domains, and verify the branding.
|
|
161
|
+
|
|
162
|
+
## Keeping an existing client
|
|
163
|
+
|
|
164
|
+
A client already shipped in apps (an iOS bundle, a published CLI, stored in a
|
|
165
|
+
host's secrets) can stay in a misnamed project when moving it would change the
|
|
166
|
+
client ID. Its consent screen can still say the product's name: set the
|
|
167
|
+
Branding and verify it. Note the exception in the report; never silently.
|
|
168
|
+
|
|
169
|
+
## In the browser
|
|
170
|
+
|
|
171
|
+
- Google may ask for a passkey, security key or password re-auth (the URL
|
|
172
|
+
carries `rapt=`). Stop and ask the user to complete it; never type it.
|
|
173
|
+
- The client page's "Last used date" lags by days. Confirm which client is live
|
|
174
|
+
from the app's own sign-in redirect (`curl -sI <login url>` → `client_id=`),
|
|
175
|
+
not from that date.
|
|
176
|
+
- Settings "may take 5 minutes to a few hours"; `check-client` usually sees a
|
|
177
|
+
new redirect URI within a minute.
|
|
178
|
+
|
|
116
179
|
## Report
|
|
117
180
|
|
|
118
181
|
Say which project (ID and display name), which APIs, which client (ID, never
|
|
119
182
|
the secret), where the secrets live, the `check-client` result per redirect
|
|
120
|
-
URI, what the real sign-in screen
|
|
121
|
-
|
|
183
|
+
URI (including the name Google shows today), what the real sign-in screen
|
|
184
|
+
showed, the publishing and brand-verification status, and any verification
|
|
185
|
+
still owed (with the user cap it implies).
|
|
@@ -329,9 +329,15 @@ async function probe(clientId, redirect, scopes) {
|
|
|
329
329
|
const url = new URL("https://accounts.google.com/o/oauth2/v2/auth");
|
|
330
330
|
url.search = new URLSearchParams({ client_id: clientId, redirect_uri: redirect, response_type: "code", scope: scopes.join(" "), prompt: "select_account" }).toString();
|
|
331
331
|
const response = await fetch(url, { redirect: "follow", headers: { "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0 Safari/537.36", "accept-language": "en-US" } });
|
|
332
|
-
const
|
|
332
|
+
const html = await response.text();
|
|
333
|
+
const text = pageText(html);
|
|
333
334
|
const error = text.match(/Error 400: (\w+)/)?.[1] ?? text.match(/Error 401: (\w+)/)?.[1] ?? text.match(/Error 403: (\w+)/)?.[1] ?? (response.url.includes("/signin/oauth/error") ? "unknown_error" : null);
|
|
334
|
-
|
|
335
|
+
// The name sits in a data-app-name attribute (seen 2026-10); the text
|
|
336
|
+
// match is the fallback for older page shapes. Unverified branding shows
|
|
337
|
+
// the redirect URI's domain here, not the App name.
|
|
338
|
+
const appName = pageText(html.match(/data-app-name="([^"]+)"/)?.[1] ?? "").trim()
|
|
339
|
+
|| text.match(/to continue to ([^.]+?)(?:\s+(?:Email|Forgot|Not your|Create account|Next)\b|$)/)?.[1]?.trim()
|
|
340
|
+
|| null;
|
|
335
341
|
return { error, appName, finalUrl: response.url };
|
|
336
342
|
}
|
|
337
343
|
|
|
@@ -364,7 +370,7 @@ async function checkClient(o) {
|
|
|
364
370
|
}
|
|
365
371
|
const nameOk = !expect || r.appName.toLowerCase() === expect.toLowerCase();
|
|
366
372
|
if (!nameOk) ok = false;
|
|
367
|
-
console.log(`${nameOk ? "✓" : "✗"} ${redirect}: accepted; Google shows "continue to ${r.appName}"${nameOk ? "" : `, expected "${expect}". Fix the App name on the Branding page (it is not the project name)
|
|
373
|
+
console.log(`${nameOk ? "✓" : "✗"} ${redirect}: accepted; Google shows "continue to ${r.appName}"${nameOk ? "" : `, expected "${expect}". ${/\./.test(r.appName) ? "Google shows a domain until the branding is verified (Branding page, Verify branding)." : "Fix the App name on the Branding page (it is not the project name)."}`}`);
|
|
368
374
|
}
|
|
369
375
|
if (!ok) process.exit(1);
|
|
370
376
|
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rudder-namecheap
|
|
3
|
+
description: Use WHENEVER Namecheap comes up, and for any domain registered there (nameservers dns1/dns2.registrar-servers.com). Covers the whole account through the Namecheap API and CLI — DNS records (A/AAAA/CNAME/TXT/MX, verification records, pointing a domain or subdomain at Vercel, Netlify or a server, removing the parking page), free email forwarding (hello@ to an inbox), URL redirects, nameservers, registrar lock, domain privacy (WhoisGuard), domain list, expiry and auto-renew, contacts, availability and pricing, registering and renewing domains, transfers, account balance, and API access setup. Does the change itself and never hands the user records to type into the Namecheap dashboard.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Namecheap
|
|
7
|
+
|
|
8
|
+
**The rule: do it through the API, never hand the user steps for the
|
|
9
|
+
dashboard.** If access is missing, the only acceptable ask is the one-time API
|
|
10
|
+
setup in section 6, stated once, after everything else is done.
|
|
11
|
+
|
|
12
|
+
Tool: `<this skill dir>/scripts/namecheap` (Python 3 stdlib, no installs).
|
|
13
|
+
`$NC --help` and `$NC <command> --help` list every option.
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
NC="<this skill dir>/scripts/namecheap"
|
|
17
|
+
$NC check # credentials work + every domain in the account
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 1. Look before changing
|
|
21
|
+
|
|
22
|
+
| Question | Command |
|
|
23
|
+
|---|---|
|
|
24
|
+
| Which domains, when do they expire, auto-renew, privacy, lock | `$NC domains` (`--expiring`, `--expired`, `--search TEXT`) |
|
|
25
|
+
| One domain in full: status, expiry, privacy, nameservers, lock | `$NC info example.com` |
|
|
26
|
+
| Where its DNS is served from (public view) | `$NC lookup example.com NS` |
|
|
27
|
+
| Records Namecheap serves + email mode | `$NC list example.com` |
|
|
28
|
+
| Email forwards | `$NC forward example.com` |
|
|
29
|
+
| WHOIS contacts | `$NC contacts example.com` |
|
|
30
|
+
| Balance | `$NC balance` |
|
|
31
|
+
| Incoming transfers | `$NC transfers` |
|
|
32
|
+
|
|
33
|
+
If the nameservers are not `dns1/dns2.registrar-servers.com`, records live at
|
|
34
|
+
that DNS host, not at Namecheap: `*.vercel-dns.com` → `vercel dns add`;
|
|
35
|
+
Netlify (`dns*.p0*.nsone.net`) → the Netlify CLI/API; Cloudflare, Route 53 →
|
|
36
|
+
their CLI/API. Registrar settings (nameservers, lock, privacy, renewals) still
|
|
37
|
+
belong here.
|
|
38
|
+
|
|
39
|
+
## 2. DNS records: list, dry-run, then apply
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
$NC list example.com
|
|
43
|
+
$NC set example.com --add 'CNAME app site.netlify.app.' --dry-run
|
|
44
|
+
$NC set example.com --add 'CNAME app site.netlify.app.' # backs up, writes, re-reads, verifies
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Namecheap's `setHosts` **replaces every record on the domain**. Never call it
|
|
48
|
+
with curl or any other client: one call missing the MX or TXT records silently
|
|
49
|
+
breaks mail and verification. The tool merges with the live set, refuses record
|
|
50
|
+
types it cannot round-trip (CAA, SRV: tell the user those need the dashboard),
|
|
51
|
+
and backs up every write to `~/.config/namecheap/backups/`. Undo with
|
|
52
|
+
`$NC restore <backup.json>`.
|
|
53
|
+
|
|
54
|
+
| Goal | Command |
|
|
55
|
+
|---|---|
|
|
56
|
+
| Apex + www to Vercel (removes the parking page) | `$NC vercel example.com`, then `vercel domains add example.com <project>` and `vercel domains add www.example.com <project>` |
|
|
57
|
+
| Subdomain to Vercel | `$NC vercel example.com --sub app` |
|
|
58
|
+
| Verification TXT (Vercel, Google, …) | `$NC set example.com --add 'TXT _vercel "vc-domain-verify=..."'` |
|
|
59
|
+
| Subdomain to Netlify / any host | `$NC set example.com --add 'CNAME app site-name.netlify.app.'` |
|
|
60
|
+
| A record to a server | `$NC set example.com --add 'A api 203.0.113.7'` |
|
|
61
|
+
| Redirect a name (301) | `$NC set example.com --add 'URL301 old https://new.example.com'` |
|
|
62
|
+
| Third-party mail (MX) | `$NC set example.com --add 'MX @ mx1.provider.com. 1800 10'` |
|
|
63
|
+
| Replace a conflicting record | add `--replace` (without it the tool refuses and shows the clash) |
|
|
64
|
+
| Remove a record | `$NC set example.com --remove 'CNAME old'` (value optional) |
|
|
65
|
+
| Free email forwarding | `$NC forward example.com --add hello=you@example.com` (refuses to cut off live MX mail unless `--force`) |
|
|
66
|
+
|
|
67
|
+
Verify with `$NC list` (Namecheap's view, already re-read after the write) and
|
|
68
|
+
`$NC lookup example.com A` (public DNS, after the TTL).
|
|
69
|
+
|
|
70
|
+
## 3. Registrar settings
|
|
71
|
+
|
|
72
|
+
| Goal | Command |
|
|
73
|
+
|---|---|
|
|
74
|
+
| Move DNS to another host (Vercel, Cloudflare, …) | `$NC nameservers example.com --set ns1.host.com ns2.host.com --yes` |
|
|
75
|
+
| Back to Namecheap BasicDNS | `$NC nameservers example.com --default --yes` |
|
|
76
|
+
| Transfer lock | `$NC lock example.com --on` / `--off` (off only to transfer it out) |
|
|
77
|
+
| Domain privacy | `$NC privacy example.com --on` / `--off`; `$NC privacy` lists all |
|
|
78
|
+
|
|
79
|
+
Switching nameservers moves the whole domain: copy the records to the new host
|
|
80
|
+
first, or mail and verification break. The tool asks for `--yes` for that reason.
|
|
81
|
+
|
|
82
|
+
## 4. Buying and renewing (spends money)
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
$NC available idea.dev other.com # free? premium?
|
|
86
|
+
$NC price dev # your register price; --action renew|transfer, --years N
|
|
87
|
+
$NC renew example.com --years 1 # prints price + balance, charges nothing
|
|
88
|
+
$NC register idea.dev --contacts-from example.com # same: prints, charges nothing
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Anything that charges the account does nothing without `--yes`. **Before
|
|
92
|
+
adding `--yes`, tell the user the item and total and get a clear yes in chat**,
|
|
93
|
+
every time; a yes for one purchase does not cover the next. Registration copies
|
|
94
|
+
WHOIS contacts from a domain the user already owns and turns free privacy on.
|
|
95
|
+
Premium names are refused (they need the dashboard). Payment comes from the
|
|
96
|
+
account balance; if it is short, say so and stop.
|
|
97
|
+
|
|
98
|
+
## 5. Report
|
|
99
|
+
|
|
100
|
+
Say what changed (before → after), the backup path for record writes, what
|
|
101
|
+
`lookup` shows publicly, anything still propagating, and for purchases the
|
|
102
|
+
amount charged and the order id.
|
|
103
|
+
|
|
104
|
+
## 6. When access is missing
|
|
105
|
+
|
|
106
|
+
The tool reads `NAMECHEAP_API_USER` / `NAMECHEAP_API_KEY` (optionally
|
|
107
|
+
`NAMECHEAP_USERNAME`, `NAMECHEAP_CLIENT_IP`) from the environment or
|
|
108
|
+
`~/.config/namecheap/credentials.env`. On a Rudder cloud machine the environment
|
|
109
|
+
comes from the Rudder secrets vault; `env | grep -c NAMECHEAP` shows whether it
|
|
110
|
+
has them.
|
|
111
|
+
|
|
112
|
+
If the tool prints `NO_NAMECHEAP_CREDENTIALS`, or an API error naming an IP that
|
|
113
|
+
isn't whitelisted, first do everything that doesn't need Namecheap. Then send
|
|
114
|
+
the user one short message with only this:
|
|
115
|
+
|
|
116
|
+
1. Namecheap → Profile → Tools → **Namecheap API Access** → ON. Namecheap
|
|
117
|
+
requires a $50 balance, $50 spent in the last two years, or 20 domains.
|
|
118
|
+
2. **Whitelisted IPs** → add the IP the tool printed (this machine's public
|
|
119
|
+
IPv4; only IPv4 works).
|
|
120
|
+
3. Store the key once, from their computer, so every Rudder cloud machine has
|
|
121
|
+
it: `rudder cloud secrets set NAMECHEAP_API_USER <namecheap-username>` and
|
|
122
|
+
`rudder cloud secrets set NAMECHEAP_API_KEY` (prompts for the value). For
|
|
123
|
+
this machine only: `! <this skill dir>/scripts/namecheap setup <namecheap-username>`
|
|
124
|
+
(prompts for the key).
|
|
125
|
+
|
|
126
|
+
Never print the key, commit it, put it in a URL or pass it as a command-line
|
|
127
|
+
argument. Never sign in to the Namecheap dashboard yourself: the account
|
|
128
|
+
password is the user's. A cloud machine's outbound IP can change on restart;
|
|
129
|
+
when Namecheap rejects a call, the error names the new IP. Whitelist it too, or
|
|
130
|
+
pin a static egress IP, which costs money and needs the user's go-ahead.
|