Both TickShield app skills now uniformly follow the app-<action> naming convention (app-dev, app-publish) — the grandfathered-name exception is removed from AGENTS.md, README and skill-forge
6.3 KiB
6.3 KiB
接入自查清单(审查模式基准)
逐项审计,输出三档:通过 / 不符(die 级,阻断接入)/ 风险(warn 级,不阻断但必须列清单)。每项给证据(文件:行号)。[S] = scripts/check-app.sh 可自动查。
A. 身份与清单
| # | 项 | 档 | 验证方法 |
|---|---|---|---|
| A1 | app.manifest.json 在仓库根 |
die [S] |
文件存在 |
| A2 | listingKey 过 ^[a-z0-9][a-z0-9-]{0,62}$,全局唯一,用户已确认不再变 |
die [S] |
正则 + 用户确认记录 |
| A3 | version 严格 semver |
die [S] |
正则 |
| A4 | type ∈ micro/service(缺省=service) |
die [S] |
取值 |
| A5 | scopes 每项命名空间格式(≥两段,建议 <listingKey>.<action>) |
die [S] |
正则 |
| A6 | manifest 不含 deployDescriptor |
die [S] |
无该 key |
| A7 | exchangeTargets/dependencies 各项是合法 listingKey |
die | 正则 |
| A8 | navItems/footerNavItems 每项含 id/label/path;icon 为 emoji/字符或 lucide 名(写错名静默兜底成字符,须眼见为实);aclManifest.pages 含 key/label,audience ∈ admin/viewer/all |
die [S] |
对照契约表 §2.1 |
| A9 | color 为 #RRGGBB;icon≤64 / cat≤64 / tagline≤120 / desc≤2000 |
warn [S] |
长度/格式 |
| A10 | 治理字段变更知悉审核语义(202 进队列,批准前不生效) | log | 口头/文档确认 |
B. 镜像与入口
| # | 项 | 档 | 验证方法 |
|---|---|---|---|
| B1 | Dockerfile FROM tickshield-node-runtime:base |
die [S] |
首行非注释指令 |
| B2 | RUN ln -s /opt/xgent/runtime/node_modules /app/node_modules(或等价) |
die [S] |
grep |
| B3 | 不覆盖 CMD/ENTRYPOINT(继承基础镜像入口) | die [S] |
无 CMD/ENTRYPOINT 指令 |
| B4 | APP_ENTRY 指向的 ESM 模块导出 handler(或 default 函数) |
die [S] |
grep export |
| B5 | 启动副作用写模块顶层,失败 process.exit(1)(带病不启动) |
die | 读代码 |
| B6 | 不监听端口、不写注册/心跳/下线代码(runtime-entry 全包) | die | 无 listen(/createServer( 于入口(runtime-entry 之外) |
| B7 | 钉版:基础镜像 tag、依赖版本钉死;构建期缺料让构建失败可见 | warn | 读 Dockerfile/CI |
| B8 | 构建上下文含需 COPY 的全部路径(monorepo packages 时上下文=仓根) | warn | docker build 实跑 |
C. 四道闸与租户隔离
| # | 项 | 档 | 验证方法 |
|---|---|---|---|
| C1 | createGuard({portalUrl, appKey, appSecret}) 三参齐(env 读入) |
die [S] |
grep |
| C2 | 业务路由经 guard.routes/guard.protect 挂 spec(scope/role/pid) |
die [S] |
grep + 读路由表 |
| C3 | 业务 SQL 全走 tdb.query;无第二个 new pg.Pool 跑业务(dbCheck 探活池是唯一例外) |
die [S] |
grep pg.Pool 计数 |
| C4 | INSERT 显式写 tenant_id(第一参 claims.tenant_id) |
die | 读代码逐条 INSERT |
| C5 | JOIN/子查询/UNION/CTE 走 queryUnscoped(sql, params, tenantId) 且显式租户过滤 |
die | grep + 读代码 |
| C6 | 启动 await tdb.start() + await guard.assertTenantTables(tdb, [全部业务表]) |
die [S] |
grep |
| C7 | 不自实现 JWT 验签替代四道闸(自定义域名下无网关验签,全靠 guard 自省) | die | grep jsonwebtoken|jwt.verify |
| C8 | 每张业务表含 tenant_id 列(迁移文件可查) |
die | 读迁移/schema |
| C9 | 物理库租户经 TENANT_DS_<KEY> env 注入 DSN,不写死多库连接串 |
warn | 读 env 用法 |
D. 路径与网络
| # | 项 | 档 | 验证方法 |
|---|---|---|---|
| D1 | 应用 API 路径无 /api、/auth、/svc 前缀(含自定义域名规划) |
die [S] |
grep 路由表 |
| D2 | compose/部署描述:container_name == 网络 alias == listingKey |
die | 读 compose/k8s |
| D3 | 容器接入网关所在 Docker 网络 | die | 读 compose |
| D4 | 监听 PORT(默认 8080),不在代码里写死其他端口 |
warn | grep listen(应在 runtime-entry 外不存在) |
E. micro 前端(type=micro 时)
| # | 项 | 档 | 验证方法 |
|---|---|---|---|
| E1 | portal-sdk 用 vendor 版 <script src="/apps/<key>/_/vendor/portal-sdk.js">,源码不 import '@aigrego/portal-sdk' |
die [S] |
grep |
| E2 | index.html 资源引用全部绝对路径 /apps/<key>/_/... |
die [S] |
读 html |
| E3 | 无内联 <script> 代码块(PROD CSP 严格 default-src 'self') |
die [S] |
grep html |
| E4 | sdk.ready() 握手 + 非 iframe 环境降级友好页 |
die | 读 sdk 封装 |
| E5 | 后端调用一律 sdk.callService(appKey, ...),不直接 fetch /svc/... |
warn | grep fetch |
| E6 | acl 驱动页面显隐/前端路由守卫(UX 闸;真闸在后端) | warn | 读路由守卫 |
| E7 | i18n 只读宿主 localStorage['ts-lang'] + storage 事件监听,不反写 |
warn | grep |
| E8 | 产物构建为单 bundle;发布 publish --dist 包根直接含 index.html |
warn | 读 build 脚本 |
F. 日志/追踪/密钥卫生
| # | 项 | 档 | 验证方法 |
|---|---|---|---|
| F1 | 日志用 @aigrego/logger JSON 行写 stdout;每请求一行 |
warn [S] |
grep createLogger |
| F2 | 密钥/令牌值不进日志 fields(自动脱敏只是兜底) | die | grep 可疑字段名 |
| F3 | 自建出站 HTTP 调用注入 traceparent 头 |
warn | 读出站调用 |
| F4 | 仓库内无明文 APP_SECRET/令牌;.gitignore 挡 .aigrego-registry.env |
die [S] |
grep + git ls-files |
| F5 | CI 用 secrets 注入 APP_SECRET,不走命令行参数 |
warn | 读 CI yaml |
G. 发布与文档
| # | 项 | 档 | 验证方法 |
|---|---|---|---|
| G1 | .gitea/workflows/release.yaml(或等价 CI):whoami 先验 → buildx 推镜像 → publish --manifest --image --store --wait |
warn | 读 CI |
| G2 | docs/PRD_app-<listingKey>.md 存在,开头六字段齐(项目代号/应用名称/listingKey/文档版本/文档状态/对标产品),含 Goals/Non-Goals |
warn [S] |
读文件头 |
| G3 | 注释/日志/文档中文;注释绑定 FR-/TKT-/BUG- 编号写清为什么 | warn | 抽查 |
| G4 | 镜像 host 在平台 registries 白名单(部署前找平台管理员确认) | die(部署时) | 平台侧确认 |
| G5 | 联调六项(注册/健康/四道闸/租户隔离/SDK 握手/制品交付)演练留档 | die(上线前) | verify 日志 |