@h-ai/cli 0.1.0-alpha9 → 1.0.0-beta.2
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.en.md +229 -0
- package/README.ja.md +229 -0
- package/README.md +175 -113
- package/dist/chunk-AKV2CQZV.js +1497 -0
- package/dist/chunk-AKV2CQZV.js.map +1 -0
- package/dist/chunk-EF7WOFWZ.js +7557 -0
- package/dist/chunk-EF7WOFWZ.js.map +1 -0
- package/dist/chunk-MUHRBJSW.js +29272 -0
- package/dist/chunk-MUHRBJSW.js.map +1 -0
- package/dist/chunk-ZSDEVXZ7.js +38 -0
- package/dist/{chunk-2H7UOFLK.js.map → chunk-ZSDEVXZ7.js.map} +1 -1
- package/dist/cli-config-templates-HHFHNXBN.js +5 -0
- package/dist/cli-config-templates-HHFHNXBN.js.map +1 -0
- package/dist/cli-skill-templates-PN4FLGBC.js +5 -0
- package/dist/cli-skill-templates-PN4FLGBC.js.map +1 -0
- package/dist/index.js +4444 -554
- package/dist/index.js.map +1 -1
- package/dist/metafile-esm.json +1 -0
- package/dist/src-TEBHR5I5.js +5 -0
- package/dist/src-TEBHR5I5.js.map +1 -0
- package/package.json +35 -15
- package/templates/README.md +56 -114
- package/templates/apps/admin/messages/en-US.json +7 -0
- package/templates/apps/admin/messages/ja-JP.json +40 -0
- package/templates/apps/admin/messages/zh-CN.json +7 -0
- package/templates/apps/admin/src/routes/+layout.svelte.hbs +65 -8
- package/templates/apps/admin/src/routes/+page.svelte.hbs +35 -14
- package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +54 -22
- package/templates/apps/admin/src/routes/admin/+page.svelte.hbs +33 -24
- package/templates/apps/admin/src/routes/admin/settings/+page.svelte.hbs +16 -13
- package/templates/apps/api/.dockerignore.hbs +25 -0
- package/templates/apps/api/.gitignore.hbs +22 -0
- package/templates/apps/api/.npmrc.hbs +1 -0
- package/templates/apps/api/apps/{{projectName}}-contract/README.md.hbs +39 -0
- package/templates/apps/api/apps/{{projectName}}-contract/package.json.hbs +41 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/app-contract.ts.hbs +27 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/app-schemas.ts.hbs +28 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/index.ts.hbs +5 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +16 -0
- package/templates/apps/api/apps/{{projectName}}-contract/tests/contract.test.ts.hbs +18 -0
- package/templates/apps/api/apps/{{projectName}}-contract/tsconfig.json.hbs +12 -0
- package/templates/apps/api/apps/{{projectName}}-contract/tsup.config.ts.hbs +11 -0
- package/templates/apps/api/apps/{{projectName}}-contract/vitest.config.ts.hbs +9 -0
- package/templates/apps/api/apps/{{projectName}}-serv/README.md.hbs +60 -0
- package/templates/apps/api/apps/{{projectName}}-serv/config/_core.yml.hbs +17 -0
- package/templates/apps/api/apps/{{projectName}}-serv/config/_serv.yml.hbs +54 -0
- package/templates/apps/api/apps/{{projectName}}-serv/data/.gitkeep.hbs +1 -0
- package/templates/apps/api/apps/{{projectName}}-serv/package.json.hbs +66 -0
- package/templates/apps/api/apps/{{projectName}}-serv/src/app.ts.hbs +119 -0
- package/templates/apps/api/apps/{{projectName}}-serv/src/build-metadata.ts.hbs +7 -0
- package/templates/apps/api/apps/{{projectName}}-serv/src/index.ts.hbs +41 -0
- package/templates/apps/api/apps/{{projectName}}-serv/src/lib/server/init.ts.hbs +165 -0
- package/templates/apps/api/apps/{{projectName}}-serv/src/server/procedures/app-procedures.ts.hbs +57 -0
- package/templates/apps/api/apps/{{projectName}}-serv/src/server/procedures/index.ts.hbs +41 -0
- package/templates/apps/api/apps/{{projectName}}-serv/tests/service.test.ts.hbs +176 -0
- package/templates/apps/api/apps/{{projectName}}-serv/tsconfig.json.hbs +16 -0
- package/templates/apps/api/apps/{{projectName}}-serv/tsup.config.ts.hbs +20 -0
- package/templates/apps/api/apps/{{projectName}}-serv/vitest.config.ts.hbs +12 -0
- package/templates/apps/api/e2e/api-serv.spec.ts.hbs +113 -0
- package/templates/apps/api/e2e/capture-evidence.ts.hbs +23 -0
- package/templates/apps/api/eslint.config.js.hbs +30 -0
- package/templates/apps/api/hai.json.hbs +4 -0
- package/templates/apps/api/images/serv.Dockerfile.hbs +37 -0
- package/templates/apps/api/package.json.hbs +53 -0
- package/templates/apps/api/playwright.config.ts.hbs +67 -0
- package/templates/apps/api/pnpm-workspace.yaml.hbs +40 -0
- package/templates/apps/api/tsconfig.base.json +14 -0
- package/templates/apps/fullstack/.dockerignore.hbs +25 -0
- package/templates/apps/fullstack/.gitignore.hbs +38 -0
- package/templates/apps/fullstack/.npmrc.hbs +1 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/.env.example.hbs +10 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +67 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/capacitor.config.ts.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/eslint.config.js.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/index.html.hbs +22 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/messages/en-US.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/messages/ja-JP.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/messages/zh-CN.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/package.json.hbs +86 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/project.inlang/settings.json.hbs +17 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/public/runtime-config.js.hbs +4 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/App.svelte.hbs +59 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.css.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.d.ts.hbs +8 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/build-metadata.ts.hbs +9 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/lib/capacitor.ts.hbs +19 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/main.ts.hbs +21 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/svelte.config.js.hbs +16 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/tsconfig.json.hbs +23 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +74 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/.env.example.hbs +6 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +64 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/eslint.config.js.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/index.html.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/en-US.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/ja-JP.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/zh-CN.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/package.json.hbs +66 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/project.inlang/settings.json.hbs +17 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/App.svelte.hbs +25 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.css.hbs +18 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.d.ts.hbs +8 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/build-metadata.ts.hbs +9 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/main.ts.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/Cargo.toml.hbs +33 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/build.rs.hbs +6 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/capabilities/default.json.hbs +16 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/128x128.png +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/128x128@2x.png +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/32x32.png +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/icon.icns +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/icon.ico +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/src/lib.rs.hbs +91 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/src/main.rs.hbs +8 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/tauri.conf.json.hbs +46 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/svelte.config.js.hbs +14 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/tsconfig.json.hbs +22 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +89 -0
- package/templates/apps/fullstack/apps/{{projectName}}-miniapp/README.md.hbs +25 -0
- package/templates/apps/fullstack/apps/{{projectName}}-miniapp/messages/en-US.json.hbs +12 -0
- package/templates/apps/fullstack/apps/{{projectName}}-miniapp/messages/ja-JP.json.hbs +12 -0
- package/templates/apps/fullstack/apps/{{projectName}}-miniapp/messages/zh-CN.json.hbs +12 -0
- package/templates/apps/fullstack/apps/{{projectName}}-miniapp/project.inlang/settings.json.hbs +17 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +54 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/eslint.config.js.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/index.html.hbs +21 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/messages/en-US.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/messages/ja-JP.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/messages/zh-CN.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/package.json.hbs +53 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/project.inlang/settings.json.hbs +17 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/public/runtime-config.js.hbs +1 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/App.svelte.hbs +18 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.css.hbs +18 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.d.ts.hbs +8 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/build-metadata.ts.hbs +9 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/main.ts.hbs +14 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/svelte.config.js.hbs +16 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/tsconfig.json.hbs +23 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +76 -0
- package/templates/apps/fullstack/docs/security-configuration.md.hbs +349 -0
- package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +988 -0
- package/templates/apps/fullstack/e2e/session-close.spec.ts.hbs +119 -0
- package/templates/apps/fullstack/eslint.config.js.hbs +41 -0
- package/templates/apps/fullstack/hai.json.hbs +11 -0
- package/templates/apps/fullstack/images/serv.Dockerfile.hbs +38 -0
- package/templates/apps/fullstack/images/web/19-runtime-config.envsh.hbs +5 -0
- package/templates/apps/fullstack/images/web/nginx.conf.hbs +24 -0
- package/templates/apps/fullstack/images/web/runtime-config.js.template.hbs +3 -0
- package/templates/apps/fullstack/images/web.Dockerfile.hbs +37 -0
- package/templates/apps/fullstack/package.json.hbs +61 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/README.md.hbs +40 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/package.json.hbs +30 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-contract.ts.hbs +78 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-schemas.ts.hbs +134 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/app-contract.ts.hbs +20 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/app-schemas.ts.hbs +35 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/index.ts.hbs +7 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +23 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/tests/contract.test.ts.hbs +31 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/tsconfig.json.hbs +9 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/tsup.config.ts.hbs +9 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +84 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_ai.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_audit.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_cache.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_core.yml.hbs +22 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_db.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_feedback.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_iam.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_payment.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_reach.yml.hbs +60 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_scheduler.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_serv.yml.hbs +64 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_storage.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_vecdb.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/data/.gitkeep.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +62 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/app-server.ts.hbs +115 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/build-metadata.ts.hbs +7 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/index.ts.hbs +40 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/admin-service.ts.hbs +294 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/audit-jobs.ts.hbs +28 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/business-settings.ts.hbs +50 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/messages.ts.hbs +50 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/admin-procedures.ts.hbs +106 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/app-procedures.ts.hbs +49 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/index.ts.hbs +34 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/runtime.ts.hbs +159 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/security-roles.ts.hbs +73 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/app-server.test.ts.hbs +505 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/runtime.test.ts.hbs +72 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/security.test.ts.hbs +183 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tsconfig.json.hbs +10 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tsup.config.ts.hbs +18 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/vitest.config.ts.hbs +12 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/.gitignore.hbs +10 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/README.md.hbs +97 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/en-US.json.hbs +164 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/ja-JP.json.hbs +164 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/zh-CN.json.hbs +164 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/package.json.hbs +55 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/project.inlang/settings.json.hbs +11 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/index.ts.hbs +7 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/api-client.ts.hbs +94 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/feedback-client.ts.hbs +36 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/sensitive-actions.svelte.ts.hbs +16 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/session-recovery.svelte.ts.hbs +4 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AdminWorkspace.svelte.hbs +122 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AppShell.svelte.hbs +90 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/FeedbackEntry.svelte.hbs +86 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/audit.svelte.hbs +94 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/configuration.svelte.hbs +25 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/feedback.svelte.hbs +157 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/roles.svelte.hbs +77 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/settings.svelte.hbs +44 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/users.svelte.hbs +216 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/security/role-label.ts.hbs +12 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/guide-store.ts.hbs +55 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/management-store.svelte.ts.hbs +614 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/theme-store.svelte.ts.hbs +23 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/svelte.config.js.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/api-client.test.ts.hbs +150 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/management-store.test.ts.hbs +253 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/tsconfig.json.hbs +17 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/vitest.config.ts.hbs +7 -0
- package/templates/apps/fullstack/playwright.config.ts.hbs +114 -0
- package/templates/apps/fullstack/playwright.session-close.config.ts.hbs +18 -0
- package/templates/apps/fullstack/pnpm-workspace.yaml.hbs +38 -0
- package/templates/apps/fullstack/tsconfig.base.json +14 -0
- package/templates/apps/h5/messages/en-US.json +3 -0
- package/templates/apps/h5/messages/ja-JP.json +40 -0
- package/templates/apps/h5/messages/zh-CN.json +3 -0
- package/templates/apps/h5/src/routes/+layout.svelte.hbs +85 -30
- package/templates/apps/h5/src/routes/+page.svelte.hbs +20 -8
- package/templates/apps/h5/src/routes/discover/+page.svelte.hbs +17 -6
- package/templates/apps/h5/src/routes/profile/+page.svelte.hbs +17 -6
- package/templates/apps/mobile-app/.env.hbs +3 -0
- package/templates/apps/{android-app → mobile-app}/capacitor.config.ts.hbs +2 -2
- package/templates/apps/mobile-app/index.html.hbs +14 -0
- package/templates/apps/mobile-app/messages/en-US.json +36 -0
- package/templates/apps/mobile-app/messages/ja-JP.json +36 -0
- package/templates/apps/mobile-app/messages/zh-CN.json +36 -0
- package/templates/apps/mobile-app/public/runtime-config.js +1 -0
- package/templates/apps/mobile-app/src/App.svelte.hbs +153 -0
- package/templates/apps/mobile-app/src/lib/api.ts.hbs +213 -0
- package/templates/apps/mobile-app/src/lib/app-config.ts.hbs +14 -0
- package/templates/apps/{android-app → mobile-app}/src/lib/capacitor.ts +6 -7
- package/templates/apps/mobile-app/src/lib/pages/home.svelte.hbs +58 -0
- package/templates/apps/mobile-app/src/lib/pages/profile.svelte.hbs +13 -0
- package/templates/apps/mobile-app/src/lib/pages/tasks.svelte.hbs +16 -0
- package/templates/apps/mobile-app/src/main.ts.hbs +11 -0
- package/templates/apps/website/messages/en-US.json +4 -2
- package/templates/apps/website/messages/ja-JP.json +34 -0
- package/templates/apps/website/messages/zh-CN.json +4 -2
- package/templates/apps/website/scripts/static-website.mjs.hbs +67 -0
- package/templates/apps/website/src/routes/+layout.svelte.hbs +77 -26
- package/templates/apps/website/src/routes/+layout.ts +3 -0
- package/templates/apps/website/src/routes/+page.svelte.hbs +31 -12
- package/templates/apps/website/src/routes/about/+page.svelte.hbs +11 -6
- package/templates/apps/website/src/routes/api/health/+server.ts +3 -0
- package/templates/apps/website/src/routes/contact/+page.svelte.hbs +44 -34
- package/templates/apps/website/src/routes/services/+page.svelte.hbs +27 -40
- package/templates/base/.dockerignore.hbs +27 -0
- package/templates/base/.gitignore.hbs +41 -0
- package/templates/base/.npmrc.hbs +1 -0
- package/templates/base/e2e/app.spec.ts.hbs +213 -0
- package/templates/base/e2e/helpers.ts +1 -1
- package/templates/base/eslint-rules.js +45 -0
- package/templates/base/eslint.config.js.hbs +34 -0
- package/templates/base/hai.json.hbs +4 -0
- package/templates/base/images/web/nginx.conf.hbs +24 -0
- package/templates/base/images/web.Dockerfile.hbs +72 -0
- package/templates/base/package.json.hbs +125 -49
- package/templates/base/playwright.config.ts +44 -6
- package/templates/base/pnpm-workspace.yaml.hbs +40 -0
- package/templates/base/src/app.css.hbs +40 -0
- package/templates/base/src/app.d.ts.hbs +14 -1
- package/templates/base/src/app.html.hbs +13 -0
- package/templates/base/src/hooks.server.ts.hbs +115 -43
- package/templates/base/src/lib/build-metadata.ts.hbs +7 -0
- package/templates/base/src/lib/server/init.ts.hbs +125 -152
- package/templates/base/src/lib/server/kit-config.ts.hbs +40 -0
- package/templates/base/src/routes/+layout.server.ts.hbs +35 -0
- package/templates/base/static/favicon.png +0 -0
- package/templates/base/svelte.config.js.hbs +84 -5
- package/templates/base/tests/scaffold.test.ts.hbs +102 -0
- package/templates/base/tsconfig.json.hbs +50 -0
- package/templates/base/vite.config.ts.hbs +117 -12
- package/templates/base/vitest.config.ts.hbs +19 -0
- package/templates/features/ai/routes/api/chat/+server.ts +6 -7
- package/templates/features/iam/routes-admin/(auth)/+layout.svelte.hbs +3 -17
- package/templates/features/iam/routes-admin/(auth)/auth/forgot-password/+page.svelte.hbs +10 -0
- package/templates/features/iam/routes-admin/(auth)/auth/login/+page.svelte.hbs +9 -96
- package/templates/features/iam/routes-admin/(auth)/auth/register/+page.svelte.hbs +9 -122
- package/templates/features/iam/routes-admin/(auth)/auth/reset-password/+page.svelte.hbs +10 -0
- package/templates/features/iam/routes-h5/auth/forgot-password/+page.svelte.hbs +10 -0
- package/templates/features/iam/routes-h5/auth/login/+page.svelte.hbs +9 -96
- package/templates/features/iam/routes-h5/auth/register/+page.svelte.hbs +9 -112
- package/templates/features/iam/routes-h5/auth/reset-password/+page.svelte.hbs +10 -0
- package/templates/features/iam/routes-shared/api/auth/captcha/+server.ts.hbs +4 -0
- package/templates/features/iam/routes-shared/api/auth/config/+server.ts +4 -0
- package/templates/features/iam/routes-shared/api/auth/login/+server.ts +1 -29
- package/templates/features/iam/routes-shared/api/auth/login/ldap/+server.ts +4 -0
- package/templates/features/iam/routes-shared/api/auth/login/otp/+server.ts +4 -0
- package/templates/features/iam/routes-shared/api/auth/logout/+server.ts +13 -6
- package/templates/features/iam/routes-shared/api/auth/otp/send/+server.ts +4 -0
- package/templates/features/iam/routes-shared/api/auth/password/renew/+server.ts +5 -0
- package/templates/features/iam/routes-shared/api/auth/password-reset/confirm/+server.ts +4 -0
- package/templates/features/iam/routes-shared/api/auth/password-reset/request/+server.ts +4 -0
- package/templates/features/iam/routes-shared/api/auth/reauthenticate/+server.ts +5 -0
- package/templates/features/iam/routes-shared/api/auth/register/+server.ts +1 -23
- package/templates/features/iam/routes-shared/api/auth/session/close/+server.ts.hbs +4 -0
- package/templates/features/iam/routes-website/auth/forgot-password/+page.svelte.hbs +10 -0
- package/templates/features/iam/routes-website/auth/login/+page.svelte.hbs +11 -0
- package/templates/features/iam/routes-website/auth/register/+page.svelte.hbs +11 -0
- package/templates/features/iam/routes-website/auth/reset-password/+page.svelte.hbs +10 -0
- package/templates/features/payment/routes/api/v1/payment/create/+server.ts +25 -23
- package/templates/features/payment/routes/api/v1/payment/notify/[provider]/+server.ts +5 -2
- package/templates/features/storage/routes/api/upload/+server.ts +10 -8
- package/templates/i18n/project.inlang/settings.json +2 -2
- package/templates/shared/.gitattributes +11 -0
- package/templates/shared/build-metadata.ts +42 -0
- package/templates/shared/container-runtime-config.sh +30 -0
- package/templates/shared/e2e-env.ts +98 -0
- package/templates/shared/hash-router.svelte.ts +83 -0
- package/templates/shared/public-base-path.mjs +19 -0
- package/templates/shared/run-e2e.mjs +104 -0
- package/templates/shared/vite-runtime-config.ts +56 -0
- package/templates/skills/AGENTS.md +75 -16
- package/templates/skills/CLAUDE.md +0 -11
- package/templates/skills/bridges/admin/AGENTS.md +89 -0
- package/templates/skills/bridges/api/AGENTS.md +83 -0
- package/templates/skills/bridges/fullstack/AGENTS.md.hbs +102 -0
- package/templates/skills/bridges/h5/AGENTS.md +88 -0
- package/templates/skills/bridges/mobile-app/AGENTS.md +100 -0
- package/templates/skills/bridges/website/AGENTS.md +88 -0
- package/templates/skills/copilot-instructions.md +3 -59
- package/templates/skills/hai-ai/SKILL.md +44 -715
- package/templates/skills/hai-ai/guide.md +457 -0
- package/templates/skills/hai-ai/reference.md +292 -0
- package/templates/skills/hai-api-client/SKILL.md +26 -339
- package/templates/skills/hai-api-client/reference.md +180 -0
- package/templates/skills/hai-api-contract/SKILL.md +36 -0
- package/templates/skills/hai-api-contract/reference.md +280 -0
- package/templates/skills/hai-app-create/SKILL.md +38 -351
- package/templates/skills/hai-app-create/collaboration.md +52 -0
- package/templates/skills/hai-app-create/development.md +243 -0
- package/templates/skills/hai-app-create/reference.md +376 -0
- package/templates/skills/hai-app-review/SKILL.md +57 -126
- package/templates/skills/hai-app-review/differential.md +34 -0
- package/templates/skills/hai-app-tests/SKILL.md +34 -454
- package/templates/skills/hai-app-tests/reference.md +462 -0
- package/templates/skills/hai-app-tests/validation.md +42 -0
- package/templates/skills/hai-audit/SKILL.md +37 -122
- package/templates/skills/hai-audit/reference.md +184 -0
- package/templates/skills/hai-build/SKILL.md +62 -315
- package/templates/skills/hai-build/paths.md +30 -0
- package/templates/skills/hai-build/reference.md +353 -0
- package/templates/skills/hai-cache/SKILL.md +26 -175
- package/templates/skills/hai-cache/reference.md +229 -0
- package/templates/skills/hai-capacitor/SKILL.md +24 -364
- package/templates/skills/hai-capacitor/reference.md +358 -0
- package/templates/skills/hai-change-plan/SKILL.md +46 -0
- package/templates/skills/hai-ci/SKILL.md +114 -0
- package/templates/skills/hai-core/SKILL.md +31 -469
- package/templates/skills/hai-core/reference.md +557 -0
- package/templates/skills/hai-core/request-access.md +65 -0
- package/templates/skills/hai-crypto/SKILL.md +29 -180
- package/templates/skills/hai-crypto/reference.md +317 -0
- package/templates/skills/hai-datapipe/SKILL.md +24 -207
- package/templates/skills/hai-datapipe/reference.md +204 -0
- package/templates/skills/hai-deploy/SKILL.md +53 -178
- package/templates/skills/hai-deploy/credentials.md +19 -0
- package/templates/skills/hai-deploy/middleware.md +129 -0
- package/templates/skills/hai-feedback/SKILL.md +85 -0
- package/templates/skills/hai-framework-sync/SKILL.md +105 -0
- package/templates/skills/hai-framework-sync/sync.md +49 -0
- package/templates/skills/hai-iam/SKILL.md +53 -325
- package/templates/skills/hai-iam/reference.md +535 -0
- package/templates/skills/hai-kit/SKILL.md +33 -329
- package/templates/skills/hai-kit/reference.md +202 -0
- package/templates/skills/hai-payment/SKILL.md +28 -262
- package/templates/skills/hai-payment/reference.md +295 -0
- package/templates/skills/hai-pr-review/SKILL.md +41 -0
- package/templates/skills/hai-reach/SKILL.md +28 -300
- package/templates/skills/hai-reach/reference.md +363 -0
- package/templates/skills/hai-reldb/SKILL.md +28 -449
- package/templates/skills/hai-reldb/reference.md +500 -0
- package/templates/skills/hai-scheduler/SKILL.md +26 -174
- package/templates/skills/hai-scheduler/reference.md +216 -0
- package/templates/skills/hai-serv/SKILL.md +60 -0
- package/templates/skills/hai-serv/reference.md +792 -0
- package/templates/skills/hai-spec-implement/SKILL.md +50 -0
- package/templates/skills/hai-spec-implement/changes.md +67 -0
- package/templates/skills/hai-spec-implement/evaluation.md +18 -0
- package/templates/skills/hai-spec-implement/handoff.md +47 -0
- package/templates/skills/hai-spec-implement/templates.md +117 -0
- package/templates/skills/hai-spec-implement/workflow.md +56 -0
- package/templates/skills/hai-spec-review/SKILL.md +57 -0
- package/templates/skills/hai-spec-review/checklist.md +71 -0
- package/templates/skills/hai-storage/SKILL.md +31 -262
- package/templates/skills/hai-storage/reference.md +284 -0
- package/templates/skills/hai-ui/SKILL.md +62 -238
- package/templates/skills/hai-ui/guide.md +81 -0
- package/templates/skills/hai-ui/reference.md +705 -0
- package/templates/skills/hai-ui-design/SKILL.md +31 -0
- package/templates/skills/hai-ui-design/patterns.md +31 -0
- package/templates/skills/hai-ui-review/SKILL.md +32 -0
- package/templates/skills/hai-ui-review/checklist.md +29 -0
- package/templates/skills/hai-vecdb/SKILL.md +25 -267
- package/templates/skills/hai-vecdb/reference.md +325 -0
- package/templates/skills/opencode.json +0 -5
- package/dist/chunk-2H7UOFLK.js +0 -10
- package/dist/chunk-LANIDJC7.js +0 -659
- package/dist/chunk-LANIDJC7.js.map +0 -1
- package/dist/chunk-YV7WPUI6.js +0 -206
- package/dist/chunk-YV7WPUI6.js.map +0 -1
- package/dist/config-templates-S5RI2MC6.js +0 -5
- package/dist/config-templates-S5RI2MC6.js.map +0 -1
- package/dist/skill-templates-N5DU5FNX.js +0 -5
- package/dist/skill-templates-N5DU5FNX.js.map +0 -1
- package/dist/src-XJ6YXNAF.js +0 -15030
- package/dist/src-XJ6YXNAF.js.map +0 -1
- package/templates/apps/android-app/.env.hbs +0 -3
- package/templates/apps/android-app/messages/en-US.json +0 -24
- package/templates/apps/android-app/messages/zh-CN.json +0 -24
- package/templates/apps/android-app/src/lib/api.ts.hbs +0 -30
- package/templates/apps/android-app/src/routes/+layout.svelte.hbs +0 -42
- package/templates/apps/android-app/src/routes/+layout.ts +0 -7
- package/templates/apps/android-app/src/routes/+page.svelte.hbs +0 -27
- package/templates/apps/api/src/routes/+layout.svelte +0 -14
- package/templates/apps/api/src/routes/+page.svelte +0 -11
- package/templates/apps/api/src/routes/api/v1/health/+server.ts +0 -14
- package/templates/apps/api/src/routes/api/v1/items/+server.ts +0 -37
- package/templates/apps/api/src/routes/api/v1/items/[id]/+server.ts +0 -30
- package/templates/base/src/app.css +0 -2
- package/templates/base/tsconfig.json +0 -8
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
# hai-app-create — 详细用法
|
|
2
|
+
|
|
3
|
+
从 [SKILL.md](SKILL.md) 选择主题后读取对应小节。代码片段展示 API 用法;省略的业务变量、schema、依赖与 return 上下文需由应用补齐。
|
|
4
|
+
|
|
5
|
+
新增、修改和修复功能前先读 [development.md](development.md),确认适用框架能力、当前安装版本与安全边界。这里的路由/页面示例适用于 SvelteKit;API workspace 围绕已有 contract/service 扩展,fullstack 使用现有 contract/serv/shared 和所选前端,不套用 SvelteKit 目录。
|
|
6
|
+
|
|
7
|
+
## 适用场景
|
|
8
|
+
|
|
9
|
+
- 新增页面(路由)
|
|
10
|
+
- 新增 API 端点
|
|
11
|
+
- 新增服务层模块(`$lib/server/services/`)
|
|
12
|
+
- 新增数据库表 / 数据模型
|
|
13
|
+
- 新增业务组件
|
|
14
|
+
- 修改或修复已有功能、接口和交互
|
|
15
|
+
|
|
16
|
+
## 行为开发与验证
|
|
17
|
+
|
|
18
|
+
新增/改变行为时采用下列流程;纯文案、格式或文档变化按影响验证,不为流程补无意义测试。
|
|
19
|
+
|
|
20
|
+
### Step 1:需求分析与测试设计
|
|
21
|
+
|
|
22
|
+
1. 明确功能的输入、输出、边界条件、错误场景
|
|
23
|
+
2. 按 development.md 匹配现有应用实现、框架模块及其 feature/配置;查公开类型与安装版本,再确定修改文件(服务、路由、Schema、组件等)
|
|
24
|
+
3. 设计正常、错误和适用安全边界的可观察验收(参照 `hai-app-tests`);已有行为优先扩展现有用例
|
|
25
|
+
|
|
26
|
+
### Step 2:编写测试(Red 阶段)
|
|
27
|
+
|
|
28
|
+
1. **编写目标用例**:按当前项目测试结构为改变的服务行为、Schema、接口或交互选择单元/集成/E2E 测试,不要求每次创建两套测试
|
|
29
|
+
2. **保留既有回归**:新增目标用例不得依赖破坏现有实现才能失败
|
|
30
|
+
3. 新文件可先提供最小签名,但不能为制造 Red 把现有功能替换成空实现
|
|
31
|
+
4. **运行测试确认新增目标用例因预期行为缺失而失败(既有回归保持通过)**:
|
|
32
|
+
```bash
|
|
33
|
+
pnpm --filter <app-name> test # 新增目标用例应 FAIL,既有回归应 PASS
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Step 3:编写实现(Green 阶段)
|
|
37
|
+
|
|
38
|
+
按照下文的「创建指南」编写实际功能代码,每完成一个功能点立即运行测试确认通过。
|
|
39
|
+
|
|
40
|
+
### Step 4:重构与验证(Refactor 阶段)
|
|
41
|
+
|
|
42
|
+
1. 参照 `hai-app-review` 审查代码规范
|
|
43
|
+
2. 按 [分轮验证与集中修复](../hai-app-tests/validation.md) 收集适用门禁,普通失败不中断独立检查,汇总后集中修复、再验证;优先 workspace filter,PowerShell 使用 `pnpm.cmd`
|
|
44
|
+
3. UI/路由/端到端改动执行相应 E2E;报告失败路径与安全验收结果,未运行的边界说明原因
|
|
45
|
+
|
|
46
|
+
## 目录结构约定
|
|
47
|
+
|
|
48
|
+
以下为 SvelteKit 示例;其它架构沿当前项目目录,不生成这些文件。
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
src/
|
|
52
|
+
hooks.server.ts # `handle` hook 入口
|
|
53
|
+
app.css # 全局样式(TailwindCSS 4)
|
|
54
|
+
lib/
|
|
55
|
+
server/
|
|
56
|
+
init.ts # 应用初始化(模块 init 顺序)
|
|
57
|
+
services/ # 业务服务层(Server-only)
|
|
58
|
+
index.ts # 服务聚合导出
|
|
59
|
+
user.ts # 示例:用户服务
|
|
60
|
+
schemas/ # 请求校验 Schema(Zod)
|
|
61
|
+
components/ # 业务组件(非 @h-ai/ui 通用组件)
|
|
62
|
+
stores/ # 客户端 Store(Svelte 5 Runes)
|
|
63
|
+
paraglide/ # i18n 生成文件(禁止手动修改)
|
|
64
|
+
routes/
|
|
65
|
+
+layout.svelte # 根布局
|
|
66
|
+
+page.svelte # 首页
|
|
67
|
+
(auth)/ # 认证分组路由
|
|
68
|
+
login/+page.svelte
|
|
69
|
+
admin/ # 管理区域
|
|
70
|
+
users/
|
|
71
|
+
+page.svelte # 列表页
|
|
72
|
+
+page.server.ts # 列表数据加载
|
|
73
|
+
[id]/
|
|
74
|
+
+page.svelte # 详情页
|
|
75
|
+
+page.server.ts
|
|
76
|
+
api/ # API 端点
|
|
77
|
+
auth/+server.ts
|
|
78
|
+
health/+server.ts
|
|
79
|
+
iam/
|
|
80
|
+
users/+server.ts
|
|
81
|
+
messages/ # i18n 消息文件
|
|
82
|
+
en-US.json
|
|
83
|
+
ja-JP.json
|
|
84
|
+
zh-CN.json
|
|
85
|
+
config/ # 模块配置文件
|
|
86
|
+
_core.yml
|
|
87
|
+
_db.yml
|
|
88
|
+
_cache.yml
|
|
89
|
+
_iam.yml
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## 创建页面
|
|
93
|
+
|
|
94
|
+
### 页面路由规则
|
|
95
|
+
|
|
96
|
+
使用 SvelteKit 文件路由,参考 `src/routes/` 约定:
|
|
97
|
+
|
|
98
|
+
| 类型 | 路径示例 | 说明 |
|
|
99
|
+
| -------- | ---------------------------------- | -------------------- |
|
|
100
|
+
| 静态页面 | `routes/about/+page.svelte` | 常规页面 |
|
|
101
|
+
| 动态路由 | `routes/users/[id]/+page.svelte` | URL 参数 |
|
|
102
|
+
| 分组路由 | `routes/(auth)/login/+page.svelte` | 共享布局,不影响 URL |
|
|
103
|
+
| API 端点 | `routes/api/users/+server.ts` | RESTful API |
|
|
104
|
+
|
|
105
|
+
### 页面文件模板
|
|
106
|
+
|
|
107
|
+
```svelte
|
|
108
|
+
<!-- +page.svelte -->
|
|
109
|
+
<script lang="ts">
|
|
110
|
+
// Svelte 5 Runes 语法
|
|
111
|
+
let { data } = $props()
|
|
112
|
+
let loading = $state(false)
|
|
113
|
+
|
|
114
|
+
async function handleAction() {
|
|
115
|
+
loading = true
|
|
116
|
+
try {
|
|
117
|
+
// 业务逻辑
|
|
118
|
+
} finally {
|
|
119
|
+
loading = false
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
</script>
|
|
123
|
+
|
|
124
|
+
<div class="container mx-auto p-4">
|
|
125
|
+
<!-- 使用 @h-ai/ui 组件 -->
|
|
126
|
+
</div>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 数据加载(+page.server.ts)
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
import type { PageServerLoad } from './$types'
|
|
133
|
+
import { error, redirect } from '@sveltejs/kit'
|
|
134
|
+
|
|
135
|
+
// someService 与 safeLoadErrorMessage 由应用已有服务与请求 locale 的 i18n 提供。
|
|
136
|
+
export const load: PageServerLoad = async ({ locals }) => {
|
|
137
|
+
if (!locals.session)
|
|
138
|
+
redirect(303, '/auth/login')
|
|
139
|
+
const result = await someService.list()
|
|
140
|
+
if (!result.success)
|
|
141
|
+
error(503, safeLoadErrorMessage)
|
|
142
|
+
return { items: result.data }
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## 创建 API 端点
|
|
147
|
+
|
|
148
|
+
API workspace/fullstack 读取本工程随模板交付的 `hai-api-contract` 与 `hai-serv` Skills,先检查内置领域 contract 和 feature procedures。应用私有接口通过现有 contract → procedure → typed client 扩展,serv route 使用 auth/permission/role,资源归属在服务层检查,不添加 `+server.ts` 或 kit.validate。
|
|
149
|
+
|
|
150
|
+
同源 SvelteKit 工程读取其 `hai-kit` Skill,沿用文件路由与既有 guard。各架构只读取实际提供的技能。
|
|
151
|
+
|
|
152
|
+
### SvelteKit RESTful 端点模板
|
|
153
|
+
|
|
154
|
+
本例依赖应用提供 `service`;`toHttpError(result.error)` 是应用已有或需实现的错误边界:保留安全错误码、映射 HTTP 状态,对内部失败使用当前 locale 的安全文案且不暴露 SQL/路径/凭据。不能不分类便直接透传内部错误消息。
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
// src/routes/api/[resource]/+server.ts
|
|
158
|
+
import { kit } from '@h-ai/kit'
|
|
159
|
+
import { z } from 'zod'
|
|
160
|
+
|
|
161
|
+
const CreateSchema = z.object({
|
|
162
|
+
name: z.string().min(1).max(100),
|
|
163
|
+
description: z.string().optional(),
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
// GET - 列表
|
|
167
|
+
export const GET = kit.handler(async ({ locals }) => {
|
|
168
|
+
kit.guard.require(locals.session, 'resource:read')
|
|
169
|
+
|
|
170
|
+
const result = await service.list()
|
|
171
|
+
if (!result.success)
|
|
172
|
+
return toHttpError(result.error)
|
|
173
|
+
return kit.response.ok(result.data)
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
// POST - 创建
|
|
177
|
+
export const POST = kit.handler(async ({ request, locals }) => {
|
|
178
|
+
kit.guard.require(locals.session, 'resource:create')
|
|
179
|
+
|
|
180
|
+
const data = await kit.validate.body(request, CreateSchema)
|
|
181
|
+
|
|
182
|
+
const result = await service.create(data)
|
|
183
|
+
if (!result.success)
|
|
184
|
+
return toHttpError(result.error)
|
|
185
|
+
return kit.response.created(result.data)
|
|
186
|
+
})
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### 要点
|
|
190
|
+
|
|
191
|
+
- 使用 kit.guard.require / kit.validate.body 的 SvelteKit 端点用 `kit.handler(async ({ locals, request, ... }) => { ... })` 包裹,由 handler 统一处理 throw 的 Response;其它架构用对应运行时
|
|
192
|
+
- API 权限守卫使用 `kit.guard.require(locals.session, 'xxx:yyy')`,未登录/无权限抛出 401/403 Response,由 `kit.handler` 处理,**无需**检查返回值。页面 load 使用 `kit.guard.check` 并调用 SvelteKit `error`,查询 Schema 用 safeParse 后抛原生页面错误;不能直接抛 API Response 导致页面 500。
|
|
193
|
+
- 输入校验使用 `await kit.validate.body(request, Schema)`,校验失败时 throw 400 Response,**无需**手动判断 valid
|
|
194
|
+
- 返回统一使用 `kit.response.*`
|
|
195
|
+
- 服务层保留上游 HaiResult 错误;本例 SvelteKit HTTP 边界按安全消息和状态转换,不能把数据库失败作为 400 或空列表成功。serv/oRPC 普通 procedure 按真实 HaiResult 包络契约验收,不照搬本例状态映射
|
|
196
|
+
- HaiResult 型业务操作先检查 result.success;流和显式抛错 API 按各自契约处理
|
|
197
|
+
|
|
198
|
+
## 创建服务层
|
|
199
|
+
|
|
200
|
+
服务层位于 `$lib/server/services/`,处理业务逻辑。
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
import type { HaiResult, PaginatedResult } from '@h-ai/core'
|
|
204
|
+
import { core, ok } from '@h-ai/core'
|
|
205
|
+
import { reldb } from '@h-ai/reldb'
|
|
206
|
+
|
|
207
|
+
// Article/CreateArticleInput/ListParams 为应用类型;已完成建表。
|
|
208
|
+
const articles = reldb.crud.table<Article>({
|
|
209
|
+
table: 'articles',
|
|
210
|
+
idColumn: 'id',
|
|
211
|
+
dbType: 'sqlite', // 与本例初始化后端一致;切换数据库时同步修改
|
|
212
|
+
select: ['id', 'title', 'created_at AS createdAt'],
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
export async function createArticle(input: CreateArticleInput): Promise<HaiResult<Article>> {
|
|
216
|
+
const article = { ...input, id: core.id.generate(), createdAt: new Date().toISOString() }
|
|
217
|
+
// DB 列映射由应用定义;create 返回 ExecuteResult,不是 Article。
|
|
218
|
+
const result = await articles.create({ id: article.id, title: article.title, created_at: article.createdAt })
|
|
219
|
+
if (!result.success) return result
|
|
220
|
+
return ok(article)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export async function listArticles(params: ListParams): Promise<HaiResult<PaginatedResult<Article>>> {
|
|
224
|
+
return articles.findPage({ pagination: params })
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### 服务层规则
|
|
229
|
+
|
|
230
|
+
- 应用领域操作沿现有契约返回 `HaiResult<T>`;纯 getter、工具、工厂与流按实际签名,不统一改造
|
|
231
|
+
- 写操作需 `debug`(进入)+ `info`(成功)日志
|
|
232
|
+
- 读操作仅 `debug` 日志
|
|
233
|
+
- 禁止 `console.log`,使用 `core.logger`
|
|
234
|
+
- 服务层不处理 HTTP 响应格式,只返回 HaiResult
|
|
235
|
+
|
|
236
|
+
## 创建数据模型
|
|
237
|
+
|
|
238
|
+
### Schema 定义(SQL DDL)
|
|
239
|
+
|
|
240
|
+
沿用当前应用的迁移/建表入口;仅开发初始化用的简单 SvelteKit 示例可在 `$lib/server/init.ts` 建表。不要把本例 SQLite DDL 无修改复制到 PostgreSQL/MySQL,迁移与索引需匹配实际数据库。
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
const BUSINESS_SCHEMA = `
|
|
244
|
+
CREATE TABLE IF NOT EXISTS articles (
|
|
245
|
+
id TEXT PRIMARY KEY,
|
|
246
|
+
title TEXT NOT NULL,
|
|
247
|
+
content TEXT,
|
|
248
|
+
author_id TEXT NOT NULL,
|
|
249
|
+
status TEXT DEFAULT 'draft',
|
|
250
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
251
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
CREATE INDEX IF NOT EXISTS idx_articles_author_id ON articles(author_id);
|
|
255
|
+
CREATE INDEX IF NOT EXISTS idx_articles_status ON articles(status);
|
|
256
|
+
`
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### 类型定义
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
// 在服务文件或独立类型文件中定义
|
|
263
|
+
interface Article {
|
|
264
|
+
id: string
|
|
265
|
+
title: string
|
|
266
|
+
content: string | null
|
|
267
|
+
authorId: string
|
|
268
|
+
status: 'draft' | 'published' | 'archived'
|
|
269
|
+
createdAt: string
|
|
270
|
+
updatedAt: string
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
interface CreateArticleInput {
|
|
274
|
+
title: string
|
|
275
|
+
content?: string
|
|
276
|
+
authorId: string
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## 创建业务组件
|
|
281
|
+
|
|
282
|
+
业务组件放在 `$lib/components/`,通用 UI 使用 `@h-ai/ui`。
|
|
283
|
+
|
|
284
|
+
```svelte
|
|
285
|
+
<!-- src/lib/components/ArticleCard.svelte -->
|
|
286
|
+
<script lang="ts">
|
|
287
|
+
import type { Article } from '$lib/types/article'
|
|
288
|
+
import * as m from '$lib/paraglide/messages.js'
|
|
289
|
+
|
|
290
|
+
let { article, onEdit }: { article: Article, onEdit?: () => void } = $props()
|
|
291
|
+
</script>
|
|
292
|
+
|
|
293
|
+
<div class="card bg-base-100 shadow">
|
|
294
|
+
<div class="card-body">
|
|
295
|
+
<h2 class="card-title">{article.title}</h2>
|
|
296
|
+
<p>{article.content ?? ''}</p>
|
|
297
|
+
{#if onEdit}
|
|
298
|
+
<div class="card-actions justify-end">
|
|
299
|
+
<button class="btn btn-primary" onclick={onEdit}>{m.article_edit()}</button>
|
|
300
|
+
</div>
|
|
301
|
+
{/if}
|
|
302
|
+
</div>
|
|
303
|
+
</div>
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
`Article` 放在客户端可用的共享类型位置,`article_edit` 在中英日文 messages 中新增后由项目生成;实际已安装 `@h-ai/ui` 有适用 Card/Button 时使用其公开组件和 Props,本例只展示业务 props、事件与文案边界。
|
|
307
|
+
|
|
308
|
+
### 组件规则
|
|
309
|
+
|
|
310
|
+
- 使用 Svelte 5 Runes 语法(`$props()`、`$state()`、`$derived()`、`$effect()`)
|
|
311
|
+
- 事件回调通过 props 传入(非 `createEventDispatcher`)
|
|
312
|
+
- 样式使用 TailwindCSS 4 + DaisyUI 5 class
|
|
313
|
+
- 通用 UI 组件优先使用 `@h-ai/ui`,不重复实现
|
|
314
|
+
- i18n 文本使用 `$lib/paraglide/messages.js` 中的 key
|
|
315
|
+
|
|
316
|
+
## 初始化顺序
|
|
317
|
+
|
|
318
|
+
CLI 项目统一忽略 `**/data/`,含根目录、workspace 子目录及 `.gitkeep`;数据库/上传文件不入 Git。Fullstack 的服务端 config 始终保留 core、serv、db、cache、iam、storage、audit、reach、ai、vecdb、payment、scheduler、feedback 共 13 份 YAML;构建部署配置统一位于项目根 hai.json,未启用模块整份注释,可选字段及替代 Provider 按块注释,`.env.example` 也保留未启用模块的注释凭据。
|
|
319
|
+
|
|
320
|
+
H5 所有页面继承根布局的 header/footer;认证页隐藏底部导航,业务页面使用 `@h-ai/ui` 的 `BottomNav` 与移动端壳样式,导航启用 centered/maxWidth/safeArea,与页面同宽。
|
|
321
|
+
|
|
322
|
+
扩展这些配置前先核对当前安装版本及模块公开 Schema。在服务端 workspace 安装需要的依赖,在 `src/server/runtime.ts` 按依赖顺序校验/初始化、失败清理并反序关闭,再接入 contract/procedure。整份注释文件先去掉一层外层注释,可选块只开启需要的字段;切换 Provider 时替换旧连接块并保持名称唯一。配置文件存在不代表模块已启用。crypto.init() 无配置参数,datapipe 无生命周期,不增加虚构的 YAML。
|
|
323
|
+
|
|
324
|
+
环境变量叶子覆盖只遍历 YAML 已有路径,注释键须先取消注释,或用 HAI_DB/HAI_CACHE 等整体对象覆盖。camelCase 不拆词,例如 connectTimeout → HAI_CACHE_CONNECTTIMEOUT;密钥仅写入被忽略的环境文件或部署环境。语言列表在前端/shared 的 project.inlang/settings.json 中同步,core 只配置 defaultLocale。
|
|
325
|
+
|
|
326
|
+
Fullstack 的公共 `.env` 启用当前模块的运行参数,YAML 显式引用同名变量并保留本地回退;未启用模块与可选字段保留注释。环境文件的用途、加载优先级及私有值保存方式遵守 [环境配置规范](development.md#环境配置),模块仍按公开 Schema 校验。
|
|
327
|
+
|
|
328
|
+
复用当前应用服务端启动/关闭入口;SvelteKit 通常为 `$lib/server/init.ts`,API/fullstack 使用已有 service/serv 初始化文件。下列是启用 IAM 时的常见依赖关系,不要求无关应用安装这些模块:
|
|
329
|
+
|
|
330
|
+
```
|
|
331
|
+
core.init() → crypto.init() → reldb.init() → cache.init() → iam.init() → createBusinessTables()
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
新增生命周期模块时按实际配置/依赖添加初始化、检查结果并反序关闭;关键依赖失败停止启动并清理已创建资源。core 无 close、datapipe 为纯函数、serv/kit/contract 为工厂或适配器,不能虚构 init/close。
|
|
335
|
+
|
|
336
|
+
## 容器交付
|
|
337
|
+
|
|
338
|
+
仅涉及容器构建/部署变更时使用本节;普通功能开发无需每次启动镜像。
|
|
339
|
+
|
|
340
|
+
- 保持脚手架 `images/*.Dockerfile`、`.dockerignore` 与 `package.json` 中 `build` / `compile` 命令与 hai.json 的 build/deploy 配置同步。保留 `.gitattributes`,让 `.dockerignore`、Dockerfile 和 POSIX 脚本统一使用 LF,保持跨平台输入一致并确保 Linux 脚本可运行。
|
|
341
|
+
- Podman 多阶段构建保持 `--format docker --jobs=1`;前者保留 `HEALTHCHECK`,后者避免部分 Podman 5.8/Buildah 组合在并行 stage 构建时触发内部 semaphore panic。
|
|
342
|
+
- 先复制 lockfile、workspace 配置与构建器准备的 `images/dependencies/` 安装输入执行 `pnpm fetch --ignore-scripts`,再复制源码并离线安装、构建;fetch、安装和 `pnpm pm deploy` 共用 pnpm store,安装与生产依赖整理共用 SQLite 驱动缓存,避免重复下载,兼容新增 workspace、本地归档与补丁。
|
|
343
|
+
- 默认容器面向 CPU 运行或远程 AI 服务,Dockerfile 设置 `ONNXRUNTIME_NODE_INSTALL_CUDA=skip`,跳过额外 CUDA/TensorRT 下载;使用宿主机 GPU 时定制镜像和运行参数,不修改本机 npm 或全局 AI/GPU 配置。
|
|
344
|
+
- SvelteKit 服务使用 Node adapter;纯 Vite 前端使用带 SPA fallback 的静态镜像;fullstack 的 Service 与 Web 分别交付,Service 直接监听且不增加转发进程。
|
|
345
|
+
- Web 的 `PUBLIC_*` 部署配置在容器启动时生成静态运行时配置,不作为 build arg 烘焙,确保同一镜像可跨环境部署。
|
|
346
|
+
- 配置文件随镜像提供,并允许只读挂载覆盖;密钥只通过环境变量或 `--env-file` 注入。
|
|
347
|
+
- 普通构建不携带 `data/`;持续写入使用运行期 volume;需要预置数据时显式维护独立 Dockerfile 和明确的 build context,不把本机数据加入默认镜像。
|
|
348
|
+
- 数据库和本地存储的持续写入必须落到 volume,不能依赖镜像可写层。
|
|
349
|
+
- 完成前实际启动镜像,验证健康端点、非 root 用户、环境变量覆盖、配置挂载和预置数据读取。
|
|
350
|
+
|
|
351
|
+
## 检查清单
|
|
352
|
+
|
|
353
|
+
- [ ] 需求已匹配框架现有能力/feature/配置,版本与契约已核验,自定义缺口有依据
|
|
354
|
+
- [ ] 新增/改变行为有意义的目标用例先失败、后通过;既有回归保持通过
|
|
355
|
+
- [ ] 适用安全边界已验证:非法输入、越权/租户隔离、失败结果及相关事务/幂等/清理
|
|
356
|
+
- [ ] 相关 API/页面改动已执行适用集成/E2E 流程
|
|
357
|
+
- [ ] 页面使用 Svelte 5 Runes 语法
|
|
358
|
+
- [ ] API 端点有权限守卫与输入校验
|
|
359
|
+
- [ ] 服务层和调用方遵循实际返回/抛错/流契约,不能以 HTTP 成功替代业务状态成功
|
|
360
|
+
- [ ] 日志级别正确(读 debug / 写 debug+info / 失败 warn|error)
|
|
361
|
+
- [ ] 禁止 `console.log`、`any`、硬编码密钥
|
|
362
|
+
- [ ] 用户可见文本走 i18n
|
|
363
|
+
- [ ] 涉及容器交付时,镜像启动及配置/环境变量/数据目录行为已验证
|
|
364
|
+
- [ ] 新增表有索引定义
|
|
365
|
+
- [ ] 组件优先使用 `@h-ai/ui`
|
|
366
|
+
- [ ] 按当前 scripts 运行适用 typecheck/lint/build/test/E2E 并报告未验证项
|
|
367
|
+
|
|
368
|
+
## 相关 Skills
|
|
369
|
+
|
|
370
|
+
- `hai-build`:项目架构与模块初始化顺序
|
|
371
|
+
- `hai-app-tests`:TDD 测试规范(Red 阶段详细指引)
|
|
372
|
+
- `hai-app-review`:代码审查规范(Refactor 阶段参照)
|
|
373
|
+
- `hai-kit`:SvelteKit 集成的完整 API
|
|
374
|
+
- `hai-ui`:UI 组件库使用
|
|
375
|
+
- `hai-reldb`:数据库操作详细 API
|
|
376
|
+
- `hai-iam`:认证与权限管理
|
|
@@ -1,156 +1,87 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: hai-app-review
|
|
3
|
-
description:
|
|
3
|
+
description: "审查 hai 应用的框架复用、安全边界、返回契约、代码风格与真实交互,支持开发后的自查。"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# hai-app-review
|
|
6
|
+
# hai-app-review
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
## 能力契约
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
- 安全审查(权限、输入校验、密钥管理)
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## 工作准则
|
|
22
|
-
|
|
23
|
-
1. **先搜索再改动**:用全局检索确认引用关系,避免遗漏更新。
|
|
24
|
-
2. **最小变更**:除非测试暴露缺陷,不改业务行为。
|
|
25
|
-
3. **成套更新**:代码 / 测试 / 文档同步。
|
|
26
|
-
4. **重构后测试必须仍通过**:任何重构都不能破坏已有测试。
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
## 审查清单
|
|
31
|
-
|
|
32
|
-
### TDD 合规性
|
|
33
|
-
|
|
34
|
-
- [ ] 每个功能都有对应的单元测试(`tests/` 目录)
|
|
35
|
-
- [ ] 关键流程有对应的 E2E 测试(`e2e/` 目录)
|
|
36
|
-
- [ ] 单元测试覆盖四种路径:正常、边界、权限、错误
|
|
37
|
-
- [ ] E2E 测试覆盖 API 端点的未认证/认证场景
|
|
38
|
-
- [ ] 测试先于实现编写(TDD 流程已遵循)
|
|
39
|
-
- [ ] `pnpm test` 单元测试全部通过
|
|
40
|
-
- [ ] `pnpm test:e2e` E2E 测试全部通过
|
|
41
|
-
|
|
42
|
-
---
|
|
10
|
+
| 项目 | 契约 |
|
|
11
|
+
| --- | --- |
|
|
12
|
+
| 能力 | 审查应用的框架复用、安全、质量、风格与交互 |
|
|
13
|
+
| 适用场景 | 用户要求审查/规范化,或完成功能开发后的自查 |
|
|
14
|
+
| 输入 | 指定范围、需求/验收、代码差异、当前依赖与运行证据 |
|
|
15
|
+
| 输出 | 有路径、影响、依据、验收方法的问题及验证结果 |
|
|
16
|
+
| 限制 | 只读审查不自动改代码;已有实现/修复授权时可修正本次范围内的问题。未读实现不下结论,不把偏好当缺陷。 |
|
|
43
17
|
|
|
44
|
-
##
|
|
18
|
+
## 审查路径
|
|
45
19
|
|
|
46
|
-
|
|
20
|
+
涉及框架结构、配置、核心流程或模块边界的修复,先按 [变更影响与方案确认](../hai-change-plan/SKILL.md) 提案并等待用户决定;普通业务私有实现沿当前授权处理。
|
|
47
21
|
|
|
48
|
-
|
|
49
|
-
- [ ] `+page.server.ts` / `+server.ts` 仅做请求处理(守卫 → 校验 → 调用服务 → 响应)
|
|
50
|
-
- [ ] 业务逻辑集中在 `$lib/server/services/`
|
|
51
|
-
- [ ] 客户端组件不直接调用数据库或服务端模块
|
|
52
|
-
- [ ] 依赖方向:路由 → 服务 → 框架模块,不反向
|
|
22
|
+
发现表达、状态区分与同步检查遵循[沟通与同步维护](../hai-app-create/collaboration.md)。审查范围内核对使用文档、配置示例、截图、测试、模板和调用方是否需要更新。
|
|
53
23
|
|
|
54
|
-
|
|
24
|
+
对代码差异读取 [差异审查](differential.md):固定 base/head,先核对需求符合性,再按真实风险检查历史约束、直接与关键间接调用方。完整应用审查使用同样的需求追踪与发现复核,说明实际覆盖范围。发现、修复和验收沿 [工作交接契约](../hai-spec-implement/handoff.md) 记录。
|
|
55
25
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
26
|
+
1. 读取当前项目入口规则、用户指定需求、package scripts、lockfile 与差异,确认 SvelteKit、API workspace、fullstack 或 Vite/原生架构。业务以当前明确需求为准;模板角色、流程、限额和生成代码是初始实现,不能据此否定新需求或要求恢复已被替代的行为。
|
|
27
|
+
2. 按 [development.md](../hai-app-create/development.md) 对需求核对实际框架能力、当前安装版本及适用安全边界;只读所涉及模块 skill、公开类型和相关调用方。
|
|
28
|
+
3. 沿真实路径检查输入 → 身份/资源权限 → 服务/副作用 → 结果 → UI。先报告能导致安全或行为错误的问题,再检查风格与维护性。
|
|
29
|
+
4. 对已授权修复做最小改动并验证。修正真实缺陷不以“已有测试未发现”为前提;保留用户已有改动与业务目标。区分实现偏离需求的缺陷与待做的模板适配,核对测试及 AGENTS/skills/README 是否仍描述过期默认业务。
|
|
59
30
|
|
|
60
|
-
|
|
61
|
-
// ❌ 重新包装
|
|
62
|
-
const result = await reldb.sql.query(sql)
|
|
63
|
-
if (!result.success) {
|
|
64
|
-
return { success: false, error: { code: 'QUERY_FAILED', message: result.error.message } }
|
|
65
|
-
}
|
|
31
|
+
## 框架复用与架构
|
|
66
32
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
33
|
+
- 本次需求是否已经由应用已有服务、框架 feature/配置/扩展点实现?查实际 API 与版本,不能只计算导入包数量。
|
|
34
|
+
- 登录/刷新、数据库连接/CRUD/事务、缓存、上传、AI provider、任务调度及通用 UI 若已有适用能力,应复用。自定义代码或新依赖应有具体缺口证据,不能为覆盖率安装无关模块。
|
|
35
|
+
- SvelteKit 的 hooks 仅编排初始化/中间件,load/端点守卫 → 校验 → 服务 → 响应;API workspace/fullstack 在现有 contract/procedure/serv 扩展,不生成 kit 路由。
|
|
36
|
+
- UI 负责显示与交互;数据库、密钥与服务端模块留在服务端。浏览器共享类型从客户端可用的 contract/types/shared 引入,不从 server services 引入。
|
|
37
|
+
- 从 `package.json.exports` 公开入口导入;复用真实类型,拒绝内部源码路径、本地仿造类型和无用途转发层。公共 contract/配置变化同步服务、客户端、测试和文档。
|
|
72
38
|
|
|
73
|
-
|
|
39
|
+
## 返回、失败与生命周期
|
|
74
40
|
|
|
75
|
-
-
|
|
76
|
-
-
|
|
77
|
-
-
|
|
78
|
-
-
|
|
41
|
+
- 返回 HaiResult 的调用先检查 `success` 再读 `data`,服务层保留上游错误;纯函数、getter、工厂、流式 API 与显式抛错按实际签名。
|
|
42
|
+
- SvelteKit 控制流及 kit.guard.require/kit.validate.body 抛出的响应按 kit/SvelteKit 契约处理,不吞掉 redirect/error。服务端 SDK/流迭代异常不能因“框架不抛业务异常”而遗漏。
|
|
43
|
+
- HTTP 边界沿实际状态/包络与安全 i18n 契约,不暴露 SQL、路径、凭据和堆栈。serv/oRPC 普通 procedure 的失败 HaiResult 可位于 HTTP 200,error.httpStatus 不等于传输状态;不能照搬 kit 的 Response 断言。不能将依赖失败回退为空列表、零统计或空权限;权限读取失败不得继续写入。
|
|
44
|
+
- 投递、支付、调度等需要继续判断业务状态字段;HTTP/HaiResult 成功不能替代送达、完成或提交。失败反馈保留用户输入,重试明确幂等。
|
|
45
|
+
- 初始化复用当前入口;只对有生命周期的模块按真实依赖顺序 init → use → close,检查每个结果。关键依赖失败停止启动、清理已创建资源;关闭反序释放,覆盖并发初始化与失败路径。
|
|
79
46
|
|
|
80
|
-
|
|
47
|
+
## 安全验收
|
|
81
48
|
|
|
82
|
-
|
|
83
|
-
- [ ] 日志级别正确:
|
|
49
|
+
按 development.md 的安全表选本次适用项,并检查可观察行为:
|
|
84
50
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
| 校验失败 | `warn` |
|
|
91
|
-
| 系统异常 | `error` |
|
|
92
|
-
| 初始化完成 / 关闭 | `info` |
|
|
93
|
-
| 安全操作(登录/登出) | `info`(成功)/ `warn`(失败) |
|
|
51
|
+
- 非法/超限输入被 schema 拒绝且没有写入/外部副作用。SvelteKit 用对应 kit 校验,API service 在 contract/procedure 边界校验,不给其它架构强加 kit.validate。
|
|
52
|
+
- 未登录、缺权限、跨资源/用户/租户访问被拒绝;客户端身份字段不能替代服务端会话。公开接口有明确匿名策略。
|
|
53
|
+
- SQL 值参数化;动态标识符白名单;文件路径/类型/大小与目的地 URL 限制匹配真实入口;不可信 HTML/AI 内容不能执行。
|
|
54
|
+
- 日志、响应、客户端构建产物与公共环境变量无密钥/密码/token。会话沿现有 Cookie/内存或原生安全 TokenStorage;相关 CORS、Cookie、CSRF、刷新与退出路径得到验证。
|
|
55
|
+
- 适用的事务、幂等、并发/重复请求、回调验签、金额与订单绑定、任务重试/取消得到验证。共享业务状态不放单进程 memory。
|
|
94
56
|
|
|
95
|
-
|
|
96
|
-
- [ ] 失败日志附带 `{ error }` 或 `{ reason }`
|
|
57
|
+
typecheck/lint 不能证明越权、租户隔离、事务、错误状态或资源清理正确;需要适用的失败/攻击用例、运行检查或明确未验证说明。
|
|
97
58
|
|
|
98
|
-
|
|
59
|
+
## 代码风格与质量
|
|
99
60
|
|
|
100
|
-
-
|
|
101
|
-
-
|
|
61
|
+
- 禁止 `any`、无说明的 `as unknown as T`、`console.log`、硬编码密钥;外部 `unknown` 先校验/缩窄。必要第三方断言有真实依据。
|
|
62
|
+
- 遵循当前 ESLint、TypeScript、目录与命名规则,函数返回类型按真实契约标注;不把所有返回类型都强制成 HaiResult。
|
|
63
|
+
- 注释中文,结构化日志英文并脱敏。读操作用 debug,写操作成功用 info,失败按业务/系统性质用 warn/error;避免记录整份请求、凭据或未经脱敏的 error/context。
|
|
64
|
+
- 用户可见文案沿现有 i18n 入口,同步中英日文;包括错误、空态、降级、校验和状态文案。禁止手改 Paraglide 生成文件;框架组件内置翻译沿公开 Props 使用。
|
|
65
|
+
- 业务逻辑不塞入 UI/hook;优先 early return、按职责拆分复杂函数。遵守实际 lint 的复杂度/长度限制,不为了数字拆出无意义转发链。
|
|
66
|
+
- 循环串行/并发按依赖、事务、限流与资源限制选择;列表分页/流式处理,避免热路径同步 I/O、重复连接和无界并发。
|
|
102
67
|
|
|
103
|
-
|
|
68
|
+
## 交互与行为验证
|
|
104
69
|
|
|
105
|
-
-
|
|
106
|
-
- [ ] 禁止直接修改 `src/lib/paraglide` 生成文件
|
|
107
|
-
- [ ] `@h-ai/ui` 组件内置翻译,不传入翻译 props
|
|
70
|
+
界面设计与真实交互的详细审查由已交付的 hai-ui-review 提供;应用审查仍负责端到端业务与服务端权限,复用已有发现和证据,避免重复执行相同检查。
|
|
108
71
|
|
|
109
|
-
|
|
72
|
+
涉及 UI 时沿真实用户路径走查,确认适用的:
|
|
110
73
|
|
|
111
|
-
-
|
|
112
|
-
-
|
|
113
|
-
-
|
|
114
|
-
-
|
|
74
|
+
- Svelte 5 Runes、props 事件、SSR/浏览器边界及项目样式系统;优先复用 `@h-ai/ui` 的公开组件。
|
|
75
|
+
- Loading/Empty/Error/Success 四态、表单校验/错误焦点、长任务进度、失败后输入恢复与重试。
|
|
76
|
+
- 桌面/移动布局、长文本与中英日文展开、主题对比、键盘/触摸/IME、焦点与可访问性;危险操作有符合产品目标的确认/撤销。
|
|
77
|
+
- 并发操作、网络失败、权限变化与返回导航不导致假成功、丢失输入或死路。
|
|
115
78
|
|
|
116
|
-
|
|
79
|
+
新增/改变行为有对应的有效单元/集成/E2E 用例;关键接口覆盖正常、失败及适用权限/边界路径。已有代码是否遵循 TDD 不能仅从最终 diff 推断,需当时执行证据;测试数量与机械打勾不代替行为验证。
|
|
117
80
|
|
|
118
|
-
|
|
119
|
-
- [ ] 事件回调通过 props 传入(非 `createEventDispatcher`)
|
|
120
|
-
- [ ] 样式使用 TailwindCSS 4 + DaisyUI 5
|
|
81
|
+
## 门禁与输出
|
|
121
82
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
- [ ] 模块初始化顺序正确:`core → db → cache → iam → ...`
|
|
125
|
-
- [ ] 初始化在 `$lib/server/init.ts` 统一管理
|
|
126
|
-
- [ ] 配置文件路径遵循 `config/_<module>.yml` 约定
|
|
127
|
-
|
|
128
|
-
---
|
|
129
|
-
|
|
130
|
-
## 质量门禁
|
|
131
|
-
|
|
132
|
-
审查完成后按顺序执行:
|
|
133
|
-
|
|
134
|
-
1. `pnpm typecheck`
|
|
135
|
-
2. `pnpm lint`
|
|
136
|
-
3. `pnpm test`(单元测试)
|
|
137
|
-
4. `pnpm --filter <app-name> test:e2e`(E2E 测试)
|
|
138
|
-
|
|
139
|
-
优先使用 `pnpm --filter <app-name>` 指定应用。
|
|
140
|
-
|
|
141
|
-
---
|
|
142
|
-
|
|
143
|
-
## 输出要求
|
|
144
|
-
|
|
145
|
-
- 列出改动文件与原因
|
|
146
|
-
- 说明是否修复了缺陷或仅做规范化
|
|
147
|
-
- 明确测试(单元 + E2E)与 lint 结果
|
|
148
|
-
- 确认重构后所有测试仍然通过
|
|
149
|
-
|
|
150
|
-
---
|
|
83
|
+
从当前 package.json 选择实际 scripts,优先 workspace filter;PowerShell 使用 `pnpm.cmd`。按 [分轮验证与集中修复](../hai-app-tests/validation.md) 先收集全部可执行门禁及日志,再归并根因、集中修复、验证失败及受影响项;普通失败不中断独立检查。浏览器、真实 provider、容器和原生交付各自报告实际结果。
|
|
151
84
|
|
|
152
|
-
|
|
85
|
+
交付说明需求/范围、带路径与影响的发现、已复用能力和必要缺口、已修正项、已执行门禁/行为证据、同步的 contract/调用方/i18n/配置/文档,以及未验证项和原因。只读审查报告问题与验证建议;不能凭审查清单宣称所有测试通过。
|
|
153
86
|
|
|
154
|
-
-
|
|
155
|
-
- `hai-app-create`:TDD 驱动的应用功能创建规范
|
|
156
|
-
- `hai-app-tests`:TDD 测试规范(Red 阶段详细指引)
|
|
87
|
+
相关技能:[hai-app-create](../hai-app-create/SKILL.md)、[hai-app-tests](../hai-app-tests/SKILL.md)、[hai-build](../hai-build/SKILL.md)。
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# 差异审查
|
|
2
|
+
|
|
3
|
+
应用改动自查、PR/提交/分支审查按需读取。本方法借鉴 [Trail of Bits differential-review](https://github.com/trailofbits/skills/tree/main/plugins/differential-review),按实际风险选择审查深度,不以 diff 行数决定安全性。
|
|
4
|
+
|
|
5
|
+
## 1. 固定比较对象
|
|
6
|
+
|
|
7
|
+
PR 使用其实际 base/head SHA,分支使用已确认集成分支与目标分支的 merge-base。记录比较命令和两端 SHA;区分提交间差异、staged、unstaged 和未跟踪文件。审查期间 head 变化时,补审新增差异并重新核验受影响结论,不沿用旧行号声称已审查当前版本。
|
|
8
|
+
|
|
9
|
+
先列 `git diff --name-status --find-renames <base> <head>`、统计和完整 diff,再按需读取文件上下文、公开类型、测试、配置及调用方。不能仅凭截断 diff 做全量结论。无 Git、远程权限不足或缺少 base 时,说明实际可读范围,继续可进行的文件级审查。
|
|
10
|
+
|
|
11
|
+
## 2. 先找可能造成较大后果的变化
|
|
12
|
+
|
|
13
|
+
| 变化 | 必查内容 |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| 登录、鉴权、租户、资源 ID、输入校验 | 谁能调用、能操作谁的数据、校验移除后替代约束是否真实存在 |
|
|
16
|
+
| 支付、上传、外部请求、AI 工具、任务 | 验签、目的地/大小限制、幂等、未知结果、重试/取消和外部副作用 |
|
|
17
|
+
| 状态、事务、迁移、共享缓存 | 并发/跨节点约束、失败回滚、存量数据和兼容调用方 |
|
|
18
|
+
| 公共 API、配置、默认值、导出、模板 | 正反向调用、公开类型、目标平台和生成应用是否同步 |
|
|
19
|
+
| UI 和内容渲染 | 服务端权限、HTML/URL 边界、交互丢失、键盘、焦点和语言;不能自动判为低风险 |
|
|
20
|
+
| CI、依赖、部署脚本 | 按 [hai-ci](../hai-ci/SKILL.md) 核对执行来源、权限、密钥与发布条件 |
|
|
21
|
+
|
|
22
|
+
对高风险符号用 `rg` 查直接调用方及关键间接路径,列出实际依赖范围;动态注册、远端消费者无法确定时说明限制,引用数量不代表完整影响。对删除的校验、锁、事务和失败处理读相关 `git log` / `git blame`,判断是否移除了此前修复的约束。没有替代实现的“只是重构”仍需验证行为。
|
|
23
|
+
|
|
24
|
+
## 3. 两次核对
|
|
25
|
+
|
|
26
|
+
第一次核对需求符合性:逐条检查当前目标验收,区分完整实现、已有满足、未实现和证据不足。第二次沿输入 → 身份/资源 → 服务/副作用 → 结果 → UI 检查正确性与集成。只读当前风险需要的模块资料,普通改动不升级为无关的全面安全审计。
|
|
27
|
+
|
|
28
|
+
把可疑点转为具体场景,例如“普通用户提交其他租户的资源 ID,更新语句未包含租户条件”,再核对上游守卫、服务和数据库约束能否实际阻止它。验证新/改变行为对应的成功与失败用例;缺少测试表示验证缺口,不直接证明漏洞,也不能仅因此提高业务问题严重程度。
|
|
29
|
+
|
|
30
|
+
## 4. 报告与复核
|
|
31
|
+
|
|
32
|
+
采用 [交接契约](../hai-spec-implement/handoff.md) 的发现格式。每条引用当前差异行及必要上下文,说明改动引入还是既有问题、触发条件、具体后果、证据充分程度、最小修正和验证方式。排除不成立的线索,不将已否定建议继续列为风险。
|
|
33
|
+
|
|
34
|
+
结尾记录已覆盖文件/路径、未读或被截断部分、未执行验证和原因、需要交付前解决的事项。无发现只说明本次范围未确认问题,不等同于全系统无缺陷或 CI 已通过。
|