DevOS v1 + Phase 2: unified resource model, infra ops, website deployment, AI chat ops

- Monorepo: NestJS API (Fastify) + React web (antd/ProComponents) + shared packages
- PostgreSQL/Prisma (unified resources, relations graph, audit, events, jobs)
- Auth/RBAC/workspace isolation, credential vault (AES-256-GCM)
- Servers/SSH, Docker discovery & lifecycle, Job Center
- Websites & deployments (git provider credential clone, env, health verification)
- Domains/DNS (Cloudflare adapter), certificates (TLS probe), monitoring
- Automation (cron/event/webhook HMAC + notifications), AI Gateway, MCP (29 tools)
- AI chat window (LLM function-calling + rules fallback, SSE streaming, approvals)
- Notes: Vditor WYSIWYG markdown editor, non-blocking autosave
- Tests: 35 unit/security tests; UI audit clean (desktop+mobile, deep links)
This commit is contained in:
phptits
2026-09-10 06:35:55 +00:00
commit 0d6cd37579
209 changed files with 22783 additions and 0 deletions
+84
View File
@@ -0,0 +1,84 @@
/** 安全回归测试(Phase A,对应 11-TEST-ACCEPTANCE 安全测试项) */
import { describe, test, expect } from "bun:test";
import {
buildSignatureHeader,
verifyWebhookSignature,
SIGNATURE_TOLERANCE_MS,
} from "../apps/api/src/common/security/webhook-signature";
import { SecurityPolicyService, assertProductionSecrets } from "../apps/api/src/common/security/security-policy.service";
import { ConfigService } from "../apps/api/src/common/config/config.service";
describe("webhook HMAC 签名", () => {
const secret = "whsec-test";
const body = JSON.stringify({ event: "deployment.failed" });
test("合法签名通过", () => {
const header = buildSignatureHeader(secret, body);
expect(verifyWebhookSignature(secret, header, body).ok).toBe(true);
});
test("错误密钥被拒绝", () => {
const header = buildSignatureHeader(secret, body);
expect(verifyWebhookSignature("other", header, body).ok).toBe(false);
});
test("篡改请求体被拒绝", () => {
const header = buildSignatureHeader(secret, body);
expect(verifyWebhookSignature(secret, header, body + "x").ok).toBe(false);
});
test("过期时间戳(重放)被拒绝", () => {
const stale = Math.floor((Date.now() - SIGNATURE_TOLERANCE_MS - 60_000) / 1000);
const header = `t=${stale},v1=${require("node:crypto").createHmac("sha256", secret).update(`${stale}.${body}`).digest("hex")}`;
const result = verifyWebhookSignature(secret, header, body);
expect(result.ok).toBe(false);
expect(result.reason).toContain("replay");
});
test("缺失/畸形签名被拒绝", () => {
expect(verifyWebhookSignature(secret, undefined, body).ok).toBe(false);
expect(verifyWebhookSignature(secret, "t=abc,v1=zz", body).ok).toBe(false);
});
});
describe("限流器", () => {
test("窗口内超过上限被拒绝", () => {
const svc = new SecurityPolicyService(new ConfigService());
let allowed = 0;
for (let i = 0; i < 12; i++) {
if (svc.checkRate("login:1.2.3.4")) allowed++;
}
expect(allowed).toBeLessThanOrEqual(10);
});
test("不同维度键相互隔离", () => {
const svc = new SecurityPolicyService(new ConfigService());
expect(svc.checkRate("login:5.5.5.5")).toBe(true);
expect(svc.checkRate("login:6.6.6.6")).toBe(true);
});
});
describe("注册开关", () => {
test("生产模式下默认关闭", () => {
const svc = new SecurityPolicyService(new ConfigService());
// 本测试进程 NODE_ENV 非 production → 默认开启;显式环境由部署配置决定
const verdict = svc.checkRegistration();
expect(typeof verdict.allowed).toBe("boolean");
});
});
describe("生产 secret 校验", () => {
test("拒绝已知开发默认 APP_SECRET", () => {
const origEnv = process.env.NODE_ENV;
const origSecret = process.env.APP_SECRET;
try {
process.env.NODE_ENV = "production";
process.env.APP_SECRET = "dev-devos-app-secret-change-me-please-0123456789";
process.env.ENCRYPTION_KEY = "a".repeat(64);
expect(() => new ConfigService()).toThrow(/APP_SECRET/);
} finally {
process.env.NODE_ENV = origEnv;
process.env.APP_SECRET = origSecret;
}
});
});