@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,271 @@
1
+ # Next.js Performance Patterns
2
+
3
+
4
+ ## Contents
5
+
6
+ - [Font Optimization with `next/font`](#font-optimization-with-nextfont)
7
+ - [Code Splitting with `next/dynamic`](#code-splitting-with-nextdynamic)
8
+ - [Cache Headers in `next.config.ts`](#cache-headers-in-nextconfigts)
9
+ - [Content Security Policy](#content-security-policy)
10
+ - [Script Loading Strategy](#script-loading-strategy)
11
+ - [Image Optimization](#image-optimization)
12
+ - [Bundle Analysis](#bundle-analysis)
13
+ - [Browserslist Configuration](#browserslist-configuration)
14
+
15
+ ## Font Optimization with `next/font`
16
+
17
+ ### Migration from `<link>` to `next/font/google`
18
+
19
+ Replace external Google Fonts links with `next/font/google` imports. This:
20
+ - Inlines font CSS at build time (no render-blocking request)
21
+ - Self-hosts font files from `/_next/static/` (no external dependency)
22
+ - Eliminates need for `preconnect` hints and Google Fonts CSP entries
23
+ - Enables automatic subsetting
24
+
25
+ **Before (bad):**
26
+ ```tsx
27
+ // layout.tsx
28
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
29
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
30
+ <link href="https://fonts.googleapis.com/css2?family=DM+Sans&family=Outfit&display=swap" rel="stylesheet" />
31
+ ```
32
+
33
+ **After (good):**
34
+ ```tsx
35
+ // layout.tsx
36
+ import { DM_Sans, Outfit } from "next/font/google";
37
+
38
+ const dmSans = DM_Sans({
39
+ subsets: ["latin"],
40
+ variable: "--font-dm-sans",
41
+ weight: ["400", "500", "600", "700"],
42
+ display: "swap",
43
+ });
44
+
45
+ const outfit = Outfit({
46
+ subsets: ["latin"],
47
+ variable: "--font-outfit",
48
+ weight: ["400", "500", "600", "700", "800"],
49
+ display: "swap",
50
+ });
51
+
52
+ export default function RootLayout({ children }) {
53
+ return (
54
+ <html lang="en" className={`${dmSans.variable} ${outfit.variable}`}>
55
+ <body>{children}</body>
56
+ </html>
57
+ );
58
+ }
59
+ ```
60
+
61
+ Then reference via CSS variables in `globals.css`:
62
+ ```css
63
+ body { font-family: var(--font-dm-sans), system-ui, sans-serif; }
64
+ h1, h2, h3 { font-family: var(--font-outfit), system-ui, sans-serif; }
65
+ ```
66
+
67
+ ### Multiple Font Families
68
+
69
+ Load only fonts actually used. Each family adds ~20-50KB. Three families is a practical maximum for landing pages.
70
+
71
+ If using variable fonts (weight ranges), specify the range:
72
+ ```tsx
73
+ const dmSans = DM_Sans({
74
+ subsets: ["latin"],
75
+ variable: "--font-dm-sans",
76
+ weight: ["400", "500", "600", "700"], // or omit for variable font full range
77
+ display: "swap",
78
+ });
79
+ ```
80
+
81
+ ## Code Splitting with `next/dynamic`
82
+
83
+ Lazy-load below-the-fold sections to reduce initial JavaScript bundle:
84
+
85
+ ```tsx
86
+ import dynamic from "next/dynamic";
87
+
88
+ // Above-the-fold: import normally
89
+ import { HeroSection } from "@/components/hero";
90
+ import { Navbar } from "@/components/navbar";
91
+
92
+ // Below-the-fold: lazy load
93
+ const Testimonials = dynamic(() =>
94
+ import("@/components/testimonials").then((m) => m.TestimonialsSection)
95
+ );
96
+ const FAQ = dynamic(() =>
97
+ import("@/components/faq").then((m) => m.FAQSection)
98
+ );
99
+ const Pricing = dynamic(() =>
100
+ import("@/components/pricing").then((m) => m.PricingSection)
101
+ );
102
+ ```
103
+
104
+ Only use `next/dynamic` for components that are:
105
+ - Below the initial viewport (not visible without scrolling)
106
+ - Heavy (> 10KB compressed)
107
+ - Not critical for SEO (search engines execute JS but slower)
108
+
109
+ Do NOT dynamically import the hero, navbar, or footer -- these must render immediately.
110
+
111
+ ## Cache Headers in `next.config.ts`
112
+
113
+ Add cache headers for static assets:
114
+
115
+ ```typescript
116
+ // next.config.ts
117
+ const nextConfig = {
118
+ async headers() {
119
+ return [
120
+ {
121
+ source: "/:path*.:ext(svg|png|jpg|jpeg|gif|webp|ico|woff|woff2)",
122
+ headers: [
123
+ {
124
+ key: "Cache-Control",
125
+ value: "public, max-age=31536000, immutable",
126
+ },
127
+ ],
128
+ },
129
+ ];
130
+ },
131
+ };
132
+ ```
133
+
134
+ **Critical:** Next.js uses `path-to-regexp` for route matching. Common pattern mistakes:
135
+
136
+ | Pattern | Works? | Why |
137
+ |---------|--------|-----|
138
+ | `/:path*{.svg,.png}` | No | Braces are literal in path-to-regexp |
139
+ | `/:path*.(svg\|png)` | No | Pipe needs to be inside a named param |
140
+ | `/:path*.:ext(svg\|png\|jpg)` | Yes | Regex parameter syntax |
141
+
142
+ Test patterns before deploying:
143
+ ```javascript
144
+ const { match } = require("path-to-regexp");
145
+ const fn = match("/:path*.:ext(svg|png|jpg)");
146
+ console.log(fn("/logo.svg")); // { params: { path: ["logo"], ext: "svg" } }
147
+ console.log(fn("/page")); // false
148
+ ```
149
+
150
+ ## Content Security Policy
151
+
152
+ Configure CSP in `next.config.ts` security headers:
153
+
154
+ ```typescript
155
+ {
156
+ source: "/(.*)",
157
+ headers: [
158
+ {
159
+ key: "Content-Security-Policy",
160
+ value: [
161
+ "default-src 'self'",
162
+ "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.googletagmanager.com https://www.google-analytics.com https://static.cloudflareinsights.com",
163
+ "style-src 'self' 'unsafe-inline'",
164
+ "img-src 'self' data: blob: https:",
165
+ "font-src 'self'",
166
+ "connect-src 'self' https://www.google-analytics.com https://vitals.vercel-insights.com",
167
+ ].join("; "),
168
+ },
169
+ ],
170
+ }
171
+ ```
172
+
173
+ **Rules:**
174
+ - After migrating fonts to `next/font`, remove `fonts.googleapis.com` from `style-src` and `fonts.gstatic.com` from `font-src` -- self-hosted fonts are covered by `'self'`.
175
+ - Every new third-party script/style requires a CSP update.
176
+ - CSP violations show as console errors and directly lower the Best Practices score.
177
+
178
+ ## Script Loading Strategy
179
+
180
+ Use `next/script` for third-party scripts:
181
+
182
+ ```tsx
183
+ import Script from "next/script";
184
+
185
+ // Google Analytics -- load after page is interactive
186
+ <Script
187
+ src={`https://www.googletagmanager.com/gtag/js?id=${GA_ID}`}
188
+ strategy="afterInteractive"
189
+ />
190
+ ```
191
+
192
+ | Strategy | When | Use For |
193
+ |----------|------|---------|
194
+ | `beforeInteractive` | Before hydration | Critical polyfills, A/B test scripts |
195
+ | `afterInteractive` | After hydration (default) | Analytics, tracking |
196
+ | `lazyOnload` | After everything | Chat widgets, social embeds |
197
+ | `worker` | In web worker (experimental) | Heavy non-critical scripts |
198
+
199
+ Never use raw `<script>` tags in Next.js -- they bypass optimization.
200
+
201
+ ## Image Optimization
202
+
203
+ ```tsx
204
+ import Image from "next/image";
205
+
206
+ // LCP hero image -- priority load
207
+ <Image
208
+ src="/hero.webp"
209
+ alt="Product dashboard showing analytics"
210
+ width={1200}
211
+ height={630}
212
+ priority
213
+ sizes="100vw"
214
+ />
215
+
216
+ // Below-fold image -- lazy load (default)
217
+ <Image
218
+ src="/feature.webp"
219
+ alt="Feature screenshot"
220
+ width={600}
221
+ height={400}
222
+ sizes="(max-width: 768px) 100vw, 50vw"
223
+ />
224
+ ```
225
+
226
+ **Rules:**
227
+ - Always set `priority` on the LCP image (usually the hero).
228
+ - Always provide `sizes` for responsive images.
229
+ - Always provide `width` and `height` to prevent CLS.
230
+ - Use `alt=""` for decorative images (logos next to brand text).
231
+ - Remote images require `remotePatterns` in `next.config.ts`.
232
+
233
+ ## Bundle Analysis
234
+
235
+ ```bash
236
+ # Install analyzer
237
+ npm install -D @next/bundle-analyzer
238
+
239
+ # Add to next.config.ts
240
+ const withBundleAnalyzer = require("@next/bundle-analyzer")({
241
+ enabled: process.env.ANALYZE === "true",
242
+ });
243
+ module.exports = withBundleAnalyzer(nextConfig);
244
+
245
+ # Run analysis
246
+ ANALYZE=true next build
247
+ ```
248
+
249
+ Look for:
250
+ - Large dependencies (lodash, moment.js) that can be replaced
251
+ - Duplicate packages across chunks
252
+ - Server-only code leaking into client bundles
253
+
254
+ ## Browserslist Configuration
255
+
256
+ Add to `package.json` to reduce polyfill shipping:
257
+
258
+ ```json
259
+ {
260
+ "browserslist": [
261
+ "last 2 Chrome versions",
262
+ "last 2 Firefox versions",
263
+ "last 2 Safari versions",
264
+ "last 2 Edge versions"
265
+ ]
266
+ }
267
+ ```
268
+
269
+ This tells SWC to skip polyfills for `Array.prototype.at`, `Object.fromEntries`, `String.prototype.trimStart`, etc. Saves ~10-15KB on typical bundles.
270
+
271
+ Note: Some polyfills are bundled by Next.js core and cannot be eliminated via `browserslist`.
@@ -0,0 +1,275 @@
1
+ ---
2
+ name: google-auth
3
+ description: >-
4
+ Use when implementing Google authentication in a Node.js or Python web application — Google
5
+ login, OAuth 2.0 flows, verifying Google ID tokens, service account authentication,
6
+ Application Default Credentials, Google Identity Services, Workload Identity Federation, API
7
+ keys, or working with google-auth-library (Node.js) or google-auth (Python). Covers ID token
8
+ verification and security best practices. Triggers - "google auth", "google login", "google
9
+ sign in", "OAuth 2.0 Google", "google-auth-library", "Sign In with Google", "Google Identity
10
+ Services", "GIS", "ADC", "Application Default Credentials", "service account", "Google ID
11
+ token", "verifyIdToken", "GOOGLE_APPLICATION_CREDENTIALS", "Google SSO", "вход через Google",
12
+ "авторизация Google", "сервисный аккаунт", "проверить ID-токен", "гугл-логин". For end-user
13
+ web sign-in only, use the google-signin skill instead.
14
+ ---
15
+
16
+ # Google Authentication for Node.js & Python
17
+
18
+ ## Libraries
19
+
20
+ ### Node.js
21
+
22
+ - `google-auth-library` — core auth library (OAuth2Client, GoogleAuth, JWT, Compute, Impersonated)
23
+ - `googleapis` — Google API client (wraps google-auth-library)
24
+
25
+ ```bash
26
+ npm install google-auth-library
27
+ npm install googleapis
28
+ ```
29
+
30
+ ### Python
31
+
32
+ - `google-auth` — core auth library (google.oauth2, google.auth, credentials, transport)
33
+ - `google-auth-oauthlib` — OAuth 2.0 user-credential flow helpers (Flow, InstalledAppFlow)
34
+ - `google-api-python-client` — Google API client (wraps google-auth)
35
+
36
+ ```bash
37
+ pip install google-auth
38
+ pip install google-auth-oauthlib
39
+ pip install google-api-python-client
40
+ ```
41
+
42
+ ## Authentication Methods Overview
43
+
44
+ | Method | Use Case | Node.js Key Class | Python Key Module / Class |
45
+ |--------|----------|-------------------|---------------------------|
46
+ | **ADC** | Same identity for all users, server-to-server | `GoogleAuth` | `google.auth.default()` |
47
+ | **OAuth 2.0** | Actions on behalf of end users | `OAuth2Client` | `google_auth_oauthlib.flow.Flow` |
48
+ | **Sign In with Google (GIS)** | User sign-in/sign-up on websites | GIS JS SDK + `verifyIdToken()` | GIS JS SDK + `id_token.verify_oauth2_token()` |
49
+ | **JWT / Service Account** | Server-to-server, single identity | `JWT` | `service_account.Credentials` |
50
+ | **API Key** | Public data, no user context | `OAuth2Client({ apiKey })` | passed to `googleapiclient.discovery.build(developerKey=)` |
51
+ | **Compute** | On GCP with attached service account | `Compute` | `google.auth.compute_engine.Credentials` |
52
+ | **Workload Identity Federation** | AWS/Azure/OIDC → GCP without SA keys | `ExternalAccountClient` | `google.auth.identity_pool.Credentials` / `google.auth.aws.Credentials` |
53
+
54
+ ## Quick Patterns
55
+
56
+ ### 1. Application Default Credentials (ADC)
57
+
58
+ **Node.js**
59
+
60
+ ```js
61
+ const {GoogleAuth} = require('google-auth-library');
62
+
63
+ const auth = new GoogleAuth({
64
+ scopes: 'https://www.googleapis.com/auth/cloud-platform'
65
+ });
66
+ const client = await auth.getClient();
67
+ const res = await client.fetch('https://dns.googleapis.com/dns/v1/projects/...');
68
+ ```
69
+
70
+ **Python**
71
+
72
+ ```python
73
+ import google.auth
74
+ import google.auth.transport.requests
75
+
76
+ credentials, project = google.auth.default(
77
+ scopes=['https://www.googleapis.com/auth/cloud-platform']
78
+ )
79
+ request = google.auth.transport.requests.Request()
80
+ credentials.refresh(request)
81
+ ```
82
+
83
+ ADC search order: attached service account → `gcloud auth application-default login` file → `GOOGLE_APPLICATION_CREDENTIALS` env var.
84
+
85
+ For detailed ADC setup and service account usage, see [references/adc-and-service-accounts.md](references/adc-and-service-accounts.md).
86
+
87
+ ### 2. OAuth 2.0 Web Server Flow
88
+
89
+ **Node.js**
90
+
91
+ ```js
92
+ const {OAuth2Client} = require('google-auth-library');
93
+
94
+ const client = new OAuth2Client({
95
+ clientId: CLIENT_ID,
96
+ clientSecret: CLIENT_SECRET,
97
+ redirectUri: REDIRECT_URI
98
+ });
99
+
100
+ const authUrl = client.generateAuthUrl({
101
+ access_type: 'offline',
102
+ scope: ['https://www.googleapis.com/auth/userinfo.profile'],
103
+ state: crypto.randomBytes(32).toString('hex'),
104
+ include_granted_scopes: true
105
+ });
106
+
107
+ // After redirect: exchange code for tokens
108
+ const {tokens} = await client.getToken(code);
109
+ client.setCredentials(tokens);
110
+ ```
111
+
112
+ **Python**
113
+
114
+ ```python
115
+ from google_auth_oauthlib.flow import Flow
116
+
117
+ flow = Flow.from_client_secrets_file(
118
+ 'client_secret.json',
119
+ scopes=['https://www.googleapis.com/auth/userinfo.profile'],
120
+ redirect_uri=REDIRECT_URI
121
+ )
122
+
123
+ authorization_url, state = flow.authorization_url(
124
+ access_type='offline',
125
+ include_granted_scopes='true'
126
+ )
127
+
128
+ # After redirect: exchange code for tokens
129
+ flow.fetch_token(code=code)
130
+ credentials = flow.credentials
131
+ ```
132
+
133
+ `refresh_token` is only returned on the first authorization. Use `prompt: 'consent'` (Node.js) or `prompt='consent'` (Python) to force re-consent.
134
+
135
+ For the complete OAuth 2.0 flow (parameters, token exchange, refresh, revocation, incremental auth), see [references/oauth2-web-server.md](references/oauth2-web-server.md).
136
+
137
+ ### 3. Sign In with Google — ID Token Verification
138
+
139
+ **Node.js**
140
+
141
+ ```js
142
+ const {OAuth2Client} = require('google-auth-library');
143
+ const client = new OAuth2Client();
144
+
145
+ const ticket = await client.verifyIdToken({
146
+ idToken: token,
147
+ audience: WEB_CLIENT_ID,
148
+ });
149
+ const payload = ticket.getPayload();
150
+ const userId = payload['sub'];
151
+ const email = payload['email'];
152
+ const name = payload['name'];
153
+ const picture = payload['picture'];
154
+ ```
155
+
156
+ **Python**
157
+
158
+ ```python
159
+ from google.oauth2 import id_token
160
+ from google.auth.transport import requests
161
+
162
+ request = requests.Request()
163
+
164
+ payload = id_token.verify_oauth2_token(
165
+ token,
166
+ request,
167
+ WEB_CLIENT_ID
168
+ )
169
+ user_id = payload['sub']
170
+ email = payload['email']
171
+ name = payload.get('name', '')
172
+ picture = payload.get('picture')
173
+ ```
174
+
175
+ Verification checks: JWT signature, `aud`, `exp`, `iss` (accounts.google.com).
176
+
177
+ For GIS integration, CSRF protection, and hosted domain validation, see [references/sign-in-with-google.md](references/sign-in-with-google.md).
178
+
179
+ ### 4. JWT / Service Account
180
+
181
+ **Node.js**
182
+
183
+ ```js
184
+ const {JWT} = require('google-auth-library');
185
+ const keys = require('./service-account-key.json');
186
+
187
+ const client = new JWT({
188
+ email: keys.client_email,
189
+ key: keys.private_key,
190
+ scopes: ['https://www.googleapis.com/auth/cloud-platform'],
191
+ });
192
+ const res = await client.fetch(url);
193
+ ```
194
+
195
+ **Python**
196
+
197
+ ```python
198
+ from google.oauth2 import service_account
199
+
200
+ credentials = service_account.Credentials.from_service_account_file(
201
+ 'service-account-key.json',
202
+ scopes=['https://www.googleapis.com/auth/cloud-platform']
203
+ )
204
+
205
+ # Or from a dict already loaded into memory:
206
+ credentials = service_account.Credentials.from_service_account_info(
207
+ info,
208
+ scopes=['https://www.googleapis.com/auth/cloud-platform']
209
+ )
210
+ ```
211
+
212
+ ### 5. API Key
213
+
214
+ **Node.js**
215
+
216
+ ```js
217
+ const {OAuth2Client} = require('google-auth-library');
218
+ const client = new OAuth2Client({ apiKey: 'my-api-key' });
219
+
220
+ // Or via GoogleAuth:
221
+ const {GoogleAuth} = require('google-auth-library');
222
+ const auth = new GoogleAuth({
223
+ clientOptions: { apiKey: 'my-api-key' }
224
+ });
225
+ ```
226
+
227
+ **Python**
228
+
229
+ ```python
230
+ from googleapiclient.discovery import build
231
+
232
+ service = build('customsearch', 'v1', developerKey='my-api-key')
233
+ ```
234
+
235
+ ### 6. Token Refresh
236
+
237
+ **Node.js**
238
+
239
+ ```js
240
+ client.on('tokens', (tokens) => {
241
+ if (tokens.refresh_token) {
242
+ // Store refresh_token — only sent on first auth
243
+ }
244
+ console.log(tokens.access_token);
245
+ });
246
+ ```
247
+
248
+ **Python**
249
+
250
+ ```python
251
+ from google.auth.transport.requests import Request
252
+
253
+ if credentials.expired and credentials.refresh_token:
254
+ credentials.refresh(Request())
255
+ # credentials.token is the new access token
256
+ # credentials.expiry is the new expiration datetime
257
+ ```
258
+
259
+ ## Security Best Practices
260
+
261
+ - Never expose `client_secret` or service account keys in client-side code
262
+ - Always validate `state` parameter to prevent CSRF in OAuth flows
263
+ - Use `sub` (not `email`) as the unique user identifier from Google ID tokens
264
+ - Store `refresh_token` securely; it's only returned on first authorization
265
+ - Validate external credential configurations before use (check `token_url`, `service_account_impersonation_url` point to googleapis.com)
266
+ - Prefer Workload Identity Federation over service account keys for non-GCP environments
267
+ - For GIS: verify `g_csrf_token` with double-submit-cookie pattern
268
+ - **Python-specific**: reuse a single `google.auth.transport.requests.Request()` instance across verifications for connection pooling; do not create a new one per call in hot paths
269
+
270
+ ## Reference Files
271
+
272
+ - **[OAuth 2.0 Web Server Flow](references/oauth2-web-server.md)** — Complete OAuth 2.0 flow: parameters, consent, token exchange, refresh, revocation, incremental auth, error handling (Node.js + Python)
273
+ - **[ADC & Service Accounts](references/adc-and-service-accounts.md)** — Application Default Credentials setup, service account keys, JWT, Compute credentials, environment configuration (Node.js + Python)
274
+ - **[Sign In with Google](references/sign-in-with-google.md)** — Google Identity Services (GIS), ID token verification, CSRF protection, One Tap, FedCM (Node.js + Python)
275
+ - **[Workload Identity Federation](references/workload-identity.md)** — AWS, Azure, OIDC/SAML federation, workforce identity, executable-sourced credentials (Node.js + Python)