ai-saas-guard 0.42.0 → 0.43.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/README.md +7 -5
- package/dist/hosted/beta.d.ts +97 -0
- package/dist/hosted/beta.js +132 -0
- package/docs/README.zh-CN.md +7 -5
- package/docs/hosted-node-container-app.md +7 -2
- package/docs/hosted-operational-release-gate.md +22 -0
- package/docs/hosted-operations-evidence.md +4 -0
- package/docs/npm-publishing.md +3 -3
- package/hosted/cloudflare-worker/README.md +1 -1
- package/hosted/cloudflare-worker/wrangler.jsonc +1 -1
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -235,13 +235,13 @@ The CLI is published on npm as `ai-saas-guard`, and the GitHub Action is availab
|
|
|
235
235
|
| Area | Status |
|
|
236
236
|
| --- | --- |
|
|
237
237
|
| Public GitHub repository | Available |
|
|
238
|
-
| npm CLI | `ai-saas-guard@0.
|
|
239
|
-
| GitHub Action | `zr9959/ai-saas-guard@v0` or fixed tag `v0.
|
|
238
|
+
| npm CLI | `ai-saas-guard@0.43.0` |
|
|
239
|
+
| GitHub Action | `zr9959/ai-saas-guard@v0` or fixed tag `v0.43.0` |
|
|
240
240
|
| Outputs | Launch decision queue, short summary, terminal, JSON, SARIF, and PR-focused markdown |
|
|
241
241
|
| Project config | `.ai-saas-guard.json` rule toggles, severity overrides, suppressions, and fail thresholds |
|
|
242
242
|
| Privacy model | Local-first, read-only scan commands, no LLM calls, no code upload |
|
|
243
|
-
| Versioned Action tags | `v0.
|
|
244
|
-
| Current release | `0.
|
|
243
|
+
| Versioned Action tags | `v0.43.0`, `v0` |
|
|
244
|
+
| Current release | `0.43.0` adds pre-commercial hosted gates for Phase 4 beta readiness and Phase 5 team launch readiness while keeping billing disabled |
|
|
245
245
|
| npm publishing | Trusted Publisher/OIDC, no long-lived publish token |
|
|
246
246
|
| Repository trust hardening | Strict branch protection, Dependabot, CodeQL, fast-check fuzzing, signed release provenance assets, private vulnerability reporting, secret scanning, and push protection |
|
|
247
247
|
| 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 |
|
|
@@ -369,6 +369,8 @@ The first live hosted ingress is deployed on Cloudflare Workers at `https://ai-s
|
|
|
369
369
|
|
|
370
370
|
The next hosted source-checkout step is intentionally narrow: deploy the existing read-only checkout worker behind the same selected-repository identity, keep the fixed `pr-risk --json` command, write only compact findings to the Check Run, and require deployed cleanup/log-boundary/rollback evidence before broader trial use. The hosted worker export includes `createHostedSourceCheckoutTrialPlan`, `createHostedSourceCheckoutEvidence`, and `evaluateHostedSourceCheckoutTrialGate` so Phase 3 has one machine-checkable gate for checkout start/end, token removal, CLI start/end, compact report write, Check Run write, cleanup status, live smoke, rollback, monitoring, and incident-owner proof before Phase 4 beta.
|
|
371
371
|
|
|
372
|
+
The `ai-saas-guard/hosted/beta` export adds `evaluateHostedBetaReadinessGate` and `evaluateTeamLaunchGateReadiness`. These pre-commercial gates block hosted beta unless selected-repository install limits, abuse controls, safe telemetry, uninstall deletion proof, rollback, support ownership, beta smoke, and no-audit-claim wording are ready; they also block team use unless org policy config, required status-check docs, suppression audit, reviewer checklist, release evidence export, retention docs, and billing-disabled proof are in place.
|
|
373
|
+
|
|
372
374
|
Hosted install and privacy details are summarized in [docs/hosted-install-privacy.md](docs/hosted-install-privacy.md): selected-repository permissions, supported events, Check Run data boundaries, uninstall cleanup, and why the local CLI remains the private/offline path.
|
|
373
375
|
|
|
374
376
|
The hosted operational release gate is documented in [docs/hosted-operational-release-gate.md](docs/hosted-operational-release-gate.md). It defines the hosted-specific CI, replay, queue, worker cleanup, privacy, monitoring, rollback, and incident-response evidence required before any hosted environment is exposed to users. The pure gate evaluator exported from `ai-saas-guard/hosted/contracts` blocks hosted exposure unless every P0 evidence item is fresh, a container digest is recorded, and release notes avoid pentest, certification, and full-audit claims.
|
|
@@ -423,7 +425,7 @@ Use `suppressions` for narrower false-positive handling when one rule is noisy o
|
|
|
423
425
|
|
|
424
426
|
## GitHub Action
|
|
425
427
|
|
|
426
|
-
The repo includes a composite Action. Use `v0` for the latest compatible pre-1.0 Action, a specific release tag such as `v0.
|
|
428
|
+
The repo includes a composite Action. Use `v0` for the latest compatible pre-1.0 Action, a specific release tag such as `v0.43.0` for controlled upgrades, or pin a reviewed commit SHA for stricter supply-chain control:
|
|
427
429
|
|
|
428
430
|
```yaml
|
|
429
431
|
name: ai-saas-guard
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
export interface HostedBetaReadinessGateInput {
|
|
2
|
+
requestedAt: string;
|
|
3
|
+
phase3GatePassed: boolean;
|
|
4
|
+
selectedRepositoryInstallOnly: boolean;
|
|
5
|
+
publicInstallDocsReady: boolean;
|
|
6
|
+
rateLimitEnabled: boolean;
|
|
7
|
+
abuseKillSwitchReady: boolean;
|
|
8
|
+
telemetrySafe: boolean;
|
|
9
|
+
uninstallDeletionTested: boolean;
|
|
10
|
+
rollbackTested: boolean;
|
|
11
|
+
incidentOwnerRecorded: boolean;
|
|
12
|
+
supportPathReady: boolean;
|
|
13
|
+
betaSmokePassed: boolean;
|
|
14
|
+
avoidsAuditClaims: boolean;
|
|
15
|
+
noRawSourceStorage: boolean;
|
|
16
|
+
noRawDiffStorage: boolean;
|
|
17
|
+
noPrTextStorage: boolean;
|
|
18
|
+
maxReposPerInstallation: number;
|
|
19
|
+
maxConcurrentScans: number;
|
|
20
|
+
rawSource?: string;
|
|
21
|
+
rawDiff?: string;
|
|
22
|
+
prText?: string;
|
|
23
|
+
installationToken?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface HostedBetaReadinessGate {
|
|
26
|
+
phase: "phase_4_hosted_beta_readiness";
|
|
27
|
+
readyForPublicBeta: boolean;
|
|
28
|
+
blockedReasons: string[];
|
|
29
|
+
requestedAt: string;
|
|
30
|
+
installBoundary: {
|
|
31
|
+
selectedRepositoryOnly: true;
|
|
32
|
+
maxReposPerInstallation: number;
|
|
33
|
+
maxConcurrentScans: number;
|
|
34
|
+
};
|
|
35
|
+
operations: {
|
|
36
|
+
rateLimitEnabled: boolean;
|
|
37
|
+
abuseKillSwitchReady: boolean;
|
|
38
|
+
telemetrySafe: boolean;
|
|
39
|
+
uninstallDeletionTested: boolean;
|
|
40
|
+
rollbackTested: boolean;
|
|
41
|
+
incidentOwnerRecorded: boolean;
|
|
42
|
+
supportPathReady: boolean;
|
|
43
|
+
betaSmokePassed: boolean;
|
|
44
|
+
};
|
|
45
|
+
nextAction: string;
|
|
46
|
+
privacy: {
|
|
47
|
+
includesRawSource: false;
|
|
48
|
+
includesRawDiffs: false;
|
|
49
|
+
includesUntrustedPrText: false;
|
|
50
|
+
includesInstallationToken: false;
|
|
51
|
+
claimsPentest: false;
|
|
52
|
+
claimsFullAudit: false;
|
|
53
|
+
claimsCertification: false;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export interface TeamLaunchGateReadinessInput {
|
|
57
|
+
requestedAt: string;
|
|
58
|
+
hostedBetaGatePassed: boolean;
|
|
59
|
+
orgPolicyConfigReady: boolean;
|
|
60
|
+
requiredStatusCheckDocumented: boolean;
|
|
61
|
+
suppressionAuditReady: boolean;
|
|
62
|
+
reviewerChecklistReady: boolean;
|
|
63
|
+
releaseEvidenceExportReady: boolean;
|
|
64
|
+
teamDocsReady: boolean;
|
|
65
|
+
adminBypassDocumented: boolean;
|
|
66
|
+
retentionPolicyDocumented: boolean;
|
|
67
|
+
noCommercialBillingEnabled: boolean;
|
|
68
|
+
rawSource?: string;
|
|
69
|
+
customerPayload?: unknown;
|
|
70
|
+
}
|
|
71
|
+
export interface TeamLaunchGateReadiness {
|
|
72
|
+
phase: "phase_5_team_launch_gate";
|
|
73
|
+
readyForTeamUse: boolean;
|
|
74
|
+
blockedReasons: string[];
|
|
75
|
+
requestedAt: string;
|
|
76
|
+
teamControls: {
|
|
77
|
+
orgPolicyConfigReady: boolean;
|
|
78
|
+
requiredStatusCheckDocumented: boolean;
|
|
79
|
+
suppressionAuditReady: boolean;
|
|
80
|
+
reviewerChecklistReady: boolean;
|
|
81
|
+
releaseEvidenceExportReady: boolean;
|
|
82
|
+
teamDocsReady: boolean;
|
|
83
|
+
adminBypassDocumented: boolean;
|
|
84
|
+
retentionPolicyDocumented: boolean;
|
|
85
|
+
};
|
|
86
|
+
commercialization: {
|
|
87
|
+
enabled: false;
|
|
88
|
+
reason: "pre_commercial_feedback_stage";
|
|
89
|
+
};
|
|
90
|
+
nextAction: string;
|
|
91
|
+
privacy: {
|
|
92
|
+
includesRawSource: false;
|
|
93
|
+
includesCustomerPayloads: false;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export declare function evaluateHostedBetaReadinessGate(input: HostedBetaReadinessGateInput): HostedBetaReadinessGate;
|
|
97
|
+
export declare function evaluateTeamLaunchGateReadiness(input: TeamLaunchGateReadinessInput): TeamLaunchGateReadiness;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
const MAX_BETA_REPOS_PER_INSTALLATION = 10;
|
|
2
|
+
const MAX_BETA_CONCURRENT_SCANS = 5;
|
|
3
|
+
export function evaluateHostedBetaReadinessGate(input) {
|
|
4
|
+
const blockedReasons = hostedBetaBlockedReasons(input);
|
|
5
|
+
return {
|
|
6
|
+
phase: "phase_4_hosted_beta_readiness",
|
|
7
|
+
readyForPublicBeta: blockedReasons.length === 0,
|
|
8
|
+
blockedReasons,
|
|
9
|
+
requestedAt: input.requestedAt,
|
|
10
|
+
installBoundary: {
|
|
11
|
+
selectedRepositoryOnly: true,
|
|
12
|
+
maxReposPerInstallation: Math.max(0, Math.floor(input.maxReposPerInstallation)),
|
|
13
|
+
maxConcurrentScans: Math.max(0, Math.floor(input.maxConcurrentScans))
|
|
14
|
+
},
|
|
15
|
+
operations: {
|
|
16
|
+
rateLimitEnabled: input.rateLimitEnabled,
|
|
17
|
+
abuseKillSwitchReady: input.abuseKillSwitchReady,
|
|
18
|
+
telemetrySafe: input.telemetrySafe,
|
|
19
|
+
uninstallDeletionTested: input.uninstallDeletionTested,
|
|
20
|
+
rollbackTested: input.rollbackTested,
|
|
21
|
+
incidentOwnerRecorded: input.incidentOwnerRecorded,
|
|
22
|
+
supportPathReady: input.supportPathReady,
|
|
23
|
+
betaSmokePassed: input.betaSmokePassed
|
|
24
|
+
},
|
|
25
|
+
nextAction: blockedReasons.length === 0
|
|
26
|
+
? "Open a limited public beta only for selected repositories and keep collecting operational evidence before commercialization."
|
|
27
|
+
: "Do not open hosted beta. Resolve the blocked reasons and rerun the beta readiness gate.",
|
|
28
|
+
privacy: {
|
|
29
|
+
includesRawSource: false,
|
|
30
|
+
includesRawDiffs: false,
|
|
31
|
+
includesUntrustedPrText: false,
|
|
32
|
+
includesInstallationToken: false,
|
|
33
|
+
claimsPentest: false,
|
|
34
|
+
claimsFullAudit: false,
|
|
35
|
+
claimsCertification: false
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export function evaluateTeamLaunchGateReadiness(input) {
|
|
40
|
+
const blockedReasons = teamLaunchBlockedReasons(input);
|
|
41
|
+
return {
|
|
42
|
+
phase: "phase_5_team_launch_gate",
|
|
43
|
+
readyForTeamUse: blockedReasons.length === 0,
|
|
44
|
+
blockedReasons,
|
|
45
|
+
requestedAt: input.requestedAt,
|
|
46
|
+
teamControls: {
|
|
47
|
+
orgPolicyConfigReady: input.orgPolicyConfigReady,
|
|
48
|
+
requiredStatusCheckDocumented: input.requiredStatusCheckDocumented,
|
|
49
|
+
suppressionAuditReady: input.suppressionAuditReady,
|
|
50
|
+
reviewerChecklistReady: input.reviewerChecklistReady,
|
|
51
|
+
releaseEvidenceExportReady: input.releaseEvidenceExportReady,
|
|
52
|
+
teamDocsReady: input.teamDocsReady,
|
|
53
|
+
adminBypassDocumented: input.adminBypassDocumented,
|
|
54
|
+
retentionPolicyDocumented: input.retentionPolicyDocumented
|
|
55
|
+
},
|
|
56
|
+
commercialization: {
|
|
57
|
+
enabled: false,
|
|
58
|
+
reason: "pre_commercial_feedback_stage"
|
|
59
|
+
},
|
|
60
|
+
nextAction: blockedReasons.length === 0
|
|
61
|
+
? "Use the team launch gate with design partners, collect user feedback, and delay commercialization until usage evidence exists."
|
|
62
|
+
: "Do not sell or commercialize. Resolve the team launch gate blockers before inviting teams beyond beta.",
|
|
63
|
+
privacy: {
|
|
64
|
+
includesRawSource: false,
|
|
65
|
+
includesCustomerPayloads: false
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function hostedBetaBlockedReasons(input) {
|
|
70
|
+
const reasons = [];
|
|
71
|
+
if (!input.phase3GatePassed)
|
|
72
|
+
reasons.push("phase3_gate_missing");
|
|
73
|
+
if (!input.selectedRepositoryInstallOnly)
|
|
74
|
+
reasons.push("selected_repository_install_required");
|
|
75
|
+
if (!input.publicInstallDocsReady)
|
|
76
|
+
reasons.push("public_install_docs_missing");
|
|
77
|
+
if (!input.rateLimitEnabled)
|
|
78
|
+
reasons.push("rate_limit_missing");
|
|
79
|
+
if (!input.abuseKillSwitchReady)
|
|
80
|
+
reasons.push("abuse_kill_switch_missing");
|
|
81
|
+
if (!input.telemetrySafe)
|
|
82
|
+
reasons.push("safe_telemetry_missing");
|
|
83
|
+
if (!input.uninstallDeletionTested)
|
|
84
|
+
reasons.push("uninstall_deletion_proof_missing");
|
|
85
|
+
if (!input.rollbackTested)
|
|
86
|
+
reasons.push("rollback_test_missing");
|
|
87
|
+
if (!input.incidentOwnerRecorded)
|
|
88
|
+
reasons.push("incident_owner_missing");
|
|
89
|
+
if (!input.supportPathReady)
|
|
90
|
+
reasons.push("support_path_missing");
|
|
91
|
+
if (!input.betaSmokePassed)
|
|
92
|
+
reasons.push("beta_smoke_missing");
|
|
93
|
+
if (!input.avoidsAuditClaims)
|
|
94
|
+
reasons.push("audit_claims_not_blocked");
|
|
95
|
+
if (!input.noRawSourceStorage)
|
|
96
|
+
reasons.push("raw_source_storage_blocked");
|
|
97
|
+
if (!input.noRawDiffStorage)
|
|
98
|
+
reasons.push("raw_diff_storage_blocked");
|
|
99
|
+
if (!input.noPrTextStorage)
|
|
100
|
+
reasons.push("pr_text_storage_blocked");
|
|
101
|
+
if (!Number.isFinite(input.maxReposPerInstallation) || input.maxReposPerInstallation > MAX_BETA_REPOS_PER_INSTALLATION) {
|
|
102
|
+
reasons.push("repo_limit_too_high");
|
|
103
|
+
}
|
|
104
|
+
if (!Number.isFinite(input.maxConcurrentScans) || input.maxConcurrentScans > MAX_BETA_CONCURRENT_SCANS) {
|
|
105
|
+
reasons.push("concurrency_limit_too_high");
|
|
106
|
+
}
|
|
107
|
+
return reasons;
|
|
108
|
+
}
|
|
109
|
+
function teamLaunchBlockedReasons(input) {
|
|
110
|
+
const reasons = [];
|
|
111
|
+
if (!input.hostedBetaGatePassed)
|
|
112
|
+
reasons.push("hosted_beta_gate_missing");
|
|
113
|
+
if (!input.orgPolicyConfigReady)
|
|
114
|
+
reasons.push("org_policy_config_missing");
|
|
115
|
+
if (!input.requiredStatusCheckDocumented)
|
|
116
|
+
reasons.push("required_status_check_docs_missing");
|
|
117
|
+
if (!input.suppressionAuditReady)
|
|
118
|
+
reasons.push("suppression_audit_missing");
|
|
119
|
+
if (!input.reviewerChecklistReady)
|
|
120
|
+
reasons.push("reviewer_checklist_missing");
|
|
121
|
+
if (!input.releaseEvidenceExportReady)
|
|
122
|
+
reasons.push("release_evidence_export_missing");
|
|
123
|
+
if (!input.teamDocsReady)
|
|
124
|
+
reasons.push("team_docs_missing");
|
|
125
|
+
if (!input.adminBypassDocumented)
|
|
126
|
+
reasons.push("admin_bypass_docs_missing");
|
|
127
|
+
if (!input.retentionPolicyDocumented)
|
|
128
|
+
reasons.push("retention_policy_docs_missing");
|
|
129
|
+
if (!input.noCommercialBillingEnabled)
|
|
130
|
+
reasons.push("commercial_billing_enabled_too_early");
|
|
131
|
+
return reasons;
|
|
132
|
+
}
|
package/docs/README.zh-CN.md
CHANGED
|
@@ -213,18 +213,18 @@ node dist/cli.js scan --root /path/to/your-saas
|
|
|
213
213
|
|
|
214
214
|
这个仓库是公开 GitHub 仓库。
|
|
215
215
|
|
|
216
|
-
CLI 已发布到 npm:`ai-saas-guard@0.
|
|
216
|
+
CLI 已发布到 npm:`ai-saas-guard@0.43.0`。GitHub Action 支持 `v0` 浮动标签,也支持固定版本标签,例如 `v0.43.0`。
|
|
217
217
|
|
|
218
218
|
| 模块 | 状态 |
|
|
219
219
|
| --- | --- |
|
|
220
220
|
| 公开 GitHub 仓库 | 已可用 |
|
|
221
|
-
| npm CLI | `ai-saas-guard@0.
|
|
222
|
-
| GitHub Action | `zr9959/ai-saas-guard@v0` 或固定标签 `v0.
|
|
221
|
+
| npm CLI | `ai-saas-guard@0.43.0` |
|
|
222
|
+
| GitHub Action | `zr9959/ai-saas-guard@v0` 或固定标签 `v0.43.0` |
|
|
223
223
|
| 输出格式 | 上线决策队列、短 summary、Terminal、JSON、SARIF 和 PR markdown |
|
|
224
224
|
| 项目配置 | `.ai-saas-guard.json` 支持规则开关、severity 覆盖、suppressions 和 fail threshold |
|
|
225
225
|
| 隐私模型 | 本地优先、只读扫描、不调用 LLM、不上传代码 |
|
|
226
|
-
| 当前版本 | `0.
|
|
227
|
-
| Action 标签 | `v0.
|
|
226
|
+
| 当前版本 | `0.43.0` 增加商业化前的 Phase 4 hosted beta readiness gate 和 Phase 5 team launch gate,同时继续保持 billing disabled |
|
|
227
|
+
| Action 标签 | `v0.43.0`、`v0` |
|
|
228
228
|
| npm 发布 | GitHub Actions Trusted Publisher/OIDC,无需长期 npm token |
|
|
229
229
|
| 仓库可信度加固 | 严格 branch protection、Dependabot、CodeQL、fast-check fuzzing、signed release provenance assets、private vulnerability reporting、secret scanning 和 push protection |
|
|
230
230
|
| 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 已通过 |
|
|
@@ -385,6 +385,8 @@ GitHub Marketplace wrapper 决策见 [docs/github-marketplace-wrapper-decision.m
|
|
|
385
385
|
|
|
386
386
|
下一步 hosted source checkout 仍然要保持窄边界:把现有 read-only checkout worker 放到同一个 selected-repository identity 后面,继续固定 `pr-risk --json` 命令,只把 compact findings 写入 Check Run,并在扩大 trial 前要求 deployed cleanup、log-boundary 和 rollback evidence。hosted worker export 现在包含 `createHostedSourceCheckoutTrialPlan`、`createHostedSourceCheckoutEvidence` 和 `evaluateHostedSourceCheckoutTrialGate`,用于在进入 Phase 4 beta 前统一检查 checkout start/end、token removal、CLI start/end、compact report write、Check Run write、cleanup status、live smoke、rollback、monitoring 和 incident owner proof。
|
|
387
387
|
|
|
388
|
+
`ai-saas-guard/hosted/beta` export 新增 `evaluateHostedBetaReadinessGate` 和 `evaluateTeamLaunchGateReadiness`。这两个商业化前 gate 会阻止 hosted beta 在 selected-repository install limit、abuse control、安全 telemetry、uninstall deletion proof、rollback、support owner、beta smoke 和 no-audit-claim wording 不完整时开放;也会阻止 team use 在 org policy config、required status-check docs、suppression audit、reviewer checklist、release evidence export、retention docs 和 billing-disabled proof 不完整时推进。
|
|
389
|
+
|
|
388
390
|
Hosted 安装、权限和隐私边界见 [hosted-install-privacy.md](hosted-install-privacy.md):selected-repository 权限、支持的 GitHub 事件、Check Run 数据边界、卸载清理,以及为什么本地 CLI 仍然是私有/离线路径。
|
|
389
391
|
|
|
390
392
|
相关文档:
|
|
@@ -24,6 +24,11 @@ The package exports `ai-saas-guard/hosted/app` with:
|
|
|
24
24
|
- `createHostedNodeCheckoutAppPlatform`
|
|
25
25
|
- `planHostedNodeContainerDeployment`
|
|
26
26
|
|
|
27
|
+
The package also exports `ai-saas-guard/hosted/beta` with:
|
|
28
|
+
|
|
29
|
+
- `evaluateHostedBetaReadinessGate`
|
|
30
|
+
- `evaluateTeamLaunchGateReadiness`
|
|
31
|
+
|
|
27
32
|
The staging deployment planner in [hosted-staging-deployment.md](hosted-staging-deployment.md) composes this Node/container deployment plan with real provider references, hosted operational release-gate evidence, and GitHub App promotion gates.
|
|
28
33
|
|
|
29
34
|
## HTTP Ingress
|
|
@@ -134,6 +139,6 @@ It does not return:
|
|
|
134
139
|
|
|
135
140
|
## Current Status
|
|
136
141
|
|
|
137
|
-
The repository can now instantiate a Node/container hosted app skeleton, route signed webhooks into the hosted service runtime, process one worker tick through adapters, compose the real read-only checkout scan runner behind a token-provider boundary, expose clamped worker safety budgets, validate provider adapter references before deployment,
|
|
142
|
+
The repository can now instantiate a Node/container hosted app skeleton, route signed webhooks into the hosted service runtime, process one worker tick through adapters, compose the real read-only checkout scan runner behind a token-provider boundary, expose clamped worker safety budgets, validate provider adapter references before deployment, evaluate one Phase 3 source-checkout trial gate through `evaluateHostedSourceCheckoutTrialGate`, and evaluate pre-commercial Phase 4/5 gates through `evaluateHostedBetaReadinessGate` and `evaluateTeamLaunchGateReadiness`.
|
|
138
143
|
|
|
139
|
-
A public hosted environment still requires actual platform infrastructure, a public HTTPS webhook URL, platform secrets, durable queue/storage, worker sandboxing, GitHub Checks API credentials at runtime, monitoring, rollback, incident-response evidence, and a passing Phase
|
|
144
|
+
A public hosted environment still requires actual platform infrastructure, a public HTTPS webhook URL, platform secrets, durable queue/storage, worker sandboxing, GitHub Checks API credentials at runtime, monitoring, rollback, incident-response evidence, a passing Phase 3 gate, and a passing Phase 4 beta readiness gate. Team workflow rollout additionally requires the Phase 5 team launch gate. Use [hosted-staging-deployment.md](hosted-staging-deployment.md) to plan and block staging exposure until those provider references and evidence exist.
|
|
@@ -192,6 +192,28 @@ The gate combines:
|
|
|
192
192
|
|
|
193
193
|
It returns `readyForPhase4Beta: true` only when all four layers pass. Otherwise it returns safe blocked reasons and the next action: do not open hosted beta until the missing proof is rerun. The response must remain compact and privacy-safe: no raw source, raw diffs, checkout paths, installation tokens, public hosted scanner claim, private URLs, or PR-authored commands.
|
|
194
194
|
|
|
195
|
+
### Phase 4 Hosted Beta Readiness Gate
|
|
196
|
+
|
|
197
|
+
The v0.43 `ai-saas-guard/hosted/beta` export adds `evaluateHostedBetaReadinessGate`. This gate is pre-commercial. It does not enable billing, pricing, usage metering, or a marketplace listing.
|
|
198
|
+
|
|
199
|
+
It returns `readyForPublicBeta: true` only when:
|
|
200
|
+
|
|
201
|
+
- Phase 3 source-checkout trial gate already passed
|
|
202
|
+
- installs remain selected-repository only
|
|
203
|
+
- public install and privacy docs are ready
|
|
204
|
+
- rate limits and an abuse kill switch are enabled
|
|
205
|
+
- telemetry records only safe operational metadata
|
|
206
|
+
- uninstall deletion, rollback, incident owner, support path, and beta smoke evidence exist
|
|
207
|
+
- public wording avoids pentest, full-audit, and certification claims
|
|
208
|
+
- raw source, raw diffs, PR-authored text, and installation tokens are not stored
|
|
209
|
+
- repository and concurrency limits stay within the beta caps
|
|
210
|
+
|
|
211
|
+
### Phase 5 Team Launch Gate
|
|
212
|
+
|
|
213
|
+
The same export adds `evaluateTeamLaunchGateReadiness`. This gate is also pre-commercial. It exists so design partners can use the hosted launch gate in a team workflow before paid packaging exists.
|
|
214
|
+
|
|
215
|
+
It returns `readyForTeamUse: true` only when the hosted beta gate passed and the team workflow has org policy config, required status-check documentation, suppression audit, reviewer checklist, release evidence export, team docs, admin-bypass documentation, retention documentation, and proof that commercial billing remains disabled.
|
|
216
|
+
|
|
195
217
|
### Log Boundary Evidence
|
|
196
218
|
|
|
197
219
|
Before exposure, sample ingress, queue, worker, report, and Check Run logs for the release candidate. The sample may contain scan key, installation ID, repository ID, PR number, head SHA, scanner version, duration, summary counts, error class, and cleanup status.
|
|
@@ -10,6 +10,10 @@ Recorded on 2026-05-25 from the deployed Cloudflare Worker plus temporary GitHub
|
|
|
10
10
|
|
|
11
11
|
| Check | Evidence | Result |
|
|
12
12
|
| --- | --- | --- |
|
|
13
|
+
| Cloudflare Worker health, v0.43.0 | `GET https://ai-saas-guard-hosted.zr9959.workers.dev/healthz` returned `ok: true`, routes including `/github/app/install-info`, `checkRunPublisher: "configured"`, `scannerVersion: "0.43.0"`, and all privacy flags set to false for raw payloads, PR text, source, diffs, secrets, customer payloads, checkout paths, and installation tokens | Passed |
|
|
14
|
+
| Public install guidance, v0.43.0 | `GET https://ai-saas-guard-hosted.zr9959.workers.dev/github/app/install-info` returned the `ai-saas-guard-hosted` install URL, selected-repository boundary wording, first-slice permissions `checks: write`, `contents: read`, `metadata: read`, `pull_requests: read`, subscribed events `pull_request`, `installation`, and `installation_repositories`, uninstall cleanup wording, `scannerVersion: "0.43.0"`, and no private keys, webhook secrets, installation tokens, source, diffs, or customer payloads | Passed |
|
|
15
|
+
| Deployed Worker version, v0.43.0 | `wrangler deploy` uploaded 38.57 KiB / gzip 9.86 KiB and deployed version `8744d3db-0114-4653-85e2-f1554ff1b26b` at `2026-05-25T14:00:03Z` verification time | Passed |
|
|
16
|
+
| Real hosted PR smoke, v0.43.0 | `node scripts/hosted-pr-smoke.mjs --evidence-file /tmp/ai-saas-guard-hosted-smoke-v0.43.json` opened temporary PR `#91`, waited for Check Run `77724168740` on head SHA `6d62e52b243d657dd949b48c3333224905caa830`, received conclusion `success`, closed the PR, restored the original branch, deleted the local branch, and deleted 9 staging KV records with `remainingSmokeKeys: 0`; `gh pr view 91` returned `state: "CLOSED"`, `git ls-remote --heads origin codex/hosted-smoke-20260525140128` returned no remote branch, and `wrangler kv key list --namespace-id fa5344fbd7944de6a776bf8731d58460 --remote` returned `[]` after cleanup | Passed |
|
|
13
17
|
| Cloudflare Worker health, v0.42.0 | `GET https://ai-saas-guard-hosted.zr9959.workers.dev/healthz` returned `ok: true`, routes including `/github/app/install-info`, `checkRunPublisher: "configured"`, `scannerVersion: "0.42.0"`, and all privacy flags set to false for raw payloads, PR text, source, diffs, secrets, customer payloads, checkout paths, and installation tokens | Passed |
|
|
14
18
|
| Public install guidance, v0.42.0 | `GET https://ai-saas-guard-hosted.zr9959.workers.dev/github/app/install-info` returned the `ai-saas-guard-hosted` install URL, selected-repository boundary wording, first-slice permissions `checks: write`, `contents: read`, `metadata: read`, `pull_requests: read`, subscribed events `pull_request`, `installation`, and `installation_repositories`, uninstall cleanup wording, `scannerVersion: "0.42.0"`, and no private keys, webhook secrets, installation tokens, source, diffs, or customer payloads | Passed |
|
|
15
19
|
| Deployed Worker version, v0.42.0 | `wrangler deploy` uploaded 38.57 KiB / gzip 9.86 KiB and deployed version `6de0811e-11bf-46a6-9b7b-cbecda409695` at `2026-05-25T13:40:11Z` verification time | Passed |
|
package/docs/npm-publishing.md
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
## Current State
|
|
6
6
|
|
|
7
7
|
- Package name: `ai-saas-guard`
|
|
8
|
-
- Current published version: `0.
|
|
8
|
+
- Current published version: `0.43.0`
|
|
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.
|
|
12
|
+
- GitHub Release: `v0.43.0`
|
|
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.
|
|
21
|
+
1. Create and review a release tag such as `v0.43.0`.
|
|
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.
|
|
@@ -23,7 +23,7 @@ This Worker is a real hosted ingress with first-slice Check Run publishing code,
|
|
|
23
23
|
- `HOSTED_EVENTS`: Cloudflare KV namespace for compact delivery and queued scan records.
|
|
24
24
|
- `WEBHOOK_SECRET`: Worker secret matching the GitHub App webhook secret.
|
|
25
25
|
- `GITHUB_APP_PRIVATE_KEY`: Worker secret for the staging GitHub App private key, used only in memory to sign short-lived GitHub App JWTs.
|
|
26
|
-
- `SCANNER_VERSION`: public version string, currently `0.
|
|
26
|
+
- `SCANNER_VERSION`: public version string, currently `0.43.0`.
|
|
27
27
|
- `GITHUB_APP_ID`, `GITHUB_APP_SLUG`, `GITHUB_APP_INSTALLATION_ID`: public staging identifiers for the private GitHub App installation.
|
|
28
28
|
|
|
29
29
|
## Deployment
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-saas-guard",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.43.0",
|
|
4
4
|
"description": "Local-first CLI that catches launch blockers in AI-built Next.js/Supabase/Stripe SaaS apps.",
|
|
5
5
|
"readmeFilename": "README.md",
|
|
6
6
|
"type": "module",
|
|
@@ -74,6 +74,10 @@
|
|
|
74
74
|
"types": "./dist/hosted/deployed-staging.d.ts",
|
|
75
75
|
"default": "./dist/hosted/deployed-staging.js"
|
|
76
76
|
},
|
|
77
|
+
"./hosted/beta": {
|
|
78
|
+
"types": "./dist/hosted/beta.d.ts",
|
|
79
|
+
"default": "./dist/hosted/beta.js"
|
|
80
|
+
},
|
|
77
81
|
"./hosted/worker": {
|
|
78
82
|
"types": "./dist/hosted/worker.d.ts",
|
|
79
83
|
"default": "./dist/hosted/worker.js"
|