@ssheleg/sheleg-dev 0.4.0

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 (32) hide show
  1. package/CHANGELOG.md +172 -0
  2. package/LICENSE +21 -0
  3. package/README.md +132 -0
  4. package/SECURITY.md +63 -0
  5. package/bin/sheleg-dev.js +99 -0
  6. package/package.json +45 -0
  7. package/plugins/sheleg-dev/.claude-plugin/plugin.json +28 -0
  8. package/plugins/sheleg-dev/skills/ad-tracking/SKILL.md +442 -0
  9. package/plugins/sheleg-dev/skills/ad-tracking/references/consent-mode.md +257 -0
  10. package/plugins/sheleg-dev/skills/ad-tracking/references/event-tracking.md +201 -0
  11. package/plugins/sheleg-dev/skills/ad-tracking/references/gtag-api.md +389 -0
  12. package/plugins/sheleg-dev/skills/ad-tracking/references/meta-linkedin.md +103 -0
  13. package/plugins/sheleg-dev/skills/ad-tracking/references/performance-security.md +288 -0
  14. package/plugins/sheleg-dev/skills/crypto-payments/SKILL.md +384 -0
  15. package/plugins/sheleg-dev/skills/crypto-payments/references/heleket-provider.md +1357 -0
  16. package/plugins/sheleg-dev/skills/frontend-performance/SKILL.md +147 -0
  17. package/plugins/sheleg-dev/skills/frontend-performance/references/accessibility-perf.md +172 -0
  18. package/plugins/sheleg-dev/skills/frontend-performance/references/css-performance.md +180 -0
  19. package/plugins/sheleg-dev/skills/frontend-performance/references/nextjs.md +271 -0
  20. package/plugins/sheleg-dev/skills/google-auth/SKILL.md +275 -0
  21. package/plugins/sheleg-dev/skills/google-auth/references/adc-and-service-accounts.md +464 -0
  22. package/plugins/sheleg-dev/skills/google-auth/references/oauth2-web-server.md +615 -0
  23. package/plugins/sheleg-dev/skills/google-auth/references/sign-in-with-google.md +593 -0
  24. package/plugins/sheleg-dev/skills/google-auth/references/workload-identity.md +376 -0
  25. package/plugins/sheleg-dev/skills/google-signin/SKILL.md +121 -0
  26. package/plugins/sheleg-dev/skills/google-signin/references/full-guide.md +421 -0
  27. package/plugins/sheleg-dev/skills/stripe-billing/SKILL.md +458 -0
  28. package/plugins/sheleg-dev/skills/stripe-billing/references/price-integrity.md +201 -0
  29. package/plugins/sheleg-dev/skills/stripe-billing/references/stripe-agent-toolchain.md +173 -0
  30. package/plugins/sheleg-dev/skills/stripe-billing/references/subscription-lifecycle.md +294 -0
  31. package/plugins/sheleg-dev/skills/stripe-billing/references/testing-and-local-dev.md +214 -0
  32. package/plugins/sheleg-dev/skills/stripe-billing/references/webhook-events.md +211 -0
@@ -0,0 +1,464 @@
1
+ # Application Default Credentials & Service Accounts (Node.js & Python)
2
+
3
+
4
+ ## Contents
5
+
6
+ - [Table of Contents](#table-of-contents)
7
+ - [ADC Overview](#adc-overview)
8
+ - [ADC Search Order](#adc-search-order)
9
+ - [Setting Up ADC](#setting-up-adc)
10
+ - [Using ADC in Code](#using-adc-in-code)
11
+ - [Service Account Keys (JWT)](#service-account-keys-jwt)
12
+ - [Compute Credentials](#compute-credentials)
13
+ - [Impersonated Credentials](#impersonated-credentials)
14
+ - [Downscoped Client](#downscoped-client)
15
+ - [ID Tokens](#id-tokens)
16
+ - [Environment Variables](#environment-variables)
17
+
18
+ ## Table of Contents
19
+ - [ADC Overview](#adc-overview)
20
+ - [ADC Search Order](#adc-search-order)
21
+ - [Setting Up ADC](#setting-up-adc)
22
+ - [Using ADC in Code](#using-adc-in-code)
23
+ - [Service Account Keys (JWT)](#service-account-keys-jwt)
24
+ - [Compute Credentials](#compute-credentials)
25
+ - [Impersonated Credentials](#impersonated-credentials)
26
+ - [Downscoped Client](#downscoped-client)
27
+ - [ID Tokens](#id-tokens)
28
+ - [Environment Variables](#environment-variables)
29
+
30
+ ## ADC Overview
31
+
32
+ Application Default Credentials (ADC) automatically finds credentials based on the environment. Best for server-to-server and same-identity-for-all-users scenarios.
33
+
34
+ ## ADC Search Order
35
+
36
+ 1. **Attached service account** — via GCP metadata server (Compute Engine, Cloud Run, GKE, etc.)
37
+ 2. **`gcloud auth application-default login`** — local credential file
38
+ 3. **`GOOGLE_APPLICATION_CREDENTIALS`** — env var pointing to a credential JSON file
39
+
40
+ Credential file locations from `gcloud auth application-default login`:
41
+ - **macOS/Linux**: `$HOME/.config/gcloud/application_default_credentials.json`
42
+ - **Windows**: `%APPDATA%\gcloud\application_default_credentials.json`
43
+
44
+ ## Setting Up ADC
45
+
46
+ ### Local Development
47
+
48
+ ```bash
49
+ # Login with user credentials (generates local ADC file)
50
+ gcloud auth application-default login
51
+
52
+ # With specific scopes
53
+ gcloud auth application-default login \
54
+ --scopes=https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/drive
55
+
56
+ # With service account impersonation
57
+ gcloud auth application-default login \
58
+ --impersonate-service-account=SA_EMAIL@PROJECT.iam.gserviceaccount.com
59
+ ```
60
+
61
+ ### Production (GCP)
62
+
63
+ Attach a service account to the resource (Compute Engine VM, Cloud Run service, GKE pod, etc.). No code changes needed — ADC uses the metadata server automatically.
64
+
65
+ ### External Environments
66
+
67
+ Set `GOOGLE_APPLICATION_CREDENTIALS` to point to a credential JSON file:
68
+
69
+ ```bash
70
+ export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account-key.json
71
+ # Or a workload identity federation config:
72
+ export GOOGLE_APPLICATION_CREDENTIALS=/path/to/workload-config.json
73
+ ```
74
+
75
+ ## Using ADC in Code
76
+
77
+ ### Node.js
78
+
79
+ ```js
80
+ const {GoogleAuth} = require('google-auth-library');
81
+
82
+ const auth = new GoogleAuth({
83
+ scopes: 'https://www.googleapis.com/auth/cloud-platform'
84
+ });
85
+
86
+ const client = await auth.getClient();
87
+ const projectId = await auth.getProjectId();
88
+ const url = `https://dns.googleapis.com/dns/v1/projects/${projectId}`;
89
+ const res = await client.fetch(url);
90
+ ```
91
+
92
+ #### With googleapis
93
+
94
+ ```js
95
+ const {google} = require('googleapis');
96
+
97
+ const auth = new google.auth.GoogleAuth({
98
+ scopes: ['https://www.googleapis.com/auth/cloud-platform']
99
+ });
100
+ const authClient = await auth.getClient();
101
+ google.options({auth: authClient});
102
+
103
+ const storage = google.storage('v1');
104
+ const buckets = await storage.buckets.list({project: projectId});
105
+ ```
106
+
107
+ ### Python
108
+
109
+ ```python
110
+ import google.auth
111
+
112
+ credentials, project = google.auth.default()
113
+
114
+ # With specific scopes:
115
+ credentials, project = google.auth.default(
116
+ scopes=['https://www.googleapis.com/auth/cloud-platform']
117
+ )
118
+ ```
119
+
120
+ #### With google-api-python-client
121
+
122
+ ```python
123
+ from googleapiclient.discovery import build
124
+ import google.auth
125
+
126
+ credentials, project = google.auth.default(
127
+ scopes=['https://www.googleapis.com/auth/cloud-platform']
128
+ )
129
+ storage = build('storage', 'v1', credentials=credentials)
130
+ buckets = storage.buckets().list(project=project).execute()
131
+ ```
132
+
133
+ #### With authorized requests
134
+
135
+ ```python
136
+ import google.auth
137
+ import google.auth.transport.requests
138
+
139
+ credentials, project = google.auth.default(
140
+ scopes=['https://www.googleapis.com/auth/cloud-platform']
141
+ )
142
+ request = google.auth.transport.requests.Request()
143
+ credentials.refresh(request)
144
+
145
+ # Use with requests library
146
+ authed_session = google.auth.transport.requests.AuthorizedSession(credentials)
147
+ response = authed_session.get('https://storage.googleapis.com/...')
148
+ ```
149
+
150
+ #### Load from file explicitly
151
+
152
+ ```python
153
+ import google.auth
154
+
155
+ credentials, project = google.auth.load_credentials_from_file(
156
+ '/path/to/credentials.json',
157
+ scopes=['https://www.googleapis.com/auth/cloud-platform']
158
+ )
159
+ ```
160
+
161
+ ## Service Account Keys (JWT)
162
+
163
+ ### Node.js — From JSON Key File
164
+
165
+ ```js
166
+ const {JWT} = require('google-auth-library');
167
+ const keys = require('./service-account-key.json');
168
+
169
+ const client = new JWT({
170
+ email: keys.client_email,
171
+ key: keys.private_key,
172
+ scopes: ['https://www.googleapis.com/auth/cloud-platform'],
173
+ });
174
+ const res = await client.fetch(url);
175
+ ```
176
+
177
+ ### Node.js — From Environment Variable
178
+
179
+ ```js
180
+ const {JWT} = require('google-auth-library');
181
+
182
+ const keysEnvVar = process.env['GOOGLE_CREDENTIALS'];
183
+ if (!keysEnvVar) throw new Error('GOOGLE_CREDENTIALS not set');
184
+ const keys = JSON.parse(keysEnvVar);
185
+
186
+ const client = new JWT({
187
+ email: keys.client_email,
188
+ key: keys.private_key,
189
+ scopes: ['https://www.googleapis.com/auth/cloud-platform'],
190
+ });
191
+ ```
192
+
193
+ ### Python — From JSON Key File
194
+
195
+ ```python
196
+ from google.oauth2 import service_account
197
+
198
+ credentials = service_account.Credentials.from_service_account_file(
199
+ 'service-account-key.json',
200
+ scopes=['https://www.googleapis.com/auth/cloud-platform']
201
+ )
202
+ ```
203
+
204
+ ### Python — From Dictionary
205
+
206
+ ```python
207
+ import json
208
+ from google.oauth2 import service_account
209
+
210
+ info = json.loads(os.environ['GOOGLE_CREDENTIALS'])
211
+ credentials = service_account.Credentials.from_service_account_info(
212
+ info,
213
+ scopes=['https://www.googleapis.com/auth/cloud-platform']
214
+ )
215
+ ```
216
+
217
+ ### Python — With Subject (Domain-Wide Delegation)
218
+
219
+ ```python
220
+ from google.oauth2 import service_account
221
+
222
+ credentials = service_account.Credentials.from_service_account_file(
223
+ 'service-account-key.json',
224
+ scopes=['https://www.googleapis.com/auth/gmail.readonly'],
225
+ subject='user@yourdomain.com'
226
+ )
227
+ ```
228
+
229
+ ### Service Account Key JSON Structure
230
+
231
+ ```json
232
+ {
233
+ "type": "service_account",
234
+ "project_id": "your-project-id",
235
+ "private_key_id": "key-id",
236
+ "private_key": "-----BEGIN RSA PRIVATE KEY-----\n...",
237
+ "client_email": "sa-name@project-id.iam.gserviceaccount.com",
238
+ "client_id": "123456789",
239
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
240
+ "token_uri": "https://oauth2.googleapis.com/token",
241
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
242
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/..."
243
+ }
244
+ ```
245
+
246
+ **Security**: Service account keys are a security risk. Prefer Workload Identity Federation or attached service accounts. If using keys, rotate regularly and restrict access.
247
+
248
+ ## Compute Credentials
249
+
250
+ For code running on GCP with an attached service account.
251
+
252
+ ### Node.js
253
+
254
+ ```js
255
+ const {auth, Compute} = require('google-auth-library');
256
+
257
+ const client = new Compute({
258
+ serviceAccountEmail: 'my-sa@project.iam.gserviceaccount.com' // optional
259
+ });
260
+ const projectId = await auth.getProjectId();
261
+ const res = await client.fetch(url);
262
+ ```
263
+
264
+ In most cases, prefer `GoogleAuth` (ADC) over direct `Compute` usage.
265
+
266
+ ### Python
267
+
268
+ ```python
269
+ from google.auth import compute_engine
270
+
271
+ credentials = compute_engine.Credentials(
272
+ service_account_email='my-sa@project.iam.gserviceaccount.com' # optional
273
+ )
274
+ ```
275
+
276
+ In most cases, prefer `google.auth.default()` (ADC) over direct `compute_engine.Credentials`.
277
+
278
+ ## Impersonated Credentials
279
+
280
+ Use IAM Credentials API to impersonate a target service account.
281
+
282
+ ### Node.js
283
+
284
+ ```js
285
+ const {GoogleAuth, Impersonated} = require('google-auth-library');
286
+
287
+ const auth = new GoogleAuth();
288
+ const sourceClient = await auth.getClient();
289
+
290
+ const targetClient = new Impersonated({
291
+ sourceClient: sourceClient,
292
+ targetPrincipal: 'target-sa@project.iam.gserviceaccount.com',
293
+ lifetime: 30, // seconds
294
+ delegates: [], // optional chain
295
+ targetScopes: ['https://www.googleapis.com/auth/cloud-platform']
296
+ });
297
+
298
+ const res = await targetClient.fetch(url);
299
+ ```
300
+
301
+ ### Python
302
+
303
+ ```python
304
+ from google.auth import impersonated_credentials
305
+ import google.auth
306
+
307
+ source_credentials, _ = google.auth.default()
308
+
309
+ target_credentials = impersonated_credentials.Credentials(
310
+ source_credentials=source_credentials,
311
+ target_principal='target-sa@project.iam.gserviceaccount.com',
312
+ target_scopes=['https://www.googleapis.com/auth/cloud-platform'],
313
+ lifetime=300 # seconds (default: 3600)
314
+ )
315
+ ```
316
+
317
+ The source credential needs the **Service Account Token Creator** role (`roles/iam.serviceAccountTokenCreator`).
318
+
319
+ ## Downscoped Client
320
+
321
+ Restrict permissions of a short-lived credential (Cloud Storage only).
322
+
323
+ ### Node.js
324
+
325
+ ```js
326
+ const {GoogleAuth, DownscopedClient} = require('google-auth-library');
327
+
328
+ const auth = new GoogleAuth({scopes: 'https://www.googleapis.com/auth/cloud-platform'});
329
+ const client = await auth.getClient();
330
+
331
+ const cab = {
332
+ accessBoundary: {
333
+ accessBoundaryRules: [{
334
+ availablePermissions: ['inRole:roles/storage.objectViewer'],
335
+ availableResource: '//storage.googleapis.com/projects/_/buckets/my-bucket',
336
+ availabilityCondition: {
337
+ expression: "resource.name.startsWith('projects/_/buckets/my-bucket/objects/prefix')"
338
+ }
339
+ }]
340
+ }
341
+ };
342
+
343
+ const downscopedClient = new DownscopedClient(client, cab);
344
+ const refreshedAccessToken = await downscopedClient.getAccessToken();
345
+ ```
346
+
347
+ ### Python
348
+
349
+ ```python
350
+ from google.auth import _default
351
+ from google.auth import credentials as ga_credentials
352
+ import google.auth
353
+
354
+ credentials, _ = google.auth.default(
355
+ scopes=['https://www.googleapis.com/auth/cloud-platform']
356
+ )
357
+
358
+ # Downscoping is done via the STS API; the Python library exposes it through
359
+ # google.auth.downscoped.DownscopedCredentials (available in google-auth >= 2.0):
360
+ from google.auth import downscoped
361
+
362
+ credential_access_boundary = downscoped.CredentialAccessBoundary(rules=[
363
+ downscoped.AccessBoundaryRule(
364
+ available_resource='//storage.googleapis.com/projects/_/buckets/my-bucket',
365
+ available_permissions=['inRole:roles/storage.objectViewer'],
366
+ )
367
+ ])
368
+
369
+ downscoped_credentials = downscoped.DownscopedCredentials(
370
+ source_credentials=credentials,
371
+ credential_access_boundary=credential_access_boundary
372
+ )
373
+ ```
374
+
375
+ ## ID Tokens
376
+
377
+ ### Fetching ID Tokens (for Cloud Run / Cloud Functions / IAP)
378
+
379
+ #### Node.js
380
+
381
+ ```js
382
+ const {GoogleAuth} = require('google-auth-library');
383
+
384
+ const targetUrl = 'https://cloud-run-1234-uc.a.run.app';
385
+ const auth = new GoogleAuth();
386
+ const client = await auth.getIdTokenClient(targetUrl);
387
+ const res = await client.fetch(targetUrl);
388
+ ```
389
+
390
+ #### Python
391
+
392
+ ```python
393
+ import google.oauth2.id_token
394
+ import google.auth.transport.requests
395
+
396
+ request = google.auth.transport.requests.Request()
397
+ target_audience = 'https://cloud-run-1234-uc.a.run.app'
398
+
399
+ # Fetch a raw ID token string
400
+ token = google.oauth2.id_token.fetch_id_token(request, target_audience)
401
+
402
+ # Or get refreshable ID token credentials
403
+ credentials = google.oauth2.id_token.fetch_id_token_credentials(
404
+ target_audience, request=request
405
+ )
406
+ credentials.refresh(request)
407
+ # credentials.token is the ID token
408
+ ```
409
+
410
+ #### Python — Service Account ID Token
411
+
412
+ ```python
413
+ from google.oauth2 import service_account
414
+
415
+ credentials = service_account.IDTokenCredentials.from_service_account_file(
416
+ 'service-account-key.json',
417
+ target_audience='https://cloud-run-1234-uc.a.run.app'
418
+ )
419
+ request = google.auth.transport.requests.Request()
420
+ credentials.refresh(request)
421
+ # credentials.token is the ID token
422
+ ```
423
+
424
+ ### Verifying IAP Headers
425
+
426
+ #### Node.js
427
+
428
+ ```js
429
+ const {OAuth2Client} = require('google-auth-library');
430
+
431
+ const client = new OAuth2Client();
432
+ const response = await client.getIapCerts();
433
+ const ticket = await client.verifySignedJwtWithCertsAsync(
434
+ idToken,
435
+ response.pubkeys,
436
+ `/projects/PROJECT_NUMBER/apps/PROJECT_ID`,
437
+ ['https://cloud.google.com/iap']
438
+ );
439
+ ```
440
+
441
+ #### Python
442
+
443
+ ```python
444
+ from google.oauth2 import id_token
445
+ from google.auth.transport import requests
446
+
447
+ request = requests.Request()
448
+
449
+ decoded = id_token.verify_token(
450
+ iap_jwt,
451
+ request,
452
+ audience=f'/projects/{PROJECT_NUMBER}/apps/{PROJECT_ID}',
453
+ certs_url='https://www.gstatic.com/iap/verify/public_key'
454
+ )
455
+ ```
456
+
457
+ ## Environment Variables
458
+
459
+ | Variable | Purpose |
460
+ |----------|---------|
461
+ | `GOOGLE_APPLICATION_CREDENTIALS` | Path to credential JSON file |
462
+ | `GOOGLE_CLOUD_PROJECT` | Default project ID |
463
+ | `GCLOUD_PROJECT` | Alias for project ID |
464
+ | `HTTPS_PROXY` / `https_proxy` | Proxy for HTTPS requests |