@mortar-ai/skill 0.7.1 → 0.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,8 @@
1
- # @mortar-ai/skill
1
+ # Appunvs Cloud (Mortar) Skill
2
2
 
3
- [Agent Skills](https://agentskills.io/) package for building on **Mortar** (the
4
- BaaS that AI bundles talk to). Install the canonical `SKILL.md` and its
3
+ [Agent Skills](https://agentskills.io/) package for building on **Appunvs
4
+ Cloud**, powered by the Mortar BaaS. The package and Skill ID retain the stable
5
+ `mortar` engineering name. Install the canonical `SKILL.md` and its
5
6
  `references/` into a compatible agent's skill directory to teach it the SDK
6
7
  core invariants plus on-demand capability references. The split keeps Fabric's
7
8
  loaded prompt small without hiding the storage, realtime, functions, auth, or
package/SKILL.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: mortar
3
- description: Build or change Fabric applications that use Mortar capabilities such as database, auth, storage, realtime, functions, analytics, automation, or messaging. Use for Mortar schema and provisioning, SDK integration, access policy, transactions, or backend consistency; not for Fabric's own control plane or a different backend.
3
+ description: Build or change Fabric applications that use Appunvs Cloud capabilities powered by Mortar, such as database, auth, storage, realtime, functions, analytics, automation, or messaging. Use for Mortar schema and provisioning, SDK integration, access policy, transactions, or backend consistency; not for Fabric's own control plane or a different backend.
4
4
  metadata:
5
5
  activation: auto
6
6
  priority: high
@@ -8,10 +8,12 @@ metadata:
8
8
  - keywords: [database, 数据库, backend, 后端, auth, authentication, 登录, 认证, persistence, 持久化, transaction, 事务, ACID, storage, upload, 文件, realtime, 实时, collaboration, function, compute, analytics, cron, queue, comms, secrets, billing, cloud, 云端]
9
9
  ---
10
10
 
11
- # Mortar for Fabric applications
11
+ # Appunvs Cloud (Mortar) for Fabric applications
12
12
 
13
- Mortar is an independent Backend-as-a-Service used by Fabric-built apps; Fabric
14
- itself does not run on Mortar. Do not infer its setup from another BaaS.
13
+ Appunvs Cloud is the user-facing product powered by the independent Mortar
14
+ Backend-as-a-Service. Fabric-built apps may use it; Fabric itself does not run
15
+ on Mortar. `mortar` remains the stable SDK, tool, API, and source identity. Do
16
+ not infer its setup from another BaaS.
15
17
 
16
18
  ## Fabric integration contract
17
19
 
@@ -81,7 +83,10 @@ below; if platform provisioning fails, report that platform failure.
81
83
  one-table batch or filtered mutation may use the public singleton;
82
84
  cross-table row + queue transactions require trusted server code; object
83
85
  storage and external services never join a PostgreSQL transaction.
84
- 8. Type-check and build. Handle every `{ data, error }` SDK result in UI code.
86
+ 8. Read `references/errors.md` and handle both `{ data, error }` results and
87
+ thrown SDK failures according to the surrounding application's domain and
88
+ interaction design. Follow the application's existing architecture; Mortar
89
+ must not prescribe or introduce a shared UI adapter. Type-check and build.
85
90
 
86
91
  Supported database DDL is `CREATE TABLE`, `DROP TABLE`, `ALTER TABLE … ADD/DROP
87
92
  COLUMN`, `ALTER TABLE … SET ACCESS`, and `CREATE INDEX`. Put
@@ -106,7 +111,12 @@ type names guide application types but do not runtime-validate payload values.
106
111
  recreate a table merely to change permissions.
107
112
  - For a public form, registration, or evidence upload reviewed by an operator,
108
113
  use table/bucket access `public_insert`. It permits new submissions while
109
- denying anonymous list, read, update, delete, and overwrite.
114
+ denying anonymous list, read, update, delete, and overwrite. That anonymous
115
+ restriction is not a blanket browser restriction: an authenticated AppUser
116
+ with `data_role=admin`, or trusted `app`/`admin` scope, may read and moderate
117
+ rows according to the server policy. Before deploying a Function for an
118
+ operator mutation, verify the active session and access policy; use the
119
+ authenticated SDK mutation directly when the data-admin path is supported.
110
120
  - Never use `public` merely to make anonymous submission work: it exposes all
111
121
  rows or files for public read and mutation.
112
122
  - Generate an unguessable logical object key for each public upload.
@@ -146,6 +156,8 @@ Agent Skills hosts resolve the same paths relative to this `SKILL.md`.
146
156
  `references/realtime.md`
147
157
  - Function deployment/invocation, logs, public-key boundaries, and error
148
158
  handling: `references/functions.md`
159
+ - Normalized SDK errors, `{ data, error }` versus thrown calls, retry facts,
160
+ correlation IDs, and Function error ownership: `references/errors.md`
149
161
  - The 9 infrastructure primitives, open capability registry, application
150
162
  modules, usage accounting, and trust surfaces: `references/architecture.md`
151
163
  - Product analytics, error capture, delivery guarantees, and operator summary:
@@ -190,7 +202,8 @@ section.
190
202
  durable backend guarantee.
191
203
  - No secret/admin client or hand-written fallback configuration entered the
192
204
  client bundle.
193
- - Every SDK error path is handled.
205
+ - Every SDK error path has an application-owned failure boundary; Mortar error
206
+ metadata does not dictate the application's UI or recovery flow.
194
207
  - The relevant on-demand reference—not every reference—was consulted.
195
208
  - Type-check and the surface's real build pass.
196
209
 
package/manifest.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schema_version": 1,
3
3
  "id": "mortar",
4
- "version": "0.7.1",
5
- "content_sha256": "sha256:515ca910b01c49b20a3838096bf4b1119be8c07879ab8eda220314d373dfeadd",
4
+ "version": "0.7.3",
5
+ "content_sha256": "sha256:292ee5d8a7b9b5c8165142273a452815eb4418f0169937de0833f76bcf34d0e2",
6
6
  "source_repo": "liamxujia/appunvs",
7
7
  "source_path": "mortar/skill",
8
8
  "distributions": [
@@ -11,6 +11,6 @@
11
11
  ],
12
12
  "npm": {
13
13
  "package": "@mortar-ai/skill",
14
- "version": "0.7.1"
14
+ "version": "0.7.3"
15
15
  }
16
16
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mortar-ai/skill",
3
- "version": "0.7.1",
4
- "description": "Agent skill package for building Fabric applications on Mortar (BaaS), with compact core guidance and on-demand references.",
3
+ "version": "0.7.3",
4
+ "description": "Agent skill for building Fabric applications on Appunvs Cloud powered by Mortar, with compact core guidance and on-demand references.",
5
5
  "main": "index.js",
6
6
  "files": ["SKILL.md", "references", "manifest.json", "index.js", "README.md"],
7
7
  "bin": {
@@ -13,6 +13,13 @@ const signedIn = await mortar.auth.signInWithPassword({ email, password });
13
13
  const sent = await mortar.auth.signInWithOtp({ email }); // or { phone }
14
14
  const verified = await mortar.auth.verifyOtp({ email, token });
15
15
 
16
+ const providerLogin = await mortar.auth.signInWithProvider({
17
+ provider: 'google', // apple | google | wechat | alipay
18
+ connection: 'web',
19
+ idToken,
20
+ nonce,
21
+ });
22
+
16
23
  const { data: sessionData } = await mortar.auth.getSession();
17
24
  const { data: userData, error: userError } = await mortar.auth.getUser();
18
25
  await mortar.auth.signOut();
@@ -22,6 +29,11 @@ Check each returned `error`; do not infer authentication from the presence of UI
22
29
  state. Use `onAuthStateChange` when the UI must react to session changes and
23
30
  unsubscribe during component/page cleanup.
24
31
 
32
+ For provider login, obtain the authorization code or ID token with the
33
+ provider's browser/native SDK and validate OAuth `state` before calling Mortar.
34
+ Use `listOAuthProviders()` to discover the project's public connection IDs.
35
+ Never put provider client secrets or private keys in generated app code.
36
+
25
37
  Password reset starts with `mortar.auth.resetPasswordForEmail(email)` and is
26
38
  confirmed with `passwordResetConfirm(email, token, newPassword)`. Never store or
27
39
  pass session tokens manually unless the user explicitly needs a trusted server
@@ -60,6 +60,38 @@ not claim direct public insert satisfies it. Use a reviewed supported
60
60
  server-side contract that really performs atomic deduplication, or state that
61
61
  the guarantee is not currently available for that client path.
62
62
 
63
+ ## `public_insert` and data-admin moderation
64
+
65
+ `public_insert` means anonymous write-only intake, not that every browser
66
+ session is forbidden from reading or changing rows. An authenticated AppUser
67
+ whose current token has `data_role=admin` can read and moderate those rows;
68
+ trusted `app` and `admin` scopes can do the same. The injected SDK resolves the
69
+ managed AppUser session and attaches its access token automatically, so do not
70
+ ask application code to copy tokens or put privileged project keys in a bundle.
71
+
72
+ For an operator edit supported by that policy, use the authenticated singleton
73
+ directly and handle the result:
74
+
75
+ ```ts
76
+ const { data, error, count } = await mortar
77
+ .from('submissions')
78
+ .update({ display_name: cleanName })
79
+ .eq('id', submissionId)
80
+ .select();
81
+ if (error) throw new Error(error.message);
82
+ ```
83
+
84
+ If the target table has a database trigger that performs the required
85
+ cross-table cascade, the triggering row update and that cascade run inside the
86
+ database transaction. Moving the same update behind a Function does not make
87
+ the database work more atomic; it only adds a compute/network boundary.
88
+
89
+ Do not deploy a Function merely to bypass a policy that was not verified.
90
+ Use trusted server code only when the current authenticated data-admin path is
91
+ actually unsupported, or when the operation needs a server secret, an external
92
+ provider, or a supported cross-table transaction that no database trigger
93
+ already provides.
94
+
63
95
  ## Atomic row mutations
64
96
 
65
97
  Pass an array when every insert or upsert must succeed or fail together. Mortar
@@ -0,0 +1,111 @@
1
+ # Error handling reference
2
+
3
+ Read this reference whenever application code calls Mortar. Mortar provides
4
+ structured failure facts; the application owns their product meaning and user
5
+ experience.
6
+
7
+ ## One normalized error, two JavaScript call shapes
8
+
9
+ Mortar's TypeScript SDK exposes one canonical `MortarApiError` model:
10
+
11
+ - `code`: stable machine code from the server's `error` field
12
+ - `category`: technical class such as `validation`, `authentication`, `quota`,
13
+ `rate_limit`, `dependency`, `network`, or `timeout`
14
+ - `status`: HTTP status, or `0` for a client/transport failure
15
+ - `requestId`: correlation ID from `X-Request-ID`
16
+ - `retryable` and `retryAfterMs`: transport and retry hints
17
+ - `body`: the original structured server error
18
+
19
+ Supabase-compatible query/auth/storage helpers return failures as
20
+ `{ data, error }`. Other SDK methods throw `MortarApiError`. Both shapes carry
21
+ the same underlying Mortar fields; the envelope changes control flow, not the
22
+ meaning of the error.
23
+
24
+ Always check an envelope's `error` before using `data`:
25
+
26
+ ```ts
27
+ const { data, error } = await mortar.from('todos').insert(input);
28
+ if (error) {
29
+ handleTodoCreateFailure(error); // Defined by this application and feature.
30
+ return;
31
+ }
32
+ useCreatedTodo(data);
33
+ ```
34
+
35
+ Throwing APIs already expose `MortarApiError`. When a catch binding is
36
+ `unknown`, `normalizeMortarError` converts transport and SDK failures into the
37
+ same technical model without choosing application behavior:
38
+
39
+ ```ts
40
+ import { normalizeMortarError } from '@mortar-ai/client';
41
+
42
+ try {
43
+ await mortar.storage.upload({ bucket: 'receipts', key, body: file });
44
+ } catch (cause) {
45
+ const error = normalizeMortarError(cause, 'upload receipt');
46
+ handleReceiptUploadFailure(error); // Application-defined, not SDK-defined.
47
+ }
48
+ ```
49
+
50
+ ## Error facts are not interaction policy
51
+
52
+ Mortar does not prescribe a toast, modal, inline field error, navigation,
53
+ reauthentication flow, localization key, reporting rule, or centralized UI
54
+ adapter. An application may handle failures per feature or reuse its own
55
+ abstraction when that matches its architecture.
56
+
57
+ In particular:
58
+
59
+ - `category` is a technical grouping, not a UI action. For example,
60
+ `authentication` does not require immediate navigation to a sign-in screen.
61
+ - `retryable` is a hint that the failure may succeed later, not permission to
62
+ replay the operation automatically.
63
+ - `retryAfterMs` is server timing information, not a required countdown UI.
64
+ - `requestId` supports correlation, but the application decides whether and
65
+ where it is recorded or presented.
66
+ - `body`, `detail`, and `message` are diagnostic data. They are not guaranteed
67
+ to be localized, stable, sanitized for end users, or safe as control-flow
68
+ keys. Branch on stable codes and structured fields instead.
69
+
70
+ Mutating operations are never automatically replayed without an idempotency guarantee.
71
+ An insert, payment, message send, upload, or Function mutation may already have
72
+ completed when the client observes a network failure. Require a documented
73
+ idempotency contract or an explicit application decision before replaying it.
74
+
75
+ ## Function responses are a separate contract
76
+
77
+ `mortar.compute.invoke(...)` throws only for Mortar platform failures marked by
78
+ `X-Mortar-Error: platform`. A tenant Function's response stays a raw
79
+ `Response`, including 4xx and 5xx statuses, because its business-error schema
80
+ belongs to that Function:
81
+
82
+ ```ts
83
+ try {
84
+ const response = await mortar.compute.invoke({
85
+ name: 'create-checkout',
86
+ body: JSON.stringify(input),
87
+ contentType: 'application/json',
88
+ });
89
+
90
+ if (!response.ok) {
91
+ const problem = await response.json();
92
+ applyCheckoutProblem(problem); // Function-owned application contract
93
+ return;
94
+ }
95
+ } catch (error) {
96
+ handleCheckoutPlatformFailure(error); // Application-defined for this operation.
97
+ }
98
+ ```
99
+
100
+ Do not interpret a tenant Function's business body as a Mortar platform error,
101
+ and do not infer error ownership from HTTP status alone.
102
+
103
+ ## Completion checks
104
+
105
+ - Every `{ data, error }` result checks `error` before using `data`.
106
+ - Every throwing Mortar operation has a deliberate application failure boundary.
107
+ - Control flow uses stable error codes and fields rather than diagnostic text.
108
+ - The application, not Mortar, determines UI, localization, navigation,
109
+ reporting, and recovery behavior.
110
+ - Mutating operations are never automatically replayed without an idempotency guarantee.
111
+ - Function business errors follow the Function's documented response schema.
@@ -19,25 +19,51 @@ removes the manifest, both entrypoint forms, and the legacy flat `.js` artifact.
19
19
  Client bundles may invoke a function that the platform already deployed:
20
20
 
21
21
  ```ts
22
- const response = await mortar.compute.invoke({
23
- name: 'create-checkout',
24
- method: 'POST',
25
- body: JSON.stringify({ orderId }),
26
- contentType: 'application/json',
27
- });
28
-
29
- if (!response.ok) {
30
- throw new Error(`Function failed: ${response.status} ${await response.text()}`);
22
+ try {
23
+ const response = await mortar.compute.invoke({
24
+ name: 'create-checkout',
25
+ method: 'POST',
26
+ body: JSON.stringify({ orderId }),
27
+ contentType: 'application/json',
28
+ });
29
+
30
+ if (!response.ok) {
31
+ const problem = await response.json();
32
+ applyCheckoutProblem(problem); // Function-owned business contract
33
+ return;
34
+ }
35
+ const result = await response.json();
36
+ useCheckout(result);
37
+ } catch (error) {
38
+ handleCheckoutPlatformFailure(error); // Application-defined for this operation.
31
39
  }
32
- const result = await response.json();
33
40
  ```
34
41
 
35
42
  `compute.invoke` is the only public-key compute operation. Mortar infrastructure
36
- errors such as unavailable compute or timeout throw; user-function status codes
37
- are returned as the raw `Response`, so check `response.ok` and consume the body.
43
+ errors marked by `X-Mortar-Error: platform` throw; user-function status codes
44
+ are returned as the raw `Response`, so check `response.ok` and consume the body
45
+ according to that Function's documented business-error schema. HTTP status alone
46
+ does not identify which side produced the error. See `errors.md` for the shared
47
+ platform-error facts and the application-owned policy boundary.
38
48
  Function deployment/logs remain operator-side capabilities and must never be
39
49
  recreated with an app/admin key in a browser or mobile bundle.
40
50
 
51
+ ## When not to deploy a Function
52
+
53
+ Check the authenticated row-policy path before introducing compute. In
54
+ particular, `public_insert` denies anonymous reads and mutations but permits an
55
+ authenticated AppUser with `data_role=admin` to moderate rows. When that path
56
+ matches the product requirement, call the row SDK with the managed user session
57
+ instead of deploying a Function merely to obtain an `app` scope.
58
+
59
+ A database trigger invoked by one row mutation already runs in the database
60
+ transaction with that mutation. Wrapping the update in a Function does not make
61
+ the trigger cascade more atomic and adds a separate network/compute failure
62
+ boundary. If a Function is genuinely required, authorize it with a verified
63
+ user JWT or another server-trusted identity. Never accept caller-supplied names,
64
+ employee numbers, roles, or similar request fields as proof of administrator
65
+ identity.
66
+
41
67
  Functions and external providers do not join the caller's PostgreSQL
42
68
  transaction. Make externally visible operations idempotent and persist explicit
43
69
  pending/succeeded/failed state when a workflow must recover.
@@ -1,7 +1,7 @@
1
1
  openapi: 3.0.3
2
2
  info:
3
3
  title: Mortar REST API
4
- version: "0.2.1"
4
+ version: "0.3.0"
5
5
  description: |
6
6
  Backend-as-a-Service for mainland-China-friendly mobile and web apps.
7
7
 
@@ -21,12 +21,12 @@ info:
21
21
  * `AccountToken` — Account session JWT minted by
22
22
  `/v1/_accounts/signin`, or an Account PAT (`mtr_pat_*`); scopes all
23
23
  `/v1/_accounts/*` and project-lifecycle calls to one Mortar account.
24
- * `APIKey` — Bearer token starting with `mtr_live_` (production) or
25
- `mtr_test_` (sandbox); scopes a single project (its tenant_id) and one of
26
- `admin` / `app` / `public` privilege tiers.
24
+ * `APIKey` — raw `X-Mortar-API-Key` value starting with `mtr_live_`
25
+ (production) or `mtr_test_` (sandbox); scopes a single project (its
26
+ tenant_id) and one of `admin` / `app` / `public` privilege tiers.
27
27
 
28
28
  Signed-in project users may additionally send a User access JWT in
29
- `X-Mortar-User-Token`. That optional identity layer is not modeled
29
+ `Authorization: Bearer <jwt>`. That optional identity layer is not modeled
30
30
  consistently by every operation in this partial document.
31
31
 
32
32
  Errors use a uniform `{ "error": "<machine_code>" }` body, occasionally
@@ -577,6 +577,82 @@ paths:
577
577
  "401":
578
578
  description: invalid_credentials.
579
579
 
580
+ /v1/{tenant}/auth/providers:
581
+ parameters:
582
+ - $ref: "#/components/parameters/TenantPath"
583
+ get:
584
+ tags: [auth]
585
+ summary: List configured end-user OAuth provider connections.
586
+ description: |
587
+ Returns connection IDs plus public provider client/application IDs for
588
+ Apple, Google, WeChat, and Alipay. Provider secrets and private keys are
589
+ never returned. Connections are owned by the Mortar deployment and
590
+ shared across projects through `MORTAR_AUTH_APPLE`,
591
+ `MORTAR_AUTH_GOOGLE`, `MORTAR_AUTH_WECHAT`, and `MORTAR_AUTH_ALIPAY`.
592
+ Projects cannot supply or override provider credentials.
593
+ security:
594
+ - APIKey: []
595
+ responses:
596
+ "200":
597
+ description: Configured public provider metadata.
598
+ content:
599
+ application/json:
600
+ schema:
601
+ type: object
602
+ required: [providers]
603
+ properties:
604
+ providers:
605
+ type: array
606
+ items:
607
+ $ref: "#/components/schemas/OAuthProviderConfiguration"
608
+
609
+ /v1/{tenant}/auth/oauth/{provider}:
610
+ parameters:
611
+ - $ref: "#/components/parameters/TenantPath"
612
+ - name: provider
613
+ in: path
614
+ required: true
615
+ schema:
616
+ type: string
617
+ enum: [apple, google, wechat, alipay]
618
+ post:
619
+ tags: [auth]
620
+ summary: Exchange a provider credential for a Mortar User session.
621
+ description: |
622
+ The application starts the provider browser/native flow and validates
623
+ OAuth state before calling this endpoint. Google and Apple accept a
624
+ signed `id_token` or `authorization_code`; WeChat and Alipay accept an
625
+ `authorization_code`. A supplied OIDC nonce is checked against the ID
626
+ token. Successful login resolves a durable provider subject and returns
627
+ the same Mortar session shape as password and OTP login.
628
+ security:
629
+ - APIKey: []
630
+ requestBody:
631
+ required: true
632
+ content:
633
+ application/json:
634
+ schema:
635
+ $ref: "#/components/schemas/OAuthSignInRequest"
636
+ responses:
637
+ "200":
638
+ description: Provider identity verified and Mortar session issued.
639
+ content:
640
+ application/json:
641
+ schema:
642
+ $ref: "#/components/schemas/UserAuthResponse"
643
+ "400":
644
+ description: provider_credential_required / connection_required / connection_invalid.
645
+ "401":
646
+ description: invalid_provider_credential.
647
+ "404":
648
+ description: provider_unsupported.
649
+ "409":
650
+ description: identity_link_required.
651
+ "502":
652
+ description: provider_unavailable.
653
+ "503":
654
+ description: provider_not_configured.
655
+
580
656
  /v1/{tenant}/auth/phone/start:
581
657
  parameters:
582
658
  - $ref: "#/components/parameters/TenantPath"
@@ -1856,12 +1932,19 @@ components:
1856
1932
  use and may be passed via the `MORTAR_ACCOUNT_TOKEN` env var to
1857
1933
  the `mortar` CLI.
1858
1934
  APIKey:
1935
+ type: apiKey
1936
+ in: header
1937
+ name: X-Mortar-API-Key
1938
+ description: |
1939
+ Project-scope API key starting with `mtr_live_` (production) or
1940
+ `mtr_test_` (sandbox), sent as the raw `X-Mortar-API-Key` value.
1941
+ UserToken:
1859
1942
  type: http
1860
1943
  scheme: bearer
1861
- bearerFormat: opaque
1944
+ bearerFormat: JWT
1862
1945
  description: |
1863
- Project-scope API key starting with `mtr_live_` (production) or
1864
- `mtr_test_` (sandbox). Bearer-encoded in `Authorization`.
1946
+ Optional project end-user access JWT in `Authorization: Bearer …`.
1947
+ It supplements, and never replaces, the required `X-Mortar-API-Key`.
1865
1948
 
1866
1949
  parameters:
1867
1950
  TenantPath:
@@ -1895,21 +1978,57 @@ components:
1895
1978
  responses:
1896
1979
  BadRequest:
1897
1980
  description: Malformed request.
1981
+ headers:
1982
+ X-Request-ID:
1983
+ $ref: "#/components/headers/RequestID"
1984
+ X-Mortar-Error:
1985
+ $ref: "#/components/headers/MortarErrorSource"
1898
1986
  content:
1899
1987
  application/json:
1900
1988
  schema:
1901
1989
  $ref: "#/components/schemas/Error"
1902
1990
 
1991
+ headers:
1992
+ RequestID:
1993
+ description: Stable correlation ID echoed by Mortar for this request.
1994
+ schema:
1995
+ type: string
1996
+ MortarErrorSource:
1997
+ description: Present as `platform` when the response was generated by Mortar rather than a tenant Function.
1998
+ schema:
1999
+ type: string
2000
+ enum: [platform]
2001
+
1903
2002
  schemas:
1904
2003
  Error:
1905
2004
  type: object
1906
- required: [error]
2005
+ required: [error, category, request_id]
1907
2006
  properties:
1908
2007
  error:
1909
2008
  type: string
1910
2009
  description: Machine-readable error code (e.g. `invalid_body`).
1911
2010
  detail:
1912
2011
  type: string
2012
+ description: Optional diagnostic detail; applications should localize from `error` instead of displaying this directly.
2013
+ category:
2014
+ type: string
2015
+ description: Stable application-level recovery category.
2016
+ enum: [validation, authentication, permission, not_found, conflict, quota, rate_limit, dependency, internal]
2017
+ request_id:
2018
+ type: string
2019
+ description: Correlation ID matching the `X-Request-ID` response header.
2020
+ retryable:
2021
+ type: boolean
2022
+ description: Whether retrying may succeed. Mutating requests still require an idempotency-safe operation.
2023
+ retry_after_sec:
2024
+ type: integer
2025
+ minimum: 0
2026
+ description: Server-requested delay before retrying, also represented by `Retry-After` when present.
2027
+ fields:
2028
+ type: array
2029
+ description: Optional application input fields associated with a validation error.
2030
+ items:
2031
+ type: string
1913
2032
 
1914
2033
  Account:
1915
2034
  type: object
@@ -2251,6 +2370,53 @@ components:
2251
2370
  type: string
2252
2371
  minLength: 8
2253
2372
 
2373
+ OAuthSignInRequest:
2374
+ type: object
2375
+ properties:
2376
+ connection:
2377
+ type: string
2378
+ description: |
2379
+ Named provider registration. Required when the provider has
2380
+ multiple connections and none is named `default`.
2381
+ authorization_code:
2382
+ type: string
2383
+ description: One-time code returned by the provider flow.
2384
+ id_token:
2385
+ type: string
2386
+ description: Signed Google or Apple OIDC ID token.
2387
+ redirect_uri:
2388
+ type: string
2389
+ format: uri
2390
+ description: Exact redirect URI used to obtain an authorization code.
2391
+ nonce:
2392
+ type: string
2393
+ description: Expected OIDC nonce; checked when supplied.
2394
+ code_verifier:
2395
+ type: string
2396
+ description: Google PKCE verifier used for authorization-code exchange.
2397
+
2398
+ OAuthProviderConfiguration:
2399
+ type: object
2400
+ required: [id, connections]
2401
+ properties:
2402
+ id:
2403
+ type: string
2404
+ enum: [apple, google, wechat, alipay]
2405
+ connections:
2406
+ type: array
2407
+ items:
2408
+ type: object
2409
+ required: [id, client_id]
2410
+ properties:
2411
+ id:
2412
+ type: string
2413
+ client_id:
2414
+ type: string
2415
+ description: Public OAuth client ID or provider AppID.
2416
+ mode:
2417
+ type: string
2418
+ description: Provider-specific mode, such as `mini_program`.
2419
+
2254
2420
  UserAuthResponse:
2255
2421
  type: object
2256
2422
  required: [access_token, user_id, expires_in_sec]