ai-saas-guard 0.43.2 → 0.43.3

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/README.md CHANGED
@@ -248,13 +248,13 @@ The CLI is published on npm as `ai-saas-guard`, and the GitHub Action is availab
248
248
  | Area | Status |
249
249
  | --- | --- |
250
250
  | Public GitHub repository | Available |
251
- | npm CLI | `ai-saas-guard@0.43.2` |
252
- | GitHub Action | `zr9959/ai-saas-guard@v0` or fixed tag `v0.43.2` |
251
+ | npm CLI | `ai-saas-guard@0.43.3` |
252
+ | GitHub Action | `zr9959/ai-saas-guard@v0` or fixed tag `v0.43.3` |
253
253
  | Outputs | Launch decision queue, short summary, terminal, JSON, SARIF, and PR-focused markdown |
254
254
  | Project config | `.ai-saas-guard.json` rule toggles, severity overrides, suppressions, and fail thresholds |
255
255
  | Privacy model | Local-first, read-only scan commands, no LLM calls, no code upload |
256
- | Versioned Action tags | `v0.43.2`, `v0` |
257
- | Current release | `0.43.2` fixes hosted cleanup observability, scoped smoke KV cleanup, shallow-history PR diff fallback, Check Run Markdown escaping, and local scan coverage diagnostics while keeping billing disabled |
256
+ | Versioned Action tags | `v0.43.3`, `v0` |
257
+ | Current release | `0.43.3` reduces silent-success false positives for Cloudflare Durable Object stubs, benign null-return parsing/cache reads, configuration fallback parameters, and assertion-rich tests while keeping billing disabled |
258
258
  | npm publishing | Trusted Publisher/OIDC, no long-lived publish token |
259
259
  | Repository trust hardening | Strict branch protection, Dependabot, CodeQL, fast-check fuzzing, signed release provenance assets, private vulnerability reporting, secret scanning, and push protection |
260
260
  | Cloudflare hosted ingress | Deployed at `https://ai-saas-guard-hosted.zr9959.workers.dev`; public install/privacy notes are in [docs/hosted-install-privacy.md](docs/hosted-install-privacy.md); signed GitHub App webhook delivery and compact Check Run smoke now pass in staging |
@@ -450,7 +450,7 @@ Use `suppressions` for narrower false-positive handling when one rule is noisy o
450
450
 
451
451
  ## GitHub Action
452
452
 
453
- The repo includes a composite Action. Use `v0` for the latest compatible pre-1.0 Action, a specific release tag such as `v0.43.2` for controlled upgrades, or pin a reviewed commit SHA for stricter supply-chain control:
453
+ The repo includes a composite Action. Use `v0` for the latest compatible pre-1.0 Action, a specific release tag such as `v0.43.3` for controlled upgrades, or pin a reviewed commit SHA for stricter supply-chain control:
454
454
 
455
455
  ```yaml
456
456
  name: ai-saas-guard
@@ -10,6 +10,7 @@ const mockDataPattern = /\b(mock|fixture|fixtures|demo|sample|stub|fake)\b/i;
10
10
  const bypassPattern = /\b(TODO\s*:?\s*(auth|verify|validation|rate|owner|webhook)|temporary\s+bypass|temp\s+bypass|skip\s+(auth|verification|validation|ownership|webhook)|disable\s+(auth|verification|validation)|SKIP_(AUTH|WEBHOOK|VERIFICATION|VALIDATION)|ALLOW_UNVERIFIED)\b/i;
11
11
  const assertionPattern = /\b(expect\s*\(|assert\.|assert\s*\(|t\.is\s*\(|t\.true\s*\(|should\.|toEqual\s*\(|toBe\s*\(|toMatch\s*\()/i;
12
12
  const truthyOnlyPattern = /\b(expect\s*\([^)]*\)\.(toBeTruthy|toBeDefined|toBeOk)\s*\(\s*\)|assert\.ok\s*\([^)]*\)|t\.truthy\s*\([^)]*\))/i;
13
+ const strongAssertionPattern = /\b(expect\s*\([^)]*\)\.(?:toEqual|toStrictEqual|toBe|toMatch|toHave|toContain|toThrow|rejects|resolves)\b|assert\.(?:equal|strictEqual|deepEqual|deepStrictEqual|notEqual|notStrictEqual|notDeepEqual|notDeepStrictEqual|match|doesNotMatch|rejects|doesNotReject|throws|doesNotThrow|fail)\s*\(|t\.(?:is|deepEqual|regex|throws|throwsAsync|not)\s*\()/i;
13
14
  export async function scanSilentSuccess(input) {
14
15
  const context = await resolveScanContext(input);
15
16
  const findings = [];
@@ -32,6 +33,8 @@ export async function scanSilentSuccess(input) {
32
33
  function scanSwallowedErrors(filePath, content) {
33
34
  const findings = [];
34
35
  for (const block of findCatchBlocks(content)) {
36
+ if (isBenignNullCatch(content, block))
37
+ continue;
35
38
  if (fakeSuccessPattern.test(block.text) && !safeFailurePattern.test(block.text)) {
36
39
  findings.push(finding({
37
40
  ruleId: "silent-success.swallowed-error",
@@ -88,12 +91,16 @@ function scanProductionMockData(filePath, content) {
88
91
  }
89
92
  function scanHardcodedFallbacks(filePath, content) {
90
93
  const findings = [];
91
- const fallbackPattern = /(fallback|mock|demo|sample|stub|fake)[\s\S]{0,180}(Response\.json|NextResponse\.json|success\s*:\s*true|ok\s*:\s*true|active|subscription|entitlement)/gi;
94
+ const fallbackPattern = /(fallback|mock|demo|sample|stub|fake)[\s\S]{0,220}(Response\.json|NextResponse\.json|success\s*:\s*true|ok\s*:\s*true|status\s*:\s*["']active["']|active\s*:\s*true|subscription\s*:\s*(?:mock|demo|sample|fallback|fake|\{|\[)|entitlement\s*:\s*(?:true|active|\{|\[))/gi;
92
95
  for (const match of content.matchAll(fallbackPattern)) {
93
96
  const index = match.index ?? 0;
94
97
  const window = content.slice(Math.max(0, index - 180), index + match[0].length + 180);
95
98
  if (/degraded\s*:\s*true|status\s*:\s*(4|5)\d\d|error\s*:/i.test(window))
96
99
  continue;
100
+ if (isCloudflareDurableObjectStubWindow(window))
101
+ continue;
102
+ if (isConfigurationFallbackWindow(window))
103
+ continue;
97
104
  const line = lineNumberForIndex(content, index);
98
105
  findings.push(finding({
99
106
  ruleId: "silent-success.hardcoded-fallback",
@@ -134,7 +141,7 @@ function scanTestIntegrity(filePath, content) {
134
141
  if (body.length === 0 ||
135
142
  /^\/\/\s*TODO\b/i.test(body) ||
136
143
  !assertionPattern.test(body) ||
137
- (truthyOnlyPattern.test(body) && !/\b(toEqual|toStrictEqual|toBe\(|toMatch|toHave|rejects|resolves)\b/i.test(body))) {
144
+ hasOnlyWeakTruthyAssertions(body)) {
138
145
  findings.push(testFinding(filePath, content, testCase.line, "Weak or placeholder test may create fake confidence"));
139
146
  }
140
147
  }
@@ -167,11 +174,50 @@ function findCatchBlocks(content) {
167
174
  continue;
168
175
  blocks.push({
169
176
  text: content.slice(start, end + 1),
170
- line: lineNumberForIndex(content, match.index ?? 0)
177
+ line: lineNumberForIndex(content, match.index ?? 0),
178
+ start: match.index ?? 0,
179
+ end
171
180
  });
172
181
  }
173
182
  return blocks;
174
183
  }
184
+ function isBenignNullCatch(content, block) {
185
+ if (!/\breturn\s+null\s*;?\s*\}/i.test(block.text))
186
+ return false;
187
+ if (/(?:Response|NextResponse)\.json|success\s*:\s*true|ok\s*:\s*true|return\s+true\b|subscription\s*:|entitlement\s*:|active\s*:/i.test(block.text)) {
188
+ return false;
189
+ }
190
+ const before = content.slice(Math.max(0, block.start - 520), block.start);
191
+ const after = content.slice(block.end + 1, block.end + 720);
192
+ const surrounding = `${before}\n${block.text}\n${after}`;
193
+ if (/(?:atob|btoa|base64|base64url|decodeURIComponent|TextDecoder|JSON\.parse|\bparse[A-Z]|\bdecode[A-Z]|early\s+data)/i.test(surrounding)) {
194
+ return true;
195
+ }
196
+ if (/(?:STATESTORE|DurableObject|Durable Object|idFromName|stub\.fetch|env\.[A-Z0-9_]+\.get\s*\(|KV\.get|env\.KV|get\s*\([^)]*["']json["']|cache|cached|storage|state)/i.test(surrounding) &&
197
+ /(?:KV\.get|env\.KV|stub\.fetch|fetch\s*\(|get\s*\()/i.test(after)) {
198
+ return true;
199
+ }
200
+ return false;
201
+ }
202
+ function isCloudflareDurableObjectStubWindow(window) {
203
+ return (/\bidFromName\s*\(/i.test(window) &&
204
+ /\benv\.[A-Z0-9_]+\.get\s*\(/i.test(window) &&
205
+ /\bstub\b/i.test(window));
206
+ }
207
+ function isConfigurationFallbackWindow(window) {
208
+ return (/\bfunction\b[^{;=]*\([^)]*\bfallback\s*=\s*(?:\{\}|\[\]|null|undefined|[0-9]+|["'][^"']*["'])/i.test(window) &&
209
+ !/(?:Response|NextResponse)\.json|success\s*:\s*true|ok\s*:\s*true|active\s*:\s*true|status\s*:\s*["']active["']|subscription\s*:\s*(?:mock|demo|sample|fallback|fake|\{|\[)|entitlement\s*:\s*(?:true|active|\{|\[)/i.test(window));
210
+ }
211
+ function hasOnlyWeakTruthyAssertions(body) {
212
+ if (!truthyOnlyPattern.test(body))
213
+ return false;
214
+ if (strongAssertionPattern.test(body))
215
+ return false;
216
+ if (/\bassert\.ok\s*\([^)]*(?:[=!]==?|[<>]=?|\.(?:length|size)\b|\.includes\s*\(|\.some\s*\(|\.every\s*\()/i.test(body)) {
217
+ return false;
218
+ }
219
+ return true;
220
+ }
175
221
  function findTestBlocks(content) {
176
222
  const blocks = [];
177
223
  const testPattern = /\b(?:test|it)\s*\(\s*["'`][^"'`]+["'`]\s*,\s*(?:async\s*)?\([^)]*\)\s*=>\s*\{/gi;
@@ -23,12 +23,12 @@ Current branch: `main`.
23
23
 
24
24
  Latest release state:
25
25
 
26
- - latest release commit: `1659cb5 Fix hosted hardening and action summary support (#107)`
27
- - current `main` HEAD at the 2026-05-27 handoff-drift recheck: `48587b0 docs: add codex agent working rules`
28
- - package version: `0.43.1`
29
- - npm latest: `ai-saas-guard@0.43.1`
30
- - GitHub Release: `v0.43.1`
31
- - floating Action tag: `v0` points to `1659cb513e7b8ad8948263d440893630be49fc05`
26
+ - latest release commit: `9eff887 Fix hosted smoke cleanup and scan diagnostics (#119)`
27
+ - current `main` HEAD at the 2026-05-27 post-release recheck: `9eff887 Fix hosted smoke cleanup and scan diagnostics (#119)`
28
+ - package version: `0.43.2`
29
+ - npm latest: `ai-saas-guard@0.43.2`
30
+ - GitHub Release: `v0.43.2`
31
+ - floating Action tag: `v0` points to `9eff887f83d7287c44c066c3484b871105fc5b4a`
32
32
  - Cloudflare Worker health reports `scannerVersion: "0.43.0"`
33
33
  - the live hosted endpoint is still the Cloudflare `webhook-ingress`, not a deployed full source-checkout worker
34
34
  - real hosted smoke passed on PR `#91`, Check Run `77724168740`, with KV cleanup returning `[]`
@@ -47,6 +47,7 @@ Post-release docs and evidence work after `v0.43.0`:
47
47
  - released `v0.43.1` from PR `#107`
48
48
  - merged documentation/discovery follow-up PRs `#113`, `#114`, and `#115`
49
49
  - 2026-05-27 recheck confirmed npm latest `0.43.1`, GitHub release `v0.43.1`, latest CI/CodeQL/Metrics/Cross-Project Discovery success, hosted health safe but still reporting hosted scanner `0.43.0`, issue `#93` missing real DP feedback, and issue `#94` still blocked on source-checkout/provider deletion/monitoring evidence
50
+ - released `v0.43.2` from PR `#119`; npm `latest` and floating Action tag `v0` now point at `0.43.2` / `9eff887`
50
51
 
51
52
  Current working tree note: `.local/project-handoff.md` is local-only and ignored by git. Do not force-add it.
52
53
 
@@ -103,7 +104,7 @@ Hosted path:
103
104
 
104
105
  Public docs:
105
106
 
106
- - English README and Chinese README updated through `0.43.1`
107
+ - English README and Chinese README updated through `0.43.2`
107
108
  - Codex/agent working rules in `docs/CODEX_AGENT_WORKING_RULES.md`
108
109
  - rules docs
109
110
  - hosted deployment/runtime/gate docs
@@ -6,10 +6,10 @@ Last updated: 2026-05-27, Asia/Shanghai.
6
6
 
7
7
  - Project path: `/Volumes/MyPSSD/app/ai-saas-guard`
8
8
  - Shell: `zsh`
9
- - Branch: `main` for the public source of truth; current 1-7 fix work is in the local main worktree until committed
10
- - Latest release commit: `1659cb513e7b8ad8948263d440893630be49fc05`
11
- - Current `main` HEAD at the 2026-05-27 handoff-drift recheck: `48587b068f7985ca851770a96386083221bd3ffb`
12
- - Package version: `0.43.1`
9
+ - Branch: `main` for the public source of truth; v0.43.2 release work is merged and published
10
+ - Latest release commit: `9eff887f83d7287c44c066c3484b871105fc5b4a`
11
+ - Current `main` HEAD at the 2026-05-27 post-release recheck: `9eff887f83d7287c44c066c3484b871105fc5b4a`
12
+ - Package version: `0.43.2`
13
13
  - Observed Node: `v25.8.0`
14
14
  - Package engine: Node `>=20`
15
15
  - Network: available in the last session
@@ -110,7 +110,7 @@ GitHub:
110
110
  npm:
111
111
 
112
112
  - Package: `ai-saas-guard`
113
- - Latest published version: `0.43.1`
113
+ - Latest published version: `0.43.2`
114
114
  - Publish uses GitHub Actions Trusted Publisher/OIDC.
115
115
  - Do not add long-lived npm publish tokens.
116
116
 
@@ -193,8 +193,8 @@ Use a notes file for release notes; do not inline shell text with backticks.
193
193
 
194
194
  For the latest published line:
195
195
 
196
- - `v0.43.1` release exists on GitHub and npm `latest` is `ai-saas-guard@0.43.1`
197
- - `v0` points to `1659cb513e7b8ad8948263d440893630be49fc05`
196
+ - `v0.43.2` release exists on GitHub and npm `latest` is `ai-saas-guard@0.43.2`
197
+ - `v0` points to `9eff887f83d7287c44c066c3484b871105fc5b4a`
198
198
  - latest observed `main` CI, CodeQL, Metrics Snapshot, and Cross-Project Discovery runs completed successfully on 2026-05-27
199
199
  - hosted public health returned `ok: true`, `mode: webhook-ingress`, `processingPaused: false`, safe privacy flags, and `scannerVersion: "0.43.0"`
200
200
  - issue `#93` still has no real DP-1, DP-2, or DP-3 feedback
@@ -226,18 +226,18 @@ node dist/cli.js scan --root /path/to/your-saas
226
226
 
227
227
  这个仓库是公开 GitHub 仓库。
228
228
 
229
- CLI 已发布到 npm:`ai-saas-guard@0.43.2`。GitHub Action 支持 `v0` 浮动标签,也支持固定版本标签,例如 `v0.43.2`。
229
+ CLI 已发布到 npm:`ai-saas-guard@0.43.3`。GitHub Action 支持 `v0` 浮动标签,也支持固定版本标签,例如 `v0.43.3`。
230
230
 
231
231
  | 模块 | 状态 |
232
232
  | --- | --- |
233
233
  | 公开 GitHub 仓库 | 已可用 |
234
- | npm CLI | `ai-saas-guard@0.43.2` |
235
- | GitHub Action | `zr9959/ai-saas-guard@v0` 或固定标签 `v0.43.2` |
234
+ | npm CLI | `ai-saas-guard@0.43.3` |
235
+ | GitHub Action | `zr9959/ai-saas-guard@v0` 或固定标签 `v0.43.3` |
236
236
  | 输出格式 | 上线决策队列、短 summary、Terminal、JSON、SARIF 和 PR markdown |
237
237
  | 项目配置 | `.ai-saas-guard.json` 支持规则开关、severity 覆盖、suppressions 和 fail threshold |
238
238
  | 隐私模型 | 本地优先、只读扫描、不调用 LLM、不上传代码 |
239
- | 当前版本 | `0.43.2` 修复 hosted cleanup 可观测性、smoke KV 精准清理、浅历史 PR diff fallback、Check Run Markdown 转义和本地扫描覆盖诊断,同时继续保持 billing disabled |
240
- | Action 标签 | `v0.43.2`、`v0` |
239
+ | 当前版本 | `0.43.3` 降低 silent-success Cloudflare Durable Object stub、良性 `return null` 解析/缓存读取、配置 fallback 参数和真实断言测试的误报,同时继续保持 billing disabled |
240
+ | Action 标签 | `v0.43.3`、`v0` |
241
241
  | npm 发布 | GitHub Actions Trusted Publisher/OIDC,无需长期 npm token |
242
242
  | 仓库可信度加固 | 严格 branch protection、Dependabot、CodeQL、fast-check fuzzing、signed release provenance assets、private vulnerability reporting、secret scanning 和 push protection |
243
243
  | Cloudflare hosted ingress | 已部署到 `https://ai-saas-guard-hosted.zr9959.workers.dev`;安装和隐私说明见 [hosted-install-privacy.md](hosted-install-privacy.md);提供 `/github/app/install-info`,签名 GitHub App webhook delivery、compact Check Run 和 installation cleanup staging smoke 已通过 |
@@ -5,11 +5,11 @@
5
5
  ## Current State
6
6
 
7
7
  - Package name: `ai-saas-guard`
8
- - Current published version: `0.43.1`
8
+ - Current published version: `0.43.3`
9
9
  - Next source candidate: none
10
10
  - npm registry state: published at <https://www.npmjs.com/package/ai-saas-guard>
11
11
  - First npm-published version: `0.1.1`
12
- - GitHub Release: `v0.43.1`
12
+ - GitHub Release: `v0.43.3`
13
13
  - Publish workflow: `.github/workflows/npm-publish.yml`
14
14
  - Trusted Publisher: GitHub Actions, `zr9959/ai-saas-guard`, workflow `npm-publish.yml`, allowed action `npm publish`
15
15
  - Long-lived npm publish token: not required
@@ -18,7 +18,7 @@
18
18
 
19
19
  Use GitHub Actions with npm Trusted Publisher/OIDC:
20
20
 
21
- 1. Create and review a release tag such as `v0.43.1`.
21
+ 1. Create and review a release tag such as `v0.43.3`.
22
22
  2. Publish from the GitHub Release or run the `Publish npm` workflow manually with `ref` set to that tag.
23
23
  3. Keep `permissions.id-token: write` in the workflow so npm can exchange the GitHub Actions OIDC identity for a short-lived publish credential.
24
24
  4. Run `npm publish --access public` from the workflow. Trusted publishing automatically generates provenance for this public package from this public repository.
@@ -166,7 +166,7 @@ OpenSSF Best Practices:
166
166
  Publishing:
167
167
 
168
168
  - npm package: `ai-saas-guard`
169
- - Current published release line: `v0.43.1` published to GitHub Release, npm, and the `v0` Action tag
169
+ - Current published release line: `v0.43.2` published to GitHub Release, npm, and the `v0` Action tag
170
170
  - Next source candidate: none
171
171
  - Publish workflow: `.github/workflows/npm-publish.yml`
172
172
  - Trusted Publisher: GitHub Actions for `zr9959/ai-saas-guard`, workflow `npm-publish.yml`
@@ -193,17 +193,17 @@ Next work should therefore be feedback and evidence work, not more speculative f
193
193
  - collect provider monitoring, rollback, incident-response, uninstall/deletion, and support evidence before public beta
194
194
  - keep CLI/Action/docs current
195
195
  - only start commercialization after actual usage evidence exists
196
- - 2026-05-27 update: npm/GitHub latest is `0.43.1`; the hosted ingress remains healthy and still reports `scannerVersion: "0.43.0"`; real design-partner feedback, deployed source-checkout proof, full GitHub App deletion proof, and source-checkout provider monitoring evidence remain missing
196
+ - 2026-05-27 update: npm/GitHub latest is `0.43.2`; the hosted ingress remains healthy and still reports `scannerVersion: "0.43.0"`; real design-partner feedback, deployed source-checkout proof, full GitHub App deletion proof, and source-checkout provider monitoring evidence remain missing
197
197
 
198
198
  ## Latest Deployment And Test Evidence
199
199
 
200
200
  Latest release:
201
201
 
202
- - Version: `0.43.1`
203
- - Commit/tag target: `1659cb513e7b8ad8948263d440893630be49fc05`
204
- - GitHub Release: `v0.43.1`
205
- - npm: `ai-saas-guard@0.43.1`, `latest`
206
- - GitHub Action floating tag: `v0` points to `1659cb513e7b8ad8948263d440893630be49fc05`
202
+ - Version: `0.43.2`
203
+ - Commit/tag target: `9eff887f83d7287c44c066c3484b871105fc5b4a`
204
+ - GitHub Release: `v0.43.2`
205
+ - npm: `ai-saas-guard@0.43.2`, `latest`
206
+ - GitHub Action floating tag: `v0` points to `9eff887f83d7287c44c066c3484b871105fc5b4a`
207
207
  - Cloudflare Worker deployed version: `8744d3db-0114-4653-85e2-f1554ff1b26b`
208
208
  - Worker health: `https://ai-saas-guard-hosted.zr9959.workers.dev/healthz` returns `scannerVersion: "0.43.0"`
209
209
  - Real hosted PR smoke: PR `#91`, Check Run `77724168740`, conclusion `success`, temporary branch deleted, KV smoke records cleaned to `[]`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-saas-guard",
3
- "version": "0.43.2",
3
+ "version": "0.43.3",
4
4
  "description": "Local-first TIYBAI CLI that catches launch blockers in AI-built Next.js/Supabase/Stripe SaaS apps.",
5
5
  "readmeFilename": "README.md",
6
6
  "type": "module",