@h-ai/api-contract 1.0.0-beta.19 → 1.0.0-beta.20

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 CHANGED
@@ -4,28 +4,9 @@
4
4
 
5
5
  [Framework home](../../README.en.md) · Related modules: [@h-ai/core](../core/README.en.md)
6
6
 
7
- ## Introduction
8
-
9
7
  Public HTTP API contracts for hai-framework, with oRPC contract + Zod as the single source of truth.
10
8
 
11
- ## Core features
12
-
13
- - `apiContract.iam`, `apiContract.storage`, `apiContract.ai`, `apiContract.payment`: domain contracts.
14
- - `apiContract.create()`: compose enabled domain contracts for an application.
15
- - `apiContract.route()`: define custom HTTP route metadata for reuse in application contracts.
16
- - `apiContract.pathOf()`: read the authoritative business path from a contract procedure for middleware/client reuse.
17
- - `apiContract.haiResultSchema()` / `apiContract.voidResultSchema` / `apiContract.paginatedSchema()`: shared DTO schema factories.
18
- - Shared DTO schemas: every HTTP output is wrapped in `HaiResult<T>`.
19
- - IAM token DTOs support httpOnly cookies: `refreshToken` may be absent from the response body and managed by the server through `Set-Cookie`.
20
- - IAM `auth.currentUser` returns the user profile and the current server session's `roles` / `permissions`; clients need not persist a permission snapshot to restore a session.
21
-
22
- Payment creation inputs and outputs accept WeChat `jsapi`, Alipay `h5`, and Stripe `h5` only; WeChat requires `userId` (openid). App, Native, mini-program, and other combinations fail validation. Alipay returns `{ gateway, fields }` page parameters; creation success does not establish payment. See [Payment](../payment/README.en.md) for client handling.
23
-
24
- User listing accepts `sortBy` (username/email/displayName/enabled/createdAt) and `sortDirection` (asc/desc) for header sorting before pagination.
25
-
26
- ## Getting started
27
-
28
- ### Quick start
9
+ ## Quick Start
29
10
 
30
11
  ```ts
31
12
  import { apiContract } from '@h-ai/api-contract'
@@ -57,6 +38,34 @@ export const appContract = {
57
38
  }
58
39
  ```
59
40
 
41
+ ## Features
42
+
43
+ ### Purpose, inputs and outputs
44
+
45
+ This package declares routes and validation schemas; it sends no requests and has no init/close lifecycle. A returned Schema is a validator. Check safeParse.success when parsing: it is separate from HaiResult.success inside a business response. Serv and clients consume the input/output schemas when the application mounts the routes.
46
+
47
+ | Entry | Use case | Input (`—` means none) | Return value | Call example |
48
+ | ------------------------------ | -------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
49
+ | `apiContract.create` | Compose application routes | `{ iam: apiContract.iam, payment: false }` | `{ iam: IamContract }` | `apiContract.create({ iam: apiContract.iam, payment: false })` |
50
+ | `apiContract.route` | Declare an HTTP endpoint | `{ method: "GET", path: "/status" }` | `ContractProcedureBuilder` | `apiContract.route({ method: "GET", path: "/status" })` |
51
+ | `apiContract.pathOf` | Read the declared business path | `apiContract.iam.auth.login` | `string: "/auth/login"` | `apiContract.pathOf(apiContract.iam.auth.login)` |
52
+ | `apiContract.haiResultSchema` | Validate a success or failure result | `z.string()` | `ZodSchema<HaiResult<string>>` | `apiContract.haiResultSchema(z.string())` |
53
+ | `apiContract.voidResultSchema` | Validate results without business data | `{ success: true, data: undefined }` | `ZodSchema<HaiResult<void>>` | `apiContract.voidResultSchema.safeParse({ success: true, data: undefined })` |
54
+ | `apiContract.paginatedSchema` | Validate a page of items | `z.object({ id: z.string() })` | `ZodSchema<{ items: { id: string }[], total: number, page: number, pageSize: number }>` | `apiContract.paginatedSchema(z.object({ id: z.string() }))` |
55
+ | `apiContract.iam` | Identity routes | `—` | `iam contract router` | `apiContract.create({ iam: apiContract.iam })` |
56
+ | `apiContract.storage` | Storage routes | `—` | `storage contract router` | `apiContract.create({ storage: apiContract.storage })` |
57
+ | `apiContract.ai` | AI routes | `—` | `ai contract router` | `apiContract.create({ ai: apiContract.ai })` |
58
+ | `apiContract.payment` | Payment routes | `—` | `payment contract router` | `apiContract.create({ payment: apiContract.payment })` |
59
+ | `apiContract.feedback` | Feedback routes | `—` | `feedback contract router` | `apiContract.create({ feedback: apiContract.feedback })` |
60
+
61
+ - Shared DTO schemas: every HTTP output is wrapped in `HaiResult<T>`.
62
+ - IAM token DTOs support httpOnly cookies: `refreshToken` may be absent from the response body and managed by the server through `Set-Cookie`.
63
+ - IAM `auth.currentUser` returns the user profile and the current server session's `roles` / `permissions`; clients need not persist a permission snapshot to restore a session.
64
+
65
+ Payment creation inputs and outputs accept WeChat `jsapi`, Alipay `h5`, and Stripe `h5` only; WeChat requires `userId` (openid). App, Native, mini-program, and other combinations fail validation. Alipay returns `{ gateway, fields }` page parameters; creation success does not establish payment. See [Payment](../payment/README.en.md) for client handling.
66
+
67
+ User listing accepts `sortBy` (username/email/displayName/enabled/createdAt) and `sortDirection` (asc/desc) for header sorting before pagination.
68
+
60
69
  ### API contracts
61
70
 
62
71
  For standalone contract declaration builds, this package re-exports the upstream public types `ContractProcedureBuilderWithInputOutput`, `ContractProcedureBuilderWithOutput`, and `Schema`, preserving inference for custom routes. Import explicit types from `@h-ai/api-contract` with `import type`; do not reference internal dependency installation paths.
@@ -110,10 +119,6 @@ Batch deletion via `storage.files.deleteMany` returns `{ deletedKeys, failures:
110
119
 
111
120
  Write each business path directly in its `*-contract.ts` file. Inline output schemas used only once in `.output(...)`; schemas reused within the same contract file may be private constants, but must not be exported from schemas.
112
121
 
113
- ### Configuration
114
-
115
- This package has no runtime configuration and does not read environment variables.
116
-
117
122
  ### Configuration driven authentication
118
123
 
119
124
  Password login submits only `identifier` and `password`; `AuthPanel` maps the `LoginForm` field `username` to `identifier`. Server settings `session.maxAge` / `session.refreshTokenMaxAge` control session lifetimes. The login form has no per-login persistent-session option.
@@ -124,15 +129,11 @@ IAM adds GET /auth/config and POST /auth/login/ldap, /auth/password-reset/reques
124
129
 
125
130
  [完整 IAM 配置 / IAM configuration](../iam/README.en.md)
126
131
 
127
- ### Error handling
128
-
129
- Contracts describe input and output structures only. Procedures express business errors with `HaiResult<T>`, so clients need not catch business exceptions.
130
-
131
- ## Input limits and HTTP capabilities
132
+ ### Input limits and HTTP capabilities
132
133
 
133
134
  Object keys are limited to 1024 UTF-8 bytes and reject absolute paths, backslashes, control characters and dot segments. Each public HTTP batch delete accepts 1–1000 entries. `@h-ai/storage/schemas` exposes the shared browser-safe rules. Presign expiry is an integer from 1 to 604800 seconds (Node default 3600, HTTP default 900). Upload signing accepts only key/contentType/expiresIn; contentLength/maxSize/metadata/checksum are unsupported. Invalid input returns HTTP 400 and the typed client maps it to VALIDATION_FAILED. FileUpload limits guide file selection; applications must validate actual objects on the server. Node streaming/checksum/conditional-write options have no default HTTP endpoints. See the [capability and authorization matrix (Chinese)](../storage/README.md#存储输入约束与跨端能力).
134
135
 
135
- ## Feedback domain contract
136
+ ### Feedback domain contract
136
137
 
137
138
  `FeedbackJob.type` and `FeedbackRetryInput.target` support independent `webhook` jobs. Details expose status, attempts and safe error codes in jobs. Business collectors and callback settings belong to trusted server initialization, not HTTP input. Read text and ZIP/GZIP through existing APIs; see [feedback](../feedback/README.en.md).
138
139
 
@@ -148,17 +149,25 @@ const contract = apiContract.create({ feedback: apiContract.feedback })
148
149
  const path = apiContract.pathOf(contract.feedback.reports.submit)
149
150
  ```
150
151
 
151
- ## Optional interactive challenges
152
+ ### Optional interactive challenges
152
153
 
153
154
  IamCreateCaptchaInputSchema/IamCaptchaChallengeSchema define POST /auth/captcha purposes and public challenges. Interactive inputs accept optional captcha up to4096 characters; public configuration exposes only enabled, defaulting false. Schemas validate structure; IAM enforces expiry, purpose and one-use consumption server-side.
154
155
 
155
156
  See policy, defaults and recovery boundaries in [IAM](../iam/README.en.md).
156
157
 
157
- ## Page exit session policy
158
+ ### Page exit session policy
158
159
 
159
160
  `session.endOnPageHide` defaults to `false`. Hosts call `actions.bindPageExit({ enabled: config.session.endOnPageHide })` and invoke its returned cleanup on unmount; standard admin/H5/fullstack templates already bind it. A non-BFCache `pagehide` (including reload and full document navigation) makes a best effort POST to `/auth/session/close`, revoking the held access and related refresh through the existing CSRF/encrypted transport with `keepalive` and no automatic refresh. This response does not clear cookies/local credentials, avoiding a late old response overwriting a new login. Explicit logout still revokes and clears current credentials normally. Browsers may omit page exit requests; configure server `idleTimeout`/`absoluteTimeout` as appropriate. Immediate revocation on browser close is not guaranteed.
160
161
 
161
- ## Development and testing
162
+ ## Configuration
163
+
164
+ This package has no runtime configuration and does not read environment variables.
165
+
166
+ ## Error Handling
167
+
168
+ Contracts describe input and output structures; procedures express business errors with `HaiResult<T>`. Direct Zod `parse()` calls throw on invalid input. For external input, use `safeParse()` and check its `success`, separately from `HaiResult.success` inside a business response.
169
+
170
+ ## Development
162
171
 
163
172
  ```bash
164
173
  pnpm --filter @h-ai/api-contract test
package/README.ja.md CHANGED
@@ -4,28 +4,9 @@
4
4
 
5
5
  [フレームワークのホーム](../../README.ja.md) · 関連モジュール:[@h-ai/core](../core/README.ja.md)
6
6
 
7
- ## 概要
8
-
9
7
  hai-framework の公開 HTTP API 契約パッケージ。oRPC contract + Zod を唯一の定義元として使用します。
10
8
 
11
- ## 主な機能
12
-
13
- - `apiContract.iam`、`apiContract.storage`、`apiContract.ai`、`apiContract.payment`:ドメイン単位の contract。
14
- - `apiContract.create()`:アプリケーションに必要なドメインの contract を組み合わせる。
15
- - `apiContract.route()`:アプリケーションの contract で再利用する独自 HTTP ルートのメタデータを定義。
16
- - `apiContract.pathOf()`:contract procedure から業務パスを取得し、middleware/client で再利用。
17
- - `apiContract.haiResultSchema()` / `apiContract.voidResultSchema` / `apiContract.paginatedSchema()`:共通 DTO Schema のファクトリー。
18
- - 共通 DTO Schema:すべての HTTP 出力を `HaiResult<T>` でラップ。
19
- - IAM Token DTO は httpOnly cookie に対応。レスポンス本文に `refreshToken` が含まれない場合は、サーバーが `Set-Cookie` で管理します。
20
- - IAM の `auth.currentUser` はユーザー情報と現在のサーバーセッションの `roles` / `permissions` を返します。セッション復元のためにクライアントが権限のスナップショットを永続化する必要はありません。
21
-
22
- 支払い作成の入出力は WeChat `jsapi`・Alipay `h5`・Stripe `h5` のみ受け付け、WeChat は `userId`(openid)が必須です。App・Native・ミニプログラムなどは検証で拒否します。Alipay は `{ gateway, fields }` のページパラメーターを返し、作成成功は支払い完了を意味しません。クライアント処理は [Payment](../payment/README.ja.md) を参照してください。
23
-
24
- ユーザー一覧は `sortBy`(username/email/displayName/enabled/createdAt)と `sortDirection`(asc/desc)でページ分割前に並べ替えます。
25
-
26
- ## 使い始める
27
-
28
- ### クイックスタート
9
+ ## クイックスタート
29
10
 
30
11
  ```ts
31
12
  import { apiContract } from '@h-ai/api-contract'
@@ -57,6 +38,34 @@ export const appContract = {
57
38
  }
58
39
  ```
59
40
 
41
+ ## 機能
42
+
43
+ ### 用途・入力・出力
44
+
45
+ このパッケージはルートと検証構造を定義し、通信や init/close は行いません。戻り値の Schema は検証器です。safeParse の success と、業務応答内の HaiResult.success は別の結果なので区別してください。入力・出力 Schema はアプリが Serv やクライアントに組み込む際に使われます。
46
+
47
+ | 入口 | 使用場面 | 入力(`—` は引数なし) | 戻り値 | 呼出例 |
48
+ | ------------------------------ | ------------------------------ | ------------------------------------------ | --------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
49
+ | `apiContract.create` | アプリの契約を組み合わせる | `{ iam: apiContract.iam, payment: false }` | `{ iam: IamContract }` | `apiContract.create({ iam: apiContract.iam, payment: false })` |
50
+ | `apiContract.route` | HTTP エンドポイントを定義する | `{ method: "GET", path: "/status" }` | `ContractProcedureBuilder` | `apiContract.route({ method: "GET", path: "/status" })` |
51
+ | `apiContract.pathOf` | 定義したパスを取得する | `apiContract.iam.auth.login` | `string: "/auth/login"` | `apiContract.pathOf(apiContract.iam.auth.login)` |
52
+ | `apiContract.haiResultSchema` | 成功・失敗の結果を検証する | `z.string()` | `ZodSchema<HaiResult<string>>` | `apiContract.haiResultSchema(z.string())` |
53
+ | `apiContract.voidResultSchema` | データを返さない結果を検証する | `{ success: true, data: undefined }` | `ZodSchema<HaiResult<void>>` | `apiContract.voidResultSchema.safeParse({ success: true, data: undefined })` |
54
+ | `apiContract.paginatedSchema` | ページ付き一覧を検証する | `z.object({ id: z.string() })` | `ZodSchema<{ items: { id: string }[], total: number, page: number, pageSize: number }>` | `apiContract.paginatedSchema(z.object({ id: z.string() }))` |
55
+ | `apiContract.iam` | 認証・アカウントの契約 | `—` | `iam contract router` | `apiContract.create({ iam: apiContract.iam })` |
56
+ | `apiContract.storage` | ファイルの契約 | `—` | `storage contract router` | `apiContract.create({ storage: apiContract.storage })` |
57
+ | `apiContract.ai` | AI の契約 | `—` | `ai contract router` | `apiContract.create({ ai: apiContract.ai })` |
58
+ | `apiContract.payment` | 決済の契約 | `—` | `payment contract router` | `apiContract.create({ payment: apiContract.payment })` |
59
+ | `apiContract.feedback` | フィードバックの契約 | `—` | `feedback contract router` | `apiContract.create({ feedback: apiContract.feedback })` |
60
+
61
+ - 共通 DTO Schema:すべての HTTP 出力を `HaiResult<T>` でラップ。
62
+ - IAM Token DTO は httpOnly cookie に対応。レスポンス本文に `refreshToken` が含まれない場合は、サーバーが `Set-Cookie` で管理します。
63
+ - IAM の `auth.currentUser` はユーザー情報と現在のサーバーセッションの `roles` / `permissions` を返します。セッション復元のためにクライアントが権限のスナップショットを永続化する必要はありません。
64
+
65
+ 支払い作成の入出力は WeChat `jsapi`・Alipay `h5`・Stripe `h5` のみ受け付け、WeChat は `userId`(openid)が必須です。App・Native・ミニプログラムなどは検証で拒否します。Alipay は `{ gateway, fields }` のページパラメーターを返し、作成成功は支払い完了を意味しません。クライアント処理は [Payment](../payment/README.ja.md) を参照してください。
66
+
67
+ ユーザー一覧は `sortBy`(username/email/displayName/enabled/createdAt)と `sortDirection`(asc/desc)でページ分割前に並べ替えます。
68
+
60
69
  ### API 契約
61
70
 
62
71
  独立した contract パッケージの宣言ファイルを生成するため、上流の公開型 `ContractProcedureBuilderWithInputOutput`、`ContractProcedureBuilderWithOutput`、`Schema` を本パッケージから再エクスポートしています。独自ルートの入出力の型推論を維持し、明示的な型が必要な場合は `@h-ai/api-contract` から `import type` で取得してください。依存パッケージの内部インストールパスは参照しないでください。
@@ -110,10 +119,6 @@ const app = serv.createApp({
110
119
 
111
120
  業務 path は対応する `*-contract.ts` に直接記述します。一度しか使わない出力 Schema は `.output(...)` にインラインで定義します。同じ contract ファイル内で再利用する場合は非公開の定数にできますが、schemas からエクスポートしてはいけません。
112
121
 
113
- ### 設定
114
-
115
- このパッケージには実行時設定がなく、環境変数も読み込みません。
116
-
117
122
  ### 設定による認証画面
118
123
 
119
124
  パスワードログインの送信項目は `identifier` と `password` のみです。`AuthPanel` は `LoginForm` の `username` を `identifier` に変換します。有効期間はサーバーの `session.maxAge` / `session.refreshTokenMaxAge` で設定し、フォームにログインごとの永続セッション選択肢はありません。
@@ -124,15 +129,11 @@ IAM に公開設定、LDAP、復旧要求と確定の標準 route を追加し
124
129
 
125
130
  [完整 IAM 配置 / IAM configuration](../iam/README.ja.md)
126
131
 
127
- ### エラー処理
128
-
129
- Contract は入出力構造のみを定義します。業務エラーは procedure が返す `HaiResult<T>` で表し、クライアント側で業務例外を捕捉する必要はありません。
130
-
131
- ## 入力制約と HTTP 機能
132
+ ### 入力制約と HTTP 機能
132
133
 
133
134
  キーは UTF-8 で最大 1024 バイトで、絶対パス、バックスラッシュ、制御文字、ドットセグメントを拒否します。公開 HTTP 一括削除は一度に 1–1000 件です。共通規則はブラウザー対応の `@h-ai/storage/schemas` から参照できます。署名有効期限は整数 1–604800 秒(Node 既定 3600、HTTP 既定 900)。アップロード署名の入力は key/contentType/expiresIn のみで、contentLength/maxSize/metadata/checksum は未対応です。不正入力は HTTP 400、typed client では VALIDATION_FAILED です。FileUpload の制限は選択時の補助であり、実際のオブジェクトはサーバーで検証してください。Node のストリーム/checksum/条件付き書き込みには既定の HTTP エンドポイントがありません。[機能と認可の対応表(中国語)](../storage/README.md#存储输入约束与跨端能力)を参照してください。
134
135
 
135
- ## フィードバック領域の契約
136
+ ### フィードバック領域の契約
136
137
 
137
138
  FeedbackJob.type と FeedbackRetryInput.target は独立した webhook タスクに対応し、詳細 jobs に状態・試行回数・安全なエラーコードを含みます。業務収集関数と宛先は信頼するサーバーで設定し、HTTP 入力では指定できません。本文と ZIP/GZIP は既存 API で取得します。[feedback](../feedback/README.ja.md) を参照してください。
138
139
 
@@ -148,16 +149,24 @@ const contract = apiContract.create({ feedback: apiContract.feedback })
148
149
  const path = apiContract.pathOf(contract.feedback.reports.submit)
149
150
  ```
150
151
 
151
- ## 任意の対話チャレンジ
152
+ ### 任意の対話チャレンジ
152
153
 
153
154
  IamCreateCaptchaInputSchema/IamCaptchaChallengeSchema は POST /auth/captcha の用途と公開チャレンジを定義します。対話入力の captcha は任意で最大4096文字、公開設定は既定 false の enabled のみです。Schema は構造を検証し、期限・用途・単用消費はサーバー IAM が実行します。
154
155
 
155
156
  方針・既定値・復旧範囲は次を参照: [IAM](../iam/README.ja.md)。
156
157
 
157
- ## ページ離脱時のセッション方針
158
+ ### ページ離脱時のセッション方針
158
159
 
159
160
  `session.endOnPageHide` の既定値は `false` です。ホストは `actions.bindPageExit({ enabled: config.session.endOnPageHide })` を呼び、破棄時に戻り値の解除関数を実行します。標準 admin/H5/fullstack テンプレートは接続済みです。BFCache 以外の `pagehide`(再読み込み、文書全体の移動を含む)で POST `/auth/session/close` を最善努力で送信し、保持する access と関連 refresh を失効します。既存の CSRF/暗号化転送を使用し、`keepalive` を付け、自動更新しません。古い応答が新しいログインを上書きしないよう Cookie/ローカル資格情報を消去しません。明示的ログアウトは通常どおり失効と消去を行います。ブラウザーが離脱要求を送らない場合もあるため、業務に応じてサーバーの `idleTimeout`/`absoluteTimeout` を併用してください。閉じた瞬間の失効は保証できません。
160
161
 
162
+ ## 設定
163
+
164
+ このパッケージには実行時設定がなく、環境変数も読み込みません。
165
+
166
+ ## エラー処理
167
+
168
+ Contract は入出力構造を定義し、業務エラーは procedure が返す `HaiResult<T>` で表します。Zod の `parse()` を直接呼ぶと不正な入力で検証例外が発生します。外部入力には `safeParse()` を使い、その `success` と業務応答内の `HaiResult.success` を別々に確認してください。
169
+
161
170
  ## 開発とテスト
162
171
 
163
172
  ```bash
package/README.md CHANGED
@@ -4,28 +4,9 @@
4
4
 
5
5
  [框架首页](../../README.md) · 相关模块:[@h-ai/core](../core/README.md)
6
6
 
7
- ## 简介
8
-
9
7
  hai-framework 的公共 HTTP API 契约包,用 oRPC contract 和 Zod 让前后端共用接口路径、输入输出校验与类型。
10
8
 
11
- ## 核心功能清单
12
-
13
- - `apiContract.iam`、`apiContract.storage`、`apiContract.ai`、`apiContract.payment`:领域级 contract。
14
- - `apiContract.create()`:按应用场景组合启用的领域 contract。
15
- - `apiContract.route()`:定义自定义 HTTP 路由元数据,供应用级 contract 复用。
16
- - `apiContract.pathOf()`:从 contract procedure 读取唯一业务路径,供 middleware/client 复用。
17
- - `apiContract.haiResultSchema()` / `apiContract.voidResultSchema` / `apiContract.paginatedSchema()`:公共 DTO Schema 工厂。
18
- - 公共 DTO Schema:所有 HTTP 输出统一包装为 `HaiResult<T>`。
19
- - IAM token DTO 兼容 httpOnly cookie 模式:响应体中 `refreshToken` 可能不存在,由服务端 `Set-Cookie` 管理。
20
- - IAM `auth.currentUser` 返回用户资料以及服务端当前会话的 `roles` / `permissions`,客户端恢复会话时无需持久化权限快照。
21
-
22
- 支付创建输入和输出仅接受微信 `jsapi`、支付宝 `h5`、Stripe `h5`;微信输入必填 `userId`(openid)。App、Native、小程序与其它组合会在输入校验时失败。支付宝输出是 `{ gateway, fields }` 页面参数,创建成功不代表支付完成;客户端处理见 [Payment](../payment/README.md)。
23
-
24
- 用户列表支持 `sortBy`(username/email/displayName/enabled/createdAt)和 `sortDirection`(asc/desc),供列头排序在分页前执行。
25
-
26
- ## 使用入门
27
-
28
- ### 快速开始
9
+ ## 快速开始
29
10
 
30
11
  ```ts
31
12
  import { apiContract } from '@h-ai/api-contract'
@@ -57,6 +38,34 @@ export const appContract = {
57
38
  }
58
39
  ```
59
40
 
41
+ ## 功能
42
+
43
+ ### 用途、输入与输出
44
+
45
+ 本包声明接口和校验结构,不发送请求,也没有 init/close。表中 Schema 是校验器本身;调用 safeParse 后检查其 success。业务响应中的 HaiResult.success 与校验器的 success 属于不同层,不能混用。路由的输入/输出 Schema 由应用挂载到 Serv 或客户端后实际使用。
46
+
47
+ | 入口 | 使用场景 | 输入(`—` 表示无参数) | 返回值 | 调用示例 |
48
+ | ------------------------------ | -------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
49
+ | `apiContract.create` | 组合应用接口 | `{ iam: apiContract.iam, payment: false }` | `{ iam: IamContract }` | `apiContract.create({ iam: apiContract.iam, payment: false })` |
50
+ | `apiContract.route` | 声明 HTTP 接口 | `{ method: "GET", path: "/status" }` | `ContractProcedureBuilder` | `apiContract.route({ method: "GET", path: "/status" })` |
51
+ | `apiContract.pathOf` | 取唯一业务路径 | `apiContract.iam.auth.login` | `string: "/auth/login"` | `apiContract.pathOf(apiContract.iam.auth.login)` |
52
+ | `apiContract.haiResultSchema` | 校验成功或失败结果 | `z.string()` | `ZodSchema<HaiResult<string>>` | `apiContract.haiResultSchema(z.string())` |
53
+ | `apiContract.voidResultSchema` | 校验无业务数据的结果 | `{ success: true, data: undefined }` | `ZodSchema<HaiResult<void>>` | `apiContract.voidResultSchema.safeParse({ success: true, data: undefined })` |
54
+ | `apiContract.paginatedSchema` | 校验分页列表 | `z.object({ id: z.string() })` | `ZodSchema<{ items: { id: string }[], total: number, page: number, pageSize: number }>` | `apiContract.paginatedSchema(z.object({ id: z.string() }))` |
55
+ | `apiContract.iam` | 认证与账号接口 | `—` | `iam contract router` | `apiContract.create({ iam: apiContract.iam })` |
56
+ | `apiContract.storage` | 文件接口 | `—` | `storage contract router` | `apiContract.create({ storage: apiContract.storage })` |
57
+ | `apiContract.ai` | AI 接口 | `—` | `ai contract router` | `apiContract.create({ ai: apiContract.ai })` |
58
+ | `apiContract.payment` | 支付接口 | `—` | `payment contract router` | `apiContract.create({ payment: apiContract.payment })` |
59
+ | `apiContract.feedback` | 反馈接口 | `—` | `feedback contract router` | `apiContract.create({ feedback: apiContract.feedback })` |
60
+
61
+ - 公共 DTO Schema:所有 HTTP 输出统一包装为 `HaiResult<T>`。
62
+ - IAM token DTO 兼容 httpOnly cookie 模式:响应体中 `refreshToken` 可能不存在,由服务端 `Set-Cookie` 管理。
63
+ - IAM `auth.currentUser` 返回用户资料以及服务端当前会话的 `roles` / `permissions`,客户端恢复会话时无需持久化权限快照。
64
+
65
+ 支付创建输入和输出仅接受微信 `jsapi`、支付宝 `h5`、Stripe `h5`;微信输入必填 `userId`(openid)。App、Native、小程序与其它组合会在输入校验时失败。支付宝输出是 `{ gateway, fields }` 页面参数,创建成功不代表支付完成;客户端处理见 [Payment](../payment/README.md)。
66
+
67
+ 用户列表支持 `sortBy`(username/email/displayName/enabled/createdAt)和 `sortDirection`(asc/desc),供列头排序在分页前执行。
68
+
60
69
  ### API 契约
61
70
 
62
71
  独立 contract 包构建声明文件时,`ContractProcedureBuilderWithInputOutput`、`ContractProcedureBuilderWithOutput` 和 `Schema` 由本包按上游真实类型公开转出,保持自定义路由的输入输出推导。需要显式类型时从 `@h-ai/api-contract` 使用 `import type`,不要引用依赖的内部安装路径。
@@ -110,10 +119,6 @@ const app = serv.createApp({
110
119
 
111
120
  业务 path 必须直接写在对应 `*-contract.ts`。只使用一次的输出 Schema 直接内联到 `.output(...)`;同一 contract 文件内重复使用时可保留私有常量,但不得从 schemas 导出。
112
121
 
113
- ### 配置
114
-
115
- 本包无运行时配置,不读取环境变量。
116
-
117
122
  ### 配置驱动认证页面
118
123
 
119
124
  密码登录只提交 `identifier` 和 `password`;`AuthPanel` 将 `LoginForm` 的 `username` 映射为 `identifier`。会话有效期由服务端 `session.maxAge` / `session.refreshTokenMaxAge` 配置决定,登录表单不提供按次登录的持久会话选项。
@@ -124,15 +129,11 @@ const app = serv.createApp({
124
129
 
125
130
  [完整 IAM 配置 / IAM configuration](../iam/README.md)
126
131
 
127
- ### 错误处理
128
-
129
- Contract 只描述输入输出结构。业务错误由 procedure 返回 `HaiResult<T>` 表达,客户端不需要捕获业务异常。
130
-
131
- ## 输入约束与 HTTP 能力
132
+ ### 输入约束与 HTTP 能力
132
133
 
133
134
  存储 key 按 UTF-8 最多 1024 字节,并拒绝绝对路径、反斜线、控制字符及点路径段;公开 HTTP 批量删除每次 1–1000 项。`@h-ai/storage/schemas` 提供浏览器安全的共同规则。预签名有效期为整数 1–604800 秒(Node 默认 3600,HTTP 默认 900);HTTP 上传仅接受 key/contentType/expiresIn,不支持 contentLength/maxSize/metadata/checksum。无效输入返回 HTTP 400,typed client 映射 VALIDATION_FAILED。FileUpload 的大小/类型限制仅为前端体验,实际对象须由应用服务端复核。Node 流式读写/checksum/条件写等没有默认 HTTP 端点。完整映射与授权边界见 [存储 API 能力](../storage/README.md#存储输入约束与跨端能力)。
134
135
 
135
- ## 反馈领域契约
136
+ ### 反馈领域契约
136
137
 
137
138
  `FeedbackJob.type` 与 `FeedbackRetryInput.target` 支持独立 `webhook` 任务;状态、尝试次数和安全错误码见详情 jobs。业务采集函数与回调配置仅在可信服务端注册,不接受 HTTP 输入指定。正文与 ZIP/GZIP 通过既有证据/附件接口取得,接入见 [feedback](../feedback/README.md)。
138
139
 
@@ -148,16 +149,24 @@ const contract = apiContract.create({ feedback: apiContract.feedback })
148
149
  const path = apiContract.pathOf(contract.feedback.reports.submit)
149
150
  ```
150
151
 
151
- ## 可选交互挑战
152
+ ### 可选交互挑战
152
153
 
153
154
  IamCreateCaptchaInputSchema / IamCaptchaChallengeSchema 定义 POST /auth/captcha 的用途与可公开挑战,交互鉴别输入允许最多4096字符的可选 captcha。IamPublicConfigSchema.captcha 仅含 enabled,缺省关闭。Schema 校验结构,证明有效期、用途和单次消费由服务端 IAM 执行。
154
155
 
155
156
  策略、默认值和恢复边界见 [IAM](../iam/README.md)。
156
157
 
157
- ## 页面离开会话策略
158
+ ### 页面离开会话策略
158
159
 
159
160
  `session.endOnPageHide` 默认 `false`。启用后宿主调用 `actions.bindPageExit({ enabled: config.session.endOnPageHide })` 并在卸载时调用返回的清理函数;标准 admin/H5/fullstack 模板已经接入。非 BFCache 的 `pagehide`(也包括刷新、整页导航)通过 POST `/auth/session/close` 尽力撤销当前 access 及关联 refresh,沿用 CSRF/传输加密,使用 `keepalive` 且不自动刷新会话。该响应不清 Cookie/本地凭据,避免旧响应覆盖下一次登录。显式退出仍使用正常 logout,可靠撤销并清理当前凭据。浏览器可能不发送页面离开请求,因此必须按业务配合服务端 `idleTimeout`/`absoluteTimeout`;不能据此保证关闭即撤销。
160
161
 
162
+ ## 配置
163
+
164
+ 本包无运行时配置,不读取环境变量。
165
+
166
+ ## 错误处理
167
+
168
+ Contract 只描述输入输出结构,业务错误由 procedure 返回 `HaiResult<T>` 表达。直接调用 Zod `parse()` 会在输入无效时抛校验异常;读取外部输入时可用 `safeParse()` 并检查其 `success`。这个校验结果与业务响应里的 `HaiResult.success` 分别处理。
169
+
161
170
  ## 开发测试
162
171
 
163
172
  ```bash
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@h-ai/api-contract",
3
3
  "type": "module",
4
- "version": "1.0.0-beta.19",
4
+ "version": "1.0.0-beta.20",
5
5
  "description": "Hai Framework public API contracts powered by oRPC and Zod.",
6
6
  "license": "Apache-2.0",
7
7
  "exports": {
@@ -43,8 +43,8 @@
43
43
  "node": "^22.23.4 || ^24.22.1 || ^26.12.1"
44
44
  },
45
45
  "dependencies": {
46
- "@h-ai/core": "1.0.0-beta.19",
47
- "@h-ai/storage": "1.0.0-beta.19",
46
+ "@h-ai/core": "1.0.0-beta.20",
47
+ "@h-ai/storage": "1.0.0-beta.20",
48
48
  "@orpc/contract": "^1.16.2",
49
49
  "zod": "^4.6.7"
50
50
  },