@ssheleg/sheleg-dev 0.7.0 → 0.9.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.
- package/CHANGELOG.md +114 -0
- package/README.md +24 -9
- package/SECURITY.md +28 -18
- package/package.json +4 -2
- package/plugins/sheleg-dev/.claude-plugin/plugin.json +7 -3
- package/plugins/sheleg-dev/skills/ad-tracking/fixtures/README.md +5 -4
- package/plugins/sheleg-dev/skills/ad-tracking/fixtures/assert-dedup-contract.mjs +168 -20
- package/plugins/sheleg-dev/skills/ad-tracking/references/meta-linkedin.md +6 -2
- package/plugins/sheleg-dev/skills/crypto-payments/SKILL.md +17 -80
- package/plugins/sheleg-dev/skills/crypto-payments/references/callback-route-hardening.md +55 -0
- package/plugins/sheleg-dev/skills/crypto-payments/references/testing-and-local-dev.md +60 -0
- package/plugins/sheleg-dev/skills/error-tracking/SKILL.md +259 -0
- package/plugins/sheleg-dev/skills/error-tracking/references/releases.md +159 -0
- package/plugins/sheleg-dev/skills/error-tracking/references/scrubbing.md +170 -0
- package/plugins/sheleg-dev/skills/error-tracking/references/setup.md +176 -0
- package/plugins/sheleg-dev/skills/stripe-billing/fixtures/README.md +5 -4
- package/plugins/sheleg-dev/skills/stripe-billing/fixtures/assert-money-invariants.mjs +195 -35
- package/plugins/sheleg-dev/skills/stripe-billing/references/testing-and-local-dev.md +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,120 @@ All notable changes to this project are documented here.
|
|
|
4
4
|
Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
5
5
|
Versioning: [SemVer](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## v0.9.0 — 2026-08-24
|
|
8
|
+
|
|
9
|
+
### The pack that wires integrations had nothing about knowing when they break
|
|
10
|
+
|
|
11
|
+
Six skills covered taking money, tracking conversions, signing people in and
|
|
12
|
+
page speed. None covered the layer that says any of it stopped working: a `grep`
|
|
13
|
+
for `sentry` across the whole family returned two incidental mentions.
|
|
14
|
+
|
|
15
|
+
`error-tracking` is written from a measured baseline rather than an imagined
|
|
16
|
+
one. An agent solving this exact task without the skill, in one session, made
|
|
17
|
+
four failures that were recorded as they happened:
|
|
18
|
+
|
|
19
|
+
- **Called "get a DSN" a manual step needing an account.** The account existed
|
|
20
|
+
and the CLI was already authenticated. Error tracking stayed off for no reason.
|
|
21
|
+
- **Wrote a `before_send` scrubber without knowing `EventScrubber` exists** and
|
|
22
|
+
runs by default — so it could not say which layer covered what, or whether its
|
|
23
|
+
own code was redundant or load-bearing.
|
|
24
|
+
- **Did not know the MCP is OAuth**, and would have declared it in the machine's
|
|
25
|
+
shared gateway, where an OAuth flow cannot complete.
|
|
26
|
+
- **Would have set a DSN and stopped**, leaving every issue attached to a release
|
|
27
|
+
with no commits and suspect-commit attribution permanently dead.
|
|
28
|
+
|
|
29
|
+
### The measurement the skill is built on
|
|
30
|
+
|
|
31
|
+
`sentry-sdk` 2.19.2, run 2026-08-24. The built-in `EventScrubber` is enabled by
|
|
32
|
+
default and matches on KEY NAMES against a 32-entry denylist. It does not inspect
|
|
33
|
+
string values, and neither `dsn` nor `database_url` is on that list.
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
event = {"message": "could not connect to postgresql://u:SUPERSECRET@host/db"}
|
|
37
|
+
EventScrubber().scrub_event(event)
|
|
38
|
+
assert "SUPERSECRET" in str(event) # passes — not scrubbed
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
A service that writes a database URL near an error therefore starts forwarding
|
|
42
|
+
that password to a third party the moment Sentry is added, with wider reach than
|
|
43
|
+
the log had. The skill ships both layers — and, more usefully, the test that
|
|
44
|
+
asserts layer one alone still leaks, so the day Sentry starts scrubbing values a
|
|
45
|
+
red test says the second layer may now be redundant.
|
|
46
|
+
|
|
47
|
+
### Also in this release
|
|
48
|
+
|
|
49
|
+
- The 403 that reads as an auth failure and is not: `allowMemberProjectCreation:
|
|
50
|
+
false` blocks `project create` **even for an org owner**, because the policy is
|
|
51
|
+
evaluated against the token's scopes and the device-flow token carries no
|
|
52
|
+
`org:write`. The team-scoped endpoint fails identically. Measured, with the
|
|
53
|
+
three ways out ranked.
|
|
54
|
+
- Two different tools are called `sentry`. Commands from one silently do not
|
|
55
|
+
exist in the other, and they install into prefixes where the older copy tends
|
|
56
|
+
to win — 0.38.0 shadowing 0.43.0, observed here. The shadow check is one line.
|
|
57
|
+
- `$schema` was missing from `plugin.json` and from the marketplace entry. Added.
|
|
58
|
+
|
|
59
|
+
## v0.8.0 — 2026-08-20
|
|
60
|
+
|
|
61
|
+
**The self-test that proved the money invariants was measuring one thing and claiming
|
|
62
|
+
another.** `--self-test` deleted a rule, ran an invariant, and asked whether the invariant
|
|
63
|
+
went red. Twelve invariants carried **45 `assert.` calls**, and the verdict line called
|
|
64
|
+
them *"12 assertions, each watched failing"* — so any assertion that was not the sole
|
|
65
|
+
discriminator of a rule could be replaced by `assert.ok(true)` and nothing anywhere would
|
|
66
|
+
notice. Measured against the shipped v0.7.0 pack: three neutered assertions (the
|
|
67
|
+
`clawbacks.map` deepEqual, the `mirror.periodEnd` equality, the `response.body` deepEqual)
|
|
68
|
+
left `--self-test` at exit 0 and `npm test` at 0. The same hole in `ad-tracking`, in the PII
|
|
69
|
+
guard `references/meta-linkedin.md` advertises by name.
|
|
70
|
+
|
|
71
|
+
The `assert` an invariant receives is now a recorder: a failure is remembered instead of
|
|
72
|
+
thrown, so the assertions after it still run, and each call site is one measurement
|
|
73
|
+
identified by its line. **37 of 45 watched failing, one call site at a time. Eight declared
|
|
74
|
+
`assert.unmutated`** — an assertion no rule in the pack varies — **and measured unbreakable,
|
|
75
|
+
with the reason at the call site.** Both directions: an `unmutated` assertion a mutant does
|
|
76
|
+
break is a failure too, or the escape hatch is the bypass. Four assertions that were being
|
|
77
|
+
pre-empted by a `TypeError` on the line above them became measurable rather than declared
|
|
78
|
+
away. `test/fixtures_test.js` grew three plants, one of them the NON-first assertion inside
|
|
79
|
+
a multi-assert invariant — the plant that used to pass.
|
|
80
|
+
|
|
81
|
+
Then the sweep that started there and did not stop:
|
|
82
|
+
|
|
83
|
+
- **The validator's check count did not count checks.** `checks = 10 + len(skill_dirs)`, so
|
|
84
|
+
adding a skill moved the number and adding a check did not — and five ledger rows read it
|
|
85
|
+
as evidence a guard had arrived. Every check is registered; the verdict prints the
|
|
86
|
+
registry's length, and the ledger's quoted copy of that line is compared against it.
|
|
87
|
+
- **The ledger described an artifact nobody ships.** Its shipped block was headed `v0.6.0`
|
|
88
|
+
while `v0.7.0` was tagged and on npm, and 37 rows read *verified locally · unreleased*
|
|
89
|
+
under four blocks closing *"Nothing was released."* The heading is now compared against
|
|
90
|
+
`git describe --tags` and against `package.json`.
|
|
91
|
+
- **The `mcp__.*` half of the manual gate had no guard.** Deleting that entry from
|
|
92
|
+
`hooks/hooks.json` left all three suites green, while the decision module does refuse
|
|
93
|
+
`mcp__…__create_refund` by name. And `README.md`'s copy-channel snippet registered one
|
|
94
|
+
matcher against the plugin's two — a weaker gate handed out by the document that exists
|
|
95
|
+
because the channel has none. Both are now checked; the snippet by matcher set.
|
|
96
|
+
- **This repository measured no body budget at all**, so `crypto-payments/SKILL.md` sat past
|
|
97
|
+
the house working limit and was caught by another repository's auditor. Measured here now,
|
|
98
|
+
and the skill was **split rather than trimmed**: `references/callback-route-hardening.md`
|
|
99
|
+
and `references/testing-and-local-dev.md`, 4894 → 4387 tokens. All six skills `0 GAP`.
|
|
100
|
+
- **Counted numbers became computed ones.** Seven in `SECURITY.md` (all four correct on the
|
|
101
|
+
day they were written, three of them moved by this change) and two in
|
|
102
|
+
`docs/evals/stripe-billing.md`, which restated `4994` tokens / `441` lines / `0 GAP, 13
|
|
103
|
+
PASS` against a measured 4747 / 409 / `0 GAP, 14 PASS`.
|
|
104
|
+
- **A document that ships now resolves against the tarball, not only against a clone.**
|
|
105
|
+
`SECURITY.md` sent a reader to two documents `npm pack` does not contain.
|
|
106
|
+
- **`docs/` joined the checked corpus**, with every document in it classified as live or as
|
|
107
|
+
a dated record — `docs/AGENT_SYNC.md` had been naming six paths this repository does not
|
|
108
|
+
have.
|
|
109
|
+
- **`.claude/agent-sync.json` pointed at a file that did not exist** and guarded the ledger
|
|
110
|
+
without guarding the board.
|
|
111
|
+
- **`CONTRIBUTING.md` called the gate two suites and it runs three**; the PR template asked
|
|
112
|
+
for one third of it. Both derive the list from `package.json` → `scripts.test` now.
|
|
113
|
+
- **`install.sh` — the channel that `rm -rf`s each destination — printed no notice** that
|
|
114
|
+
the gate does not travel with it, while the npm installer did.
|
|
115
|
+
|
|
116
|
+
Fourteen negative self-tests were added, one per guard, and all **42** were watched refusing
|
|
117
|
+
their plants on a green tree. CI run `32293489020` at `6f66255` — 39 steps, 39 `success`,
|
|
118
|
+
28 of 28 negatives — retires the *"CI has not seen any of this"* limitation the ledger had
|
|
119
|
+
recorded four separate times.
|
|
120
|
+
|
|
7
121
|
## v0.7.0 — 2026-08-19
|
|
8
122
|
|
|
9
123
|
**The pack that takes money had the weakest controls in the family, and every one of them
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ Part of the [ssheleg skill family](https://github.com/ssheleg/sshlg-skills).
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
## The
|
|
10
|
+
## The seven skills
|
|
11
11
|
|
|
12
12
|
| Skill | Answers |
|
|
13
13
|
|---|---|
|
|
@@ -17,13 +17,15 @@ Part of the [ssheleg skill family](https://github.com/ssheleg/sshlg-skills).
|
|
|
17
17
|
| **`google-signin`** | how do I let people sign in with Google without handing someone their account |
|
|
18
18
|
| **`google-auth`** | how does my *server* authenticate to Google — OAuth, ADC, service accounts, federation |
|
|
19
19
|
| **`frontend-performance`** | why is the Lighthouse score bad and which fix actually moves it |
|
|
20
|
+
| **`error-tracking`** | how do I know it broke, without mailing my own credentials to Sentry |
|
|
20
21
|
|
|
21
22
|
Each carries its own references and loads them only when the work reaches them.
|
|
22
23
|
|
|
23
24
|
**Two of them ship a suite rather than a warning.** `stripe-billing` and `ad-tracking`
|
|
24
25
|
carry a `fixtures/` directory — real provider webhook bodies, an assertion pack, and a
|
|
25
|
-
`--self-test` that deletes one rule at a time so you can watch every assertion fail
|
|
26
|
-
the
|
|
26
|
+
`--self-test` that deletes one rule at a time so you can watch every assertion fail — one
|
|
27
|
+
call site at a time, which is not the same thing as one invariant at a time. Copy the
|
|
28
|
+
directory in and run it:
|
|
27
29
|
|
|
28
30
|
```bash
|
|
29
31
|
node plugins/sheleg-dev/skills/stripe-billing/fixtures/assert-money-invariants.mjs --self-test
|
|
@@ -88,7 +90,7 @@ a Lighthouse score.
|
|
|
88
90
|
/plugin install sheleg-dev@sheleg-dev
|
|
89
91
|
```
|
|
90
92
|
|
|
91
|
-
**npm installer** — copies all
|
|
93
|
+
**npm installer** — copies all seven skills into `~/.claude/skills/`:
|
|
92
94
|
|
|
93
95
|
```bash
|
|
94
96
|
npx @ssheleg/sheleg-dev
|
|
@@ -158,17 +160,29 @@ settings, by design.
|
|
|
158
160
|
with the plugin and the hook is live as soon as the plugin is enabled. Nothing further
|
|
159
161
|
to do, and no per-hook switch: enablement is the whole control.
|
|
160
162
|
- **Installed by `npx @ssheleg/sheleg-dev`, `install.sh` or `npx skills add`** — those
|
|
161
|
-
copy the
|
|
163
|
+
copy the seven skills into `~/.claude/skills/` and **carry no hook**. The gate is prose
|
|
162
164
|
again until you register it yourself, in `~/.claude/settings.json` or a project's
|
|
163
165
|
`.claude/settings.json`:
|
|
164
166
|
|
|
165
167
|
```json
|
|
166
|
-
{ "hooks": { "PreToolUse": [
|
|
168
|
+
{ "hooks": { "PreToolUse": [
|
|
169
|
+
{ "matcher": "Bash",
|
|
167
170
|
"hooks": [ { "type": "command",
|
|
168
171
|
"command": "node \"$HOME/.claude/skills/.sheleg-dev-hooks/money-gate.js\"",
|
|
169
|
-
"timeout": 15 } ] }
|
|
172
|
+
"timeout": 15 } ] },
|
|
173
|
+
{ "matcher": "mcp__.*",
|
|
174
|
+
"hooks": [ { "type": "command",
|
|
175
|
+
"command": "node \"$HOME/.claude/skills/.sheleg-dev-hooks/money-gate.js\"",
|
|
176
|
+
"timeout": 15 } ] }
|
|
177
|
+
] } }
|
|
170
178
|
```
|
|
171
179
|
|
|
180
|
+
**Both entries, not just the first.** A refund does not care which door it came
|
|
181
|
+
through: `create_refund` on an MCP server never touches a shell, and the table above
|
|
182
|
+
advertises it. Until 2026-08-20 this snippet carried the `Bash` matcher alone — a
|
|
183
|
+
weaker gate than the plugin's, handed out by the document that exists because the copy
|
|
184
|
+
channels have no gate at all. `test/validate.py` now compares the two matcher sets.
|
|
185
|
+
|
|
172
186
|
Copy `plugins/sheleg-dev/hooks/` to that path first. `npx @ssheleg/sheleg-dev` prints
|
|
173
187
|
this reminder; **nothing enforces it**, which is why the plugin channel is the
|
|
174
188
|
recommended one.
|
|
@@ -219,8 +233,9 @@ matter does not error — hosts truncate it silently, which is worse); and
|
|
|
219
233
|
dangling link nor a file nobody loads can ship.
|
|
220
234
|
|
|
221
235
|
Plus, for the money fixtures, that every assertion has been watched failing and that no
|
|
222
|
-
two rules are covering for each other — `test/fixtures_test.js` neuters
|
|
223
|
-
|
|
236
|
+
two rules are covering for each other — `test/fixtures_test.js` neuters assertions,
|
|
237
|
+
including one that is **not** the first inside a multi-assert invariant, and requires each
|
|
238
|
+
pack's `--self-test` to notice. That last plant is the one that used to pass.
|
|
224
239
|
|
|
225
240
|
CI plants a defect against every one of those guards and requires the validator
|
|
226
241
|
to fail. A green from a check nobody has watched fail is not evidence.
|
package/SECURITY.md
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# Security
|
|
2
2
|
|
|
3
|
-
`sheleg-dev` is
|
|
3
|
+
`sheleg-dev` is seven skills about the layer a product reaches once it has users.
|
|
4
4
|
Five of them touch other people's money or identity — Stripe billing, crypto
|
|
5
5
|
payments, ad and conversion tracking, Google sign-in, server-side Google auth —
|
|
6
|
-
|
|
6
|
+
the sixth is front-end performance and the seventh is error tracking. Money is the
|
|
7
|
+
reason this document
|
|
7
8
|
has to be exact about the pack itself.
|
|
8
9
|
|
|
9
10
|
Everything below is checkable from a clone, and the commands at the end are the
|
|
@@ -16,8 +17,8 @@ documents name that does not exist here.
|
|
|
16
17
|
|
|
17
18
|
## What ships, and what of it executes
|
|
18
19
|
|
|
19
|
-
`git ls-files plugins` returns **
|
|
20
|
-
files of the manual gate, and 18 files of money fixtures.** Two of the
|
|
20
|
+
`git ls-files plugins` returns **56 files: 34 markdown, one plugin manifest, three
|
|
21
|
+
files of the manual gate, and 18 files of money fixtures.** Two of the seven skills now
|
|
21
22
|
ship code you can run — the assertion packs under `fixtures/` — and that is a change
|
|
22
23
|
from every release before v0.7.0, so it is stated here rather than left to be noticed.
|
|
23
24
|
They run only when you invoke them, read only the JSON fixtures beside them, and open
|
|
@@ -26,19 +27,23 @@ no socket; the greps below prove all three.
|
|
|
26
27
|
| Component | Count | Runtime behavior |
|
|
27
28
|
|---|---|---|
|
|
28
29
|
| `SKILL.md`, one per skill | 6 | Text. Read by the agent, executes nothing. |
|
|
29
|
-
| `references/` files, loaded on demand |
|
|
30
|
+
| `references/` files, loaded on demand | 25 | Text. Same. |
|
|
30
31
|
| `plugins/sheleg-dev/.claude-plugin/plugin.json` | 1 | Manifest read by Claude Code. |
|
|
31
32
|
| `plugins/sheleg-dev/hooks/hooks.json` | 1 | Hook manifest read by Claude Code. Declares one `PreToolUse` hook and no `if` filter. |
|
|
32
33
|
| `plugins/sheleg-dev/hooks/money-gate.js` | 1 | Runs on a tool call, when the plugin is enabled. Requires `path` and its own decision module — nothing else. Reads stdin, writes one JSON line, exits 0 on every path. |
|
|
33
34
|
| `plugins/sheleg-dev/hooks/lib/moneygate.js` | 1 | Pure. Payload and environment in, verdict out. No `require` at all, no filesystem, no clock. |
|
|
34
35
|
| `bin/sheleg-dev.js` — the npm installer | 1 | Runs only when you invoke it. Node built-ins only: `fs`, `path`, `os`. |
|
|
35
|
-
| `install.sh` — the shell installer | 1 |
|
|
36
|
+
| `install.sh` — the shell installer | 1 | **Not in the tarball** — `files` ships `bin/` and `plugins/`, so this one reaches you only through a clone. Runs when you invoke it. Coreutils only: `cd`, `pwd`, `dirname`, `basename`, `mkdir`, `rm`, `cp`, `echo`. It is the destructive channel: `rm -rf` per skill, then `cp -R`. |
|
|
36
37
|
| `plugins/sheleg-dev/skills/*/fixtures/*.json` — webhook payloads | 12 | Data. Placeholder ids only; no key, token, signing secret or real customer id. |
|
|
37
38
|
| `plugins/sheleg-dev/skills/*/fixtures/*.mjs` — the assertion packs and their reference implementations | 4 | Runs only when you invoke it. Reads the JSON beside it with `readFileSync` and nothing else: no `child_process`, no `fetch`, no write, no `process.env`. |
|
|
38
39
|
| `plugins/sheleg-dev/skills/*/fixtures/manifest.json` and its `README.md` | 4 | Text. The invariant-to-fixture-to-document map, which `test/validate.py` reads. |
|
|
39
40
|
|
|
40
|
-
The published tarball is
|
|
41
|
-
`LICENSE` and `package.json` —
|
|
41
|
+
The published tarball is `bin/` and `plugins/` plus `README.md`, `CHANGELOG.md`,
|
|
42
|
+
`SECURITY.md`, `LICENSE` and `package.json` — 62 files, listed by
|
|
43
|
+
`npm pack --dry-run`. `install.sh`, `test/`, `docs/` and `CONTRIBUTING.md` are **not**
|
|
44
|
+
in it; `test/validate.py` now refuses a path these shipped documents name that the
|
|
45
|
+
tarball does not carry, because resolving in a clone is the wrong question for a
|
|
46
|
+
document that ships.
|
|
42
47
|
|
|
43
48
|
**The gate can refuse a command and can never run one.** `money-gate.js` requires
|
|
44
49
|
`path` and the decision module; the decision module requires nothing. There is no
|
|
@@ -55,11 +60,11 @@ nothing but the CLI you typed.
|
|
|
55
60
|
|
|
56
61
|
## What the installers read and write
|
|
57
62
|
|
|
58
|
-
Both do one thing: copy the
|
|
63
|
+
Both do one thing: copy the seven skill directories out of the package into
|
|
59
64
|
`~/.claude/skills/<name>`.
|
|
60
65
|
|
|
61
66
|
- **Read:** only files inside the package.
|
|
62
|
-
- **Write:** only `~/.claude/skills/` —
|
|
67
|
+
- **Write:** only `~/.claude/skills/` — seven directories, named for the seven skills.
|
|
63
68
|
Nothing else on the filesystem, nothing outside `$HOME`.
|
|
64
69
|
- **Network: none.** Neither file opens a socket or resolves a hostname.
|
|
65
70
|
`bin/sheleg-dev.js` requires `fs`, `path` and `os` and nothing else — no
|
|
@@ -71,7 +76,7 @@ Both do one thing: copy the six skill directories out of the package into
|
|
|
71
76
|
|
|
72
77
|
**One destructive difference between the two installers.** `bin/sheleg-dev.js`
|
|
73
78
|
skips a skill that is already installed and says so, unless you pass `--force`
|
|
74
|
-
(`bin/sheleg-dev.js:45-46`). `install.sh` does not ask: for each of the
|
|
79
|
+
(`bin/sheleg-dev.js:45-46`). `install.sh` does not ask: for each of the seven names
|
|
75
80
|
it runs `rm -rf` on the destination and re-copies, every time
|
|
76
81
|
(`install.sh:21-22`). If you have hand-edited an installed skill, the shell
|
|
77
82
|
installer deletes your edits and the node installer does not.
|
|
@@ -136,12 +141,15 @@ environment variables, never in source and never in logs:
|
|
|
136
141
|
|
|
137
142
|
## Where the real risk is
|
|
138
143
|
|
|
139
|
-
Not the bytes — the advice. These
|
|
144
|
+
Not the bytes — the advice. These seven skills describe Stripe, Heleket and BTCPay,
|
|
140
145
|
Google Sign-In, Workload Identity Federation, four ad platforms and browser
|
|
141
146
|
defaults, and every one of those changes. **A claim here that a provider has since
|
|
142
147
|
changed is a security defect in this pack**, not merely a stale doc, and it is the
|
|
143
|
-
exposure
|
|
144
|
-
|
|
148
|
+
exposure the verification ledger names as the largest one this repository does not
|
|
149
|
+
test. **Neither that ledger nor the contributor guide is in this tarball** —
|
|
150
|
+
`docs/evidence/verification.md` and `CONTRIBUTING.md` live in the git repository at
|
|
151
|
+
<https://github.com/ssheleg/sheleg-dev>, and until 2026-08-20 this paragraph named
|
|
152
|
+
both as if you had them. The guide requires a claim about what a provider does
|
|
145
153
|
*today* to carry the date it was true. If you find one that has rotted, report it
|
|
146
154
|
with what the correct claim is and what backs it.
|
|
147
155
|
|
|
@@ -161,7 +169,7 @@ git clone https://github.com/ssheleg/sheleg-dev && cd sheleg-dev
|
|
|
161
169
|
# self-describing documents name -- this file included.
|
|
162
170
|
python3 test/validate.py
|
|
163
171
|
|
|
164
|
-
# The shipped payload:
|
|
172
|
+
# The shipped payload: 56 files.
|
|
165
173
|
git ls-files plugins
|
|
166
174
|
|
|
167
175
|
# 22 lines: the plugin manifest, the three files of the manual gate, and the 18
|
|
@@ -176,11 +184,13 @@ grep -nE "\brequire\(" plugins/sheleg-dev/hooks/money-gate.js plugins/sheleg-dev
|
|
|
176
184
|
grep -nE "child_process|\bfetch\(|require\('(http|https|net|fs|dns|tls)'\)|spawn\(|execFile|writeFile|appendFile|unlink" \
|
|
177
185
|
plugins/sheleg-dev/hooks/money-gate.js plugins/sheleg-dev/hooks/lib/moneygate.js
|
|
178
186
|
|
|
179
|
-
# Both directions of the gate, watched:
|
|
187
|
+
# Both directions of the gate, watched: every refusal and every false-positive
|
|
188
|
+
# plant. The command prints its own count -- this document does not restate it.
|
|
180
189
|
node test/moneygate_test.js
|
|
181
190
|
|
|
182
191
|
# The money fixtures: both assertion packs against their reference implementation, both
|
|
183
|
-
# --self-test runs, and
|
|
192
|
+
# --self-test runs (per ASSERTION, not per invariant), and the plants that neuter one.
|
|
193
|
+
# The command prints its own count.
|
|
184
194
|
node test/fixtures_test.js
|
|
185
195
|
|
|
186
196
|
# What the assertion packs cannot reach: NO OUTPUT, and grep exits 1 because it
|
|
@@ -196,6 +206,6 @@ grep -nE "require|child_process|exec|spawn|fetch|socket|rm -rf|cp -R|copyFileSyn
|
|
|
196
206
|
# Live-key shapes across the skill payload: one line, and it is a placeholder.
|
|
197
207
|
grep -rnE "sk_live_[A-Za-z0-9]|rk_live_[A-Za-z0-9]|whsec_[A-Za-z0-9]{8}|BEGIN [A-Z ]*PRIVATE KEY" plugins
|
|
198
208
|
|
|
199
|
-
# What npm publishes, and nothing else:
|
|
209
|
+
# What npm publishes, and nothing else: 62 files.
|
|
200
210
|
npm pack --dry-run
|
|
201
211
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ssheleg/sheleg-dev",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Six integration skills for the layer a product reaches once it has users: Stripe subscription billing, crypto payments, ad and conversion tracking under Consent Mode v2, Google sign-in and the wider Google auth surface, and Core Web Vitals. This package is the installer CLI.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"sheleg-dev": "bin/sheleg-dev.js"
|
|
@@ -43,6 +43,8 @@
|
|
|
43
43
|
"skill"
|
|
44
44
|
],
|
|
45
45
|
"scripts": {
|
|
46
|
-
"test": "python3 test/validate.py && node test/moneygate_test.js && node test/fixtures_test.js"
|
|
46
|
+
"test": "python3 test/validate.py && node test/moneygate_test.js && node test/fixtures_test.js",
|
|
47
|
+
"test:negatives": "python3 test/negatives.py",
|
|
48
|
+
"test:all": "python3 test/validate.py && node test/moneygate_test.js && node test/fixtures_test.js && python3 test/negatives.py"
|
|
47
49
|
}
|
|
48
50
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/claude-code-plugin.json",
|
|
2
3
|
"name": "sheleg-dev",
|
|
3
4
|
"displayName": "Sheleg Dev",
|
|
4
|
-
"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.",
|
|
5
|
-
"version": "0.
|
|
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.9.0",
|
|
6
7
|
"author": {
|
|
7
8
|
"name": "ssheleg",
|
|
8
9
|
"url": "https://x.com/sshlg93"
|
|
@@ -23,6 +24,9 @@
|
|
|
23
24
|
"oauth2",
|
|
24
25
|
"core-web-vitals",
|
|
25
26
|
"claude-code",
|
|
26
|
-
"cursor"
|
|
27
|
+
"cursor",
|
|
28
|
+
"sentry",
|
|
29
|
+
"error-tracking",
|
|
30
|
+
"observability"
|
|
27
31
|
]
|
|
28
32
|
}
|
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
**Copy this whole directory into your repository.** It is the executable half of what
|
|
4
4
|
`SKILL.md` → *E-commerce* and `references/meta-linkedin.md` →
|
|
5
5
|
*Deduplication with the Conversions API* state in prose: the three payloads one purchase
|
|
6
|
-
produces, six
|
|
7
|
-
emitter one rule at a time so you can watch
|
|
6
|
+
produces, six invariants a correct emitter must hold — 12 assertions between them — and a
|
|
7
|
+
self-test that breaks the emitter one rule at a time so you can watch each assertion fail
|
|
8
|
+
on its own.
|
|
8
9
|
|
|
9
10
|
```bash
|
|
10
|
-
node assert-dedup-contract.mjs # 6
|
|
11
|
-
node assert-dedup-contract.mjs --self-test # break one rule at a time;
|
|
11
|
+
node assert-dedup-contract.mjs # 6 invariants / 12 assertions
|
|
12
|
+
node assert-dedup-contract.mjs --self-test # break one rule at a time; EACH ASSERTION must go red
|
|
12
13
|
```
|
|
13
14
|
|
|
14
15
|
No dependencies, no network, **no access token anywhere in this directory** — the sink
|