@ssheleg/sheleg-dev 0.11.5 → 0.11.8

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/CHANGELOG.md CHANGED
@@ -1,3 +1,56 @@
1
+ ## v0.11.8 — a Contents entry pointing nowhere is depth the file does not have
2
+
3
+ The family audit's second round (2026-09-07) read the eight reference files that
4
+ carry tables of contents and found the class the first round had walked past:
5
+
6
+ - **`error-tracking/references/setup.md` listed a section that never existed at any
7
+ commit** — `git log -S'## Find what already exists'` is empty; the entry was born
8
+ dangling when the skill was created. Removed.
9
+ - **Eight files carried TWO tables of contents**: the generated `## Contents` (v0.3.1)
10
+ sat on top of the older hand-kept `## Table of Contents`, which is where the one
11
+ genuinely broken anchor lived — `google-auth`'s `#fedcm-migration` pointed at a
12
+ heading reworded to *FedCM — mandatory, not a migration you are planning*. The
13
+ stale lists are gone; the generated one stays.
14
+ - **The class is closed, not just the instances**: `check_reference_anchors_resolve`
15
+ reads every shipped `references/*.md` and `SKILL.md`, strips fenced code, and
16
+ resolves each intra-document `](#anchor)` against headings slugged by GitHub's
17
+ NON-collapsing rule (an em-dash heading anchors with two hyphens — the umbrella
18
+ measured 22 false failures from a collapsing slugger on 2026-08-14). Watched
19
+ firing on the replanted setup.md entry before being believed; a workflow negative
20
+ keeps it honest from here. Validator: 26 → **27 checks**.
21
+
22
+ ## v0.11.7 — the fifth version surface is retired, and one audit finding is refused by a guard that already knew
23
+
24
+ > **v0.11.6 is a burned tag.** It was pushed before the release PR merged, in a repository
25
+ > that squash-merges — so it points beside `main` at `7088752`, the release run refused it
26
+ > at *The tag must be reachable from the default branch*, and the remote forbids tag
27
+ > deletion. Nothing shipped under it; this version is the same tree, tagged on `main`.
28
+
29
+ A family audit (2026-09-06, `sshlg-skills` wave `AUDIT-WAVE-0906`) read all seven skills
30
+ against the standard. What it found here, closed:
31
+
32
+ - **`error-tracking` carried `metadata.version: 0.9.2` under a release whose every other
33
+ surface said 0.11.5** — the only skill in the member carrying the key, a fifth version
34
+ surface the ×4 sync never read. The key is dropped rather than synced: four surfaces
35
+ move together under a guard, and a fifth existed only to drift.
36
+ - **Five skills declared no `license:`** while their two siblings did — `ad-tracking`,
37
+ `crypto-payments`, `frontend-performance`, `google-auth`, `google-signin` all say MIT now.
38
+ - **`error-tracking`'s NOT-for clause named `triage-issue`**, an id that resolves only on
39
+ machines carrying one specific tracker plugin; it names the class now.
40
+ - **`heleket-provider.md` pointed at a bare `references/price-integrity.md`**, which
41
+ resolves only in the sibling skill; the pointer carries `../stripe-billing/` now.
42
+ - **`ad-tracking`'s troubleshooting table moved into `references/performance-security.md`**
43
+ (~285 body tokens), and `stripe-billing`'s cancellation bullets compressed against their
44
+ own reference (~65) — headroom bought by moving depth, never by deleting it. What still
45
+ sits near the ceiling is `B-106` on the board.
46
+
47
+ One finding was refused, and the refusal is the record: the audit asked for the shared
48
+ `webhook signature` literal to be qualified per provider, and `test/validate.py` already
49
+ carries `TRIGGERS_SHARED_BY_DESIGN` saying both rails own that seam — the attempted
50
+ removal turned the gate red, which is the exemption doing its job.
51
+
52
+ Board: `B-106` filed. Source: family audit 2026-09-06.
53
+
1
54
  ## v0.11.5 — the card is the umbrella's render, and the eyebrow stops painting past the canvas
2
55
 
3
56
  The committed social preview is now generated by the umbrella with the CORRECTED fit
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ssheleg/sheleg-dev",
3
- "version": "0.11.5",
3
+ "version": "0.11.8",
4
4
  "description": "Seven integration skills for the layer a product reaches once it has users: Stripe subscription billing and cancellation retention, crypto payments, ad and conversion tracking under Consent Mode v2, Google sign-in and the wider Google auth surface, error tracking, and Core Web Vitals. This package is the installer CLI.",
5
5
  "bin": {
6
6
  "sheleg-dev": "bin/sheleg-dev.js"
@@ -3,7 +3,7 @@
3
3
  "name": "sheleg-dev",
4
4
  "displayName": "Sheleg Dev",
5
5
  "description": "The integration layer a product needs once it has users: Stripe subscription billing reconciled into your own database, crypto payments that survive over-payment and duplicate webhooks, ad and conversion tracking under Consent Mode v2, Google sign-in with the account-linking guards, the wider Google auth surface, and Core Web Vitals work that moves the score, and Sentry error tracking wired so it does not forward your own credentials to a third party and so a stack trace names the commit that caused it.",
6
- "version": "0.11.5",
6
+ "version": "0.11.8",
7
7
  "author": {
8
8
  "name": "ssheleg",
9
9
  "url": "https://x.com/sshlg93"
@@ -11,6 +11,7 @@ description: >-
11
11
  "enhanced conversions", "retargeting", "purchase event", "CAPI", "gclid", "UTM",
12
12
  "attribution", "отслеживание конверсий", "пиксель Meta", "согласие на куки", "ретаргетинг",
13
13
  "аналитика рекламы". Not for running the ad campaigns themselves.
14
+ license: MIT
14
15
  ---
15
16
 
16
17
  # Advertising Analytics & Conversion Tracking Integration
@@ -364,31 +365,11 @@ failure this whole skill exists to prevent, and it looks fine in every test
364
365
  that starts by accepting.
365
366
  ## Troubleshooting
366
367
 
367
- ### Common Issues
368
-
369
- | Problem | Cause | Fix |
370
- |---|---|---|
371
- | No events in GA4 | Consent defaults not set before gtag.js loads | Ensure consent `default` call is **before** the script tag |
372
- | CSP violations in console | Missing domain in CSP header | Add the domain to the correct CSP directive |
373
- | Meta Pixel not firing | Consent-gated component not rendering | Check localStorage consent value, check CustomEvent listener |
374
- | Duplicate `PageView` events | Multiple pixel instances or route change listeners | Ensure pixel init code has `if(f.fbq)return;` guard |
375
- | Purchase events without value | Missing `value`/`currency` params | Both GA4 and Meta **require** these for conversion optimisation |
376
- | Advanced Matching not working | `fbq('init')` called before pixel SDK loads | Ensure `fbevents.js` is loaded before calling `setFbAdvancedMatching()` |
377
- | Enhanced Conversions not matching | `user_data` set after conversion event | Call `setEnhancedConversionData()` **before** the conversion event fires |
378
- | gclid lost after Stripe redirect | — (shouldn't happen) | `_gcl_aw` cookie is first-party, persists across redirects |
379
- | Events firing on localhost | Missing `isLocal` guard | Add `if (window.location.hostname === 'localhost') return;` |
380
-
381
- ### Debug Mode
382
-
383
- Enable debug logging for local development:
384
-
385
- ```typescript
386
- const isLocal = window.location.hostname === "localhost";
387
- if (isLocal) {
388
- console.debug("[Analytics]", eventName, params);
389
- return; // don't fire real events
390
- }
391
- ```
368
+ Read `references/performance-security.md` → **Troubleshooting** for the
369
+ common-issues table (consent ordering, duplicate `PageView`, Advanced/Enhanced
370
+ Matching timing, the localhost guard) and the debug-mode snippet. The two seen
371
+ most: consent `default` must run **before** gtag.js loads, and a purchase
372
+ without `value`/`currency` cannot be optimised against by either platform.
392
373
 
393
374
  ---
394
375
 
@@ -5,7 +5,6 @@
5
5
 
6
6
  ## Contents
7
7
 
8
- - [Table of Contents](#table-of-contents)
9
8
  - [Status check — 2026](#status-check--2026)
10
9
  - [Advanced vs Basic Mode](#advanced-vs-basic-mode)
11
10
  - [All Consent Types](#all-consent-types)
@@ -18,17 +17,6 @@
18
17
  - [Ads Data Redaction](#ads-data-redaction)
19
18
  - [Verification](#verification)
20
19
 
21
- ## Table of Contents
22
-
23
- - [Advanced vs Basic Mode](#advanced-vs-basic-mode)
24
- - [All Consent Types](#all-consent-types)
25
- - [Region-Specific Defaults](#region-specific-defaults)
26
- - [Granular Consent](#granular-consent)
27
- - [Consent Update Flow](#consent-update-flow)
28
- - [GTM Implementation](#gtm-implementation)
29
- - [Tag Behavior When Denied](#tag-behavior-when-denied)
30
- - [Verification](#verification)
31
-
32
20
  ## Status check — 2026
33
21
 
34
22
  Consent Mode v2 has been required since **March 2024** for anyone using Google
@@ -5,19 +5,6 @@
5
5
 
6
6
  ## Contents
7
7
 
8
- - [Table of Contents](#table-of-contents)
9
- - [Event Types](#event-types)
10
- - [Recommended Events](#recommended-events)
11
- - [Custom Events](#custom-events)
12
- - [Parameter Rules](#parameter-rules)
13
- - [Ecommerce Events](#ecommerce-events)
14
- - [SaaS / Subscription Events](#saas--subscription-events)
15
- - [trackEvent Wrapper Pattern](#trackevent-wrapper-pattern)
16
- - [User identification](#user-identification)
17
- - [UTM Attribution](#utm-attribution)
18
-
19
- ## Table of Contents
20
-
21
8
  - [Event Types](#event-types)
22
9
  - [Recommended Events](#recommended-events)
23
10
  - [Custom Events](#custom-events)
@@ -6,7 +6,6 @@ Source: [Google Tag Platform — gtag.js](https://developers.google.com/tag-plat
6
6
 
7
7
  ## Contents
8
8
 
9
- - [Table of Contents](#table-of-contents)
10
9
  - [Overview](#overview)
11
10
  - [Installation](#installation)
12
11
  - [Tag ID Formats](#tag-id-formats)
@@ -17,22 +16,6 @@ Source: [Google Tag Platform — gtag.js](https://developers.google.com/tag-plat
17
16
  - [Next.js / React Integration](#nextjs--react-integration)
18
17
 
19
18
 
20
- ## Table of Contents
21
-
22
- - [Overview](#overview)
23
- - [Installation](#installation)
24
- - [Tag ID Formats](#tag-id-formats)
25
- - [Commands](#commands)
26
- - [config](#config)
27
- - [event](#event)
28
- - [set](#set)
29
- - [get](#get)
30
- - [consent](#consent)
31
- - [Parameter Scope & Precedence](#parameter-scope--precedence)
32
- - [Data Routing](#data-routing)
33
- - [Multi-Product Configuration](#multi-product-configuration)
34
- - [Next.js / React Integration](#nextjs--react-integration)
35
-
36
19
  ## Overview
37
20
 
38
21
  The Google tag (`gtag.js`) API consists of a single function:
@@ -5,7 +5,6 @@
5
5
 
6
6
  ## Contents
7
7
 
8
- - [Table of Contents](#table-of-contents)
9
8
  - [Script Loading Strategies](#script-loading-strategies)
10
9
  - [Content Security Policy](#content-security-policy)
11
10
  - [Next.js / React Integration](#nextjs--react-integration)
@@ -13,15 +12,7 @@
13
12
  - [Debug & Testing](#debug--testing)
14
13
  - [Common Mistakes](#common-mistakes)
15
14
  - [Multi-Page Consistency](#multi-page-consistency)
16
-
17
- ## Table of Contents
18
-
19
- - [Script Loading Strategies](#script-loading-strategies)
20
- - [Content Security Policy](#content-security-policy)
21
- - [SPA (Single Page Application) Handling](#spa-single-page-application-handling)
22
- - [Debug & Testing](#debug--testing)
23
- - [Common Mistakes](#common-mistakes)
24
- - [Multi-Page Consistency](#multi-page-consistency)
15
+ - [Troubleshooting](#troubleshooting)
25
16
 
26
17
  ## Script Loading Strategies
27
18
 
@@ -288,3 +279,34 @@ terser js/consent.js -o js/consent.min.js -c -m
288
279
  ```
289
280
 
290
281
  Use the minified version in production, source version in development.
282
+
283
+ ## Troubleshooting
284
+
285
+ Moved here from `SKILL.md` — the lookup table for symptoms whose causes are
286
+ covered in the sections above.
287
+
288
+ ### Common Issues
289
+
290
+ | Problem | Cause | Fix |
291
+ |---|---|---|
292
+ | No events in GA4 | Consent defaults not set before gtag.js loads | Ensure consent `default` call is **before** the script tag |
293
+ | CSP violations in console | Missing domain in CSP header | Add the domain to the correct CSP directive |
294
+ | Meta Pixel not firing | Consent-gated component not rendering | Check localStorage consent value, check CustomEvent listener |
295
+ | Duplicate `PageView` events | Multiple pixel instances or route change listeners | Ensure pixel init code has `if(f.fbq)return;` guard |
296
+ | Purchase events without value | Missing `value`/`currency` params | Both GA4 and Meta **require** these for conversion optimisation |
297
+ | Advanced Matching not working | `fbq('init')` called before pixel SDK loads | Ensure `fbevents.js` is loaded before calling `setFbAdvancedMatching()` |
298
+ | Enhanced Conversions not matching | `user_data` set after conversion event | Call `setEnhancedConversionData()` **before** the conversion event fires |
299
+ | gclid lost after Stripe redirect | — (shouldn't happen) | `_gcl_aw` cookie is first-party, persists across redirects |
300
+ | Events firing on localhost | Missing `isLocal` guard | Add `if (window.location.hostname === 'localhost') return;` |
301
+
302
+ ### Debug Mode
303
+
304
+ Enable debug logging for local development:
305
+
306
+ ```typescript
307
+ const isLocal = window.location.hostname === "localhost";
308
+ if (isLocal) {
309
+ console.debug("[Analytics]", eventName, params);
310
+ return; // don't fire real events
311
+ }
312
+ ```
@@ -11,6 +11,7 @@ description: >-
11
11
  checkout", "pay with crypto", "USDT payment", "TRC20", "payment webhook", "IPN", "webhook
12
12
  signature", "underpayment", "Heleket", "NOWPayments", "приём криптоплатежей", "оплата
13
13
  криптой", "вебхук платежа", "недоплата". Not for card billing — use stripe-billing.
14
+ license: MIT
14
15
  ---
15
16
 
16
17
  # Crypto payments
@@ -174,8 +174,9 @@ than Stripe's and the difference decides the design:
174
174
  | Key also signs webhooks | no, a separate `whsec_` | **yes, the same value** |
175
175
 
176
176
  So the house pattern — declare the environment in a variable separate from the secret,
177
- then assert at boot that the two agree (the `stripe-billing` skill, `references/price-integrity.md`,
178
- *Test and live mode*) — applies, but its Stripe implementation does not: there is no key
177
+ then assert at boot that the two agree (the `stripe-billing` skill,
178
+ `../stripe-billing/references/price-integrity.md`, *Test and live mode*) — applies, but its
179
+ Stripe implementation does not: there is no key
179
180
  prefix to read. The comparison has to be made against something else, and Heleket gives
180
181
  exactly two candidates, both non-secret:
181
182
 
@@ -10,11 +10,9 @@ description: >-
10
10
  "set up error tracking", "SENTRY_DSN", "sentry-cli", "sentry mcp", "scrub secrets from
11
11
  errors", "release tracking", "suspect commits", "why is Sentry empty", "подключить Sentry",
12
12
  "трекинг ошибок", "секреты в Sentry", "релизы в Sentry", "наблюдаемость". NOT for judging an
13
- agent's trajectory (agent-evals), triaging tickets in a tracker (triage-issue), or choosing an
14
- uptime vendor.
13
+ agent's trajectory (agent-evals), triaging tickets in a tracker (your tracker's own triage
14
+ skill), or choosing an uptime vendor.
15
15
  license: MIT
16
- metadata:
17
- version: 0.9.2
18
16
  ---
19
17
 
20
18
  # error-tracking — Sentry wired so it does not leak, and so a stack trace names a commit
@@ -8,7 +8,6 @@ refused and you need to tell a policy problem from an auth problem.
8
8
  - [Install](#install)
9
9
  - [Authenticate](#authenticate)
10
10
  - [Token taxonomy — which kind can do what](#token-taxonomy--which-kind-can-do-what)
11
- - [Find what already exists](#find-what-already-exists)
12
11
  - [Create a project](#create-a-project)
13
12
  - [Get the DSN and wire it in](#get-the-dsn-and-wire-it-in)
14
13
  - [Declare the MCP server](#declare-the-mcp-server)
@@ -11,6 +11,7 @@ description: >-
11
11
  "render-blocking", "bundle size", "code splitting", "lazy loading", "cache headers",
12
12
  "performance budget", "ускорить сайт", "медленно грузится", "оптимизация скорости", "вес
13
13
  бандла". Not for visual design or conversion work.
14
+ license: MIT
14
15
  ---
15
16
 
16
17
  # Frontend Performance
@@ -11,6 +11,7 @@ description: >-
11
11
  "GOOGLE_APPLICATION_CREDENTIALS", "Google SSO", "авторизация Google", "сервисный аккаунт",
12
12
  "ключи сервисного аккаунта", "проверить ID-токен". For end-user web sign-in only, use the
13
13
  google-signin skill instead.
14
+ license: MIT
14
15
  ---
15
16
 
16
17
  # Google Authentication for Node.js & Python
@@ -3,19 +3,6 @@
3
3
 
4
4
  ## Contents
5
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
6
  - [ADC Overview](#adc-overview)
20
7
  - [ADC Search Order](#adc-search-order)
21
8
  - [Setting Up ADC](#setting-up-adc)
@@ -3,7 +3,6 @@
3
3
 
4
4
  ## Contents
5
5
 
6
- - [Table of Contents](#table-of-contents)
7
6
  - [Prerequisites](#prerequisites)
8
7
  - [Step 1: Set Authorization Parameters](#step-1-set-authorization-parameters)
9
8
  - [Step 2: Redirect to Google](#step-2-redirect-to-google)
@@ -18,20 +17,6 @@
18
17
  - [Complete FastAPI Example](#complete-fastapi-example)
19
18
  - [Scopes Reference](#scopes-reference)
20
19
 
21
- ## Table of Contents
22
- - [Prerequisites](#prerequisites)
23
- - [Step 1: Set Authorization Parameters](#step-1-set-authorization-parameters)
24
- - [Step 2: Redirect to Google](#step-2-redirect-to-google)
25
- - [Step 3: Handle Callback](#step-3-handle-callback)
26
- - [Step 4: Use Access Token](#step-4-use-access-token)
27
- - [Refreshing Tokens](#refreshing-tokens)
28
- - [Revoking Tokens](#revoking-tokens)
29
- - [Incremental Authorization](#incremental-authorization)
30
- - [Error Reference](#error-reference)
31
- - [Complete Express Example](#complete-express-example)
32
- - [Complete Flask Example](#complete-flask-example)
33
- - [Complete FastAPI Example](#complete-fastapi-example)
34
-
35
20
  ## Prerequisites
36
21
 
37
22
  1. Enable APIs in [Google Cloud Console](https://console.developers.google.com/apis/library)
@@ -3,7 +3,6 @@
3
3
 
4
4
  ## Contents
5
5
 
6
- - [Table of Contents](#table-of-contents)
7
6
  - [Overview](#overview)
8
7
  - [Client-Side Integration](#client-side-integration)
9
8
  - [Server-Side ID Token Verification](#server-side-id-token-verification)
@@ -17,19 +16,6 @@
17
16
  - [FedCM — mandatory, not a migration you are planning](#fedcm--mandatory-not-a-migration-you-are-planning)
18
17
  - [Sign Out](#sign-out)
19
18
 
20
- ## Table of Contents
21
- - [Overview](#overview)
22
- - [Client-Side Integration](#client-side-integration)
23
- - [Server-Side ID Token Verification](#server-side-id-token-verification)
24
- - [CSRF Protection](#csrf-protection)
25
- - [Nonce Verification](#nonce-verification)
26
- - [ID Token Payload Fields](#id-token-payload-fields)
27
- - [Account Linking Flows](#account-linking-flows)
28
- - [Next.js / React Integration Pattern](#nextjs--react-integration-pattern)
29
- - [FastAPI Integration Pattern](#fastapi-integration-pattern)
30
- - [Flask Integration Pattern](#flask-integration-pattern)
31
- - [FedCM Migration](#fedcm-migration)
32
-
33
19
  ## Overview
34
20
 
35
21
  Sign In with Google (part of Google Identity Services / GIS) provides:
@@ -3,19 +3,6 @@
3
3
 
4
4
  ## Contents
5
5
 
6
- - [Table of Contents](#table-of-contents)
7
- - [Overview](#overview)
8
- - [AWS Federation](#aws-federation)
9
- - [Azure Federation](#azure-federation)
10
- - [OIDC Provider Federation](#oidc-provider-federation)
11
- - [Custom Subject Token Supplier](#custom-subject-token-supplier)
12
- - [Workforce Identity Federation](#workforce-identity-federation)
13
- - [Executable-Sourced Credentials](#executable-sourced-credentials)
14
- - [Using External Identities](#using-external-identities)
15
- - [Configurable Token Lifetime](#configurable-token-lifetime)
16
- - [Security Considerations](#security-considerations)
17
-
18
- ## Table of Contents
19
6
  - [Overview](#overview)
20
7
  - [AWS Federation](#aws-federation)
21
8
  - [Azure Federation](#azure-federation)
@@ -10,6 +10,7 @@ description: >-
10
10
  "google.accounts.id", "gsi/client", "verify google token", "one tap", "account linking",
11
11
  "login csrf", "g_csrf_token", "вход через Google", "кнопка входа Google", "связать аккаунты",
12
12
  "проверить токен Google". For the broader library surface use google-auth instead.
13
+ license: MIT
13
14
  ---
14
15
 
15
16
  # Google Sign-In (GIS) — production web login
@@ -314,18 +314,15 @@ product decision `stripe-best-practices` owns.
314
314
 
315
315
  - **At period end is the default** — the user keeps what they paid for and
316
316
  `status` stays `active`. Under **flexible** `billing_mode` a portal
317
- cancellation sets `cancel_at` and leaves `cancel_at_period_end` **false**, so a
318
- banner reading that boolean tells a customer who cancelled ten seconds ago that
319
- their plan renews. Store the timestamp, derived from both fields.
317
+ cancellation sets `cancel_at` and leaves `cancel_at_period_end` **false** —
318
+ derive "is cancelling" from both fields, never from the boolean alone.
320
319
  - **Do the teardown in `customer.subscription.deleted`**, never beside the API
321
320
  call, so one path serves your UI, the portal and dunning alike.
322
321
  - On `invoice.payment_failed`, mark `past_due` and notify — do not cancel.
323
322
  Stripe's dunning decides the retries and the terminal state.
324
- - **A save offer's eligibility is yours.** Stripe's cancel page shows a coupon
325
- card when you pass `flow_data.subscription_cancel.retention`, but a coupon
326
- cannot be restricted to one customer and a `duration=once` discount leaves
327
- `subscription.discounts` once its invoice finalizes. Ask Stripe whether this
328
- customer was already discounted and the answer is no, every month, forever.
323
+ - **A save offer's eligibility is yours.** Stripe cannot answer "was this
324
+ customer already discounted" — a `duration=once` discount leaves
325
+ `subscription.discounts` at finalization — so track eligibility yourself.
329
326
 
330
327
  Both, with the code:
331
328
  [`references/cancellation-and-retention.md`](references/cancellation-and-retention.md).