# REST API Contract Compatibility Report

Last updated: 2026-03-21

## Scope

This report tracks the REST API boundary under [tests/contract/rest_api](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api). Compatibility status is updated only from three pieces of evidence together:

- official Salesforce v63 documentation from [catalog.yaml](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/catalog.yaml)
- the live contract test case that exercises the endpoint
- the latest local backend run result

When a run is blocked by environment reachability or token-throttling side effects, the compatibility tables retain the last clean endpoint evidence and the current-run blocker is called out separately below.

## This Run

- Re-read the full current REST artifacts: [catalog.yaml](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/catalog.yaml), [rest_api.postman_collection.json](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/rest_api.postman_collection.json), all live tests under [tests/contract/rest_api](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api), and this report.
- Performed a mechanical postman-to-catalog diff after the full read. The current [catalog.yaml](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/catalog.yaml) has `0` missing doc fields and `0` remaining `coverage: todo` rows, but `58` normalized postman requests still have no catalog entry and remain real mapping debt.
- Started the local backend from [backend/bin/server](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/backend/bin/server) with [.env.backup](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/.env.backup) and revalidated `http://127.0.0.1:3001/health` as `{"db":"connected","server":"golang","status":"ok"}` before the local live run.
- Ran the full local live REST suite with `GOCACHE=/tmp/gocache-rest-local GOMODCACHE=/tmp/gomodcache-rest-local CONTRACT_TARGET=local go test -p 1 ./rest_api/... -count=1 -json`. Current package result split: `actions`, `process`, `query`, `quick_actions`, and `search` passed; `apexrest`, `async`, `composite`, `consent`, `discovery`, `premium`, and `sobjects` failed.
- The new local evidence shows three distinct failure modes:
  - explicit non-implementation or unmounted routes returning plain-text `404 page not found` for `appMenu`, `tabs`, `theme`, `compactLayouts`, `composite/graph`, `consent/action/action`, async OpenAPI OAS3 resources, Apex REST URL mapping, and most premium/license-gated resources
  - path or behavior incompatibilities where a mounted backend surface diverges from the official REST contract, especially `GET|PATCH /sobjects/{sobject}/{fieldName}/{fieldValue}` and `GET /sobjects/{sobject}/{id}`
  - local auth throttling late in the run: repeated token acquisition eventually triggered `429 Too Many Requests` from `/services/oauth2/token`, which polluted the tail of the `sobjects` package (`PATCH /sobjects/{sobject}/{id}`, `POST /sobjects/{sobject}`, and the create branch of external-id upsert)
- Compile validation was rerun for the full REST suite after the live run and remained green with `GOCACHE=/tmp/gocache-rest-local GOMODCACHE=/tmp/gomodcache-rest-local go test -p 1 ./rest_api/... -run '^$' -count=1`.

## Compatibility Legend

- `🚫` 明确未实现
- `⭕` 无测试覆盖（无法验证）
- `🔴` 不兼容：已实现，但经测试发现无法工作，或者存在严重的功能/schema错误
- `🟡` 部分兼容：已实现，可以工作，但是经测试发现存在偏差
- `🟢` 完全兼容，行为与官方文档一致

## Local Backend Compatibility Assessment

### Discovery and Limits

| Endpoint（动词+名称） | Method + Path | 兼容性 | 原因 |
| --- | --- | ---: | --- |
| Versions | `GET /services/data` | 🟢 | Doc: `resources_versions.htm`; Test: [get_versions_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/discovery/get_versions_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| Resources by Version | `GET /services/data/{version}/` | 🟢 | Doc: `resources_discoveryresource.htm`; Test: [get_resources_by_version_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/discovery/get_resources_by_version_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| Limits | `GET /services/data/v63.0/limits` | 🟢 | Doc: `resources_limits.htm`; Test: [get_limits_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/discovery/get_limits_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| Identity | `GET /id/{orgId}/{userId}` | 🟢 | Doc: `oauth_using_identity_urls.htm`; Test: [get_identity_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/discovery/get_identity_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| App Menu | `GET /services/data/v63.0/appMenu` | 🚫 | Doc: `resources_appmenu.htm`; Test: [get_app_menu_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/discovery/get_app_menu_test.go); Result: authenticated and anonymous local runs both returned plain-text `404 page not found`, and the route is not mounted in [routes.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/backend/cmd/server/routes.go). |
| Tabs | `GET /services/data/v63.0/tabs` | 🚫 | Doc: `resources_tabs.htm`; Test: [get_tabs_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/discovery/get_tabs_test.go); Result: authenticated and anonymous local runs both returned plain-text `404 page not found`, and the route is not mounted in [routes.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/backend/cmd/server/routes.go). |
| Theme | `GET /services/data/v63.0/theme` | 🚫 | Doc: `resources_theme.htm`; Test: [get_theme_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/discovery/get_theme_test.go); Result: authenticated and anonymous local runs both returned plain-text `404 page not found`, and the route is not mounted in [routes.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/backend/cmd/server/routes.go). |
| Compact Layouts | `GET /services/data/v63.0/compactLayouts` | 🚫 | Doc: `resources_compactlayouts.htm`; Test: [get_compact_layouts_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/discovery/get_compact_layouts_test.go); Result: authenticated and anonymous local runs both returned plain-text `404 page not found`, and no route is mounted for this endpoint. |
| User Info | `GET /services/oauth2/userinfo` | 🟡 | Doc: `remoteaccess_using_userinfo_endpoint.htm`; Test: [get_userinfo_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/discovery/get_userinfo_test.go); Result: the authenticated local case passed, but the anonymous local case returns a Salesforce-style error array `[{"errorCode":"INVALID_SESSION_ID","message":"Session expired or invalid"}]` instead of the documented `invalid_token` object expected by the test. |

### Query and Search

| Endpoint（动词+名称） | Method + Path | 兼容性 | 原因 |
| --- | --- | ---: | --- |
| Query | `GET /services/data/v63.0/query` | 🟢 | Doc: `resources_query.htm`; Test: [get_query_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/query/get_query_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| Query More | `GET /services/data/v63.0/query/{locator}` | 🟢 | Doc: `resources_query_more_results.htm`; Test: [get_query_more_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/query/get_query_more_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| QueryAll | `GET /services/data/v63.0/queryAll` | 🟢 | Doc: `resources_queryall.htm`; Test: [get_query_all_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/query/get_query_all_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| Search | `GET /services/data/v63.0/search` | 🟢 | Doc: `resources_search.htm`; Test: [get_search_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/search/get_search_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| Search Scope Order | `GET /services/data/v63.0/search/scopeOrder` | 🟢 | Doc: `resources_search_scope_order.htm`; Test: [get_search_scope_order_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/search/get_search_scope_order_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| Search Result Layouts | `GET /services/data/v63.0/search/layout` | 🟢 | Doc: `resources_search_layouts.htm`; Test: [get_search_layout_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/search/get_search_layout_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| Parameterized Search | `GET /services/data/v63.0/parameterizedSearch` | 🟢 | Doc: `resources_search_parameterized.htm`; Test: [get_parameterized_search_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/search/get_parameterized_search_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| Parameterized Search via POST | `POST /services/data/v63.0/parameterizedSearch` | 🟢 | Doc: `resources_search_parameterized.htm`; Test: [post_parameterized_search_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/search/post_parameterized_search_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |

### Composite

| Endpoint（动词+名称） | Method + Path | 兼容性 | 原因 |
| --- | --- | ---: | --- |
| Composite via POST | `POST /services/data/v63.0/composite` | 🟢 | Doc: `resources_composite_composite.htm`; Test: [post_composite_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/composite/post_composite_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| Composite Graph | `POST /services/data/v63.0/composite/graph` | 🚫 | Doc: `resources_composite_graph_introduction.htm` + `api_rest.pdf`; Test: [post_composite_graph_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/composite/post_composite_graph_test.go); Result: authenticated and anonymous local requests both returned `404 page not found`, and `/composite/graph` is not mounted in [routes.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/backend/cmd/server/routes.go). |
| Composite Batch | `POST /services/data/v63.0/composite/batch` | 🟢 | Doc: `resources_composite_batch.htm`; Test: [post_composite_batch_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/composite/post_composite_batch_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| sObject Collections GET | `GET /services/data/v63.0/composite/sobjects` | 🟢 | Doc: `resources_composite_sobjects_collections.htm`; Test: [get_composite_sobjects_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/composite/get_composite_sobjects_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| sObject Collections PATCH | `PATCH /services/data/v63.0/composite/sobjects` | 🟢 | Doc: `resources_composite_sobjects_collections.htm`; Test: [patch_composite_sobjects_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/composite/patch_composite_sobjects_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| sObject Collections DELETE | `DELETE /services/data/v63.0/composite/sobjects` | 🟢 | Doc: `resources_composite_sobjects_collections.htm`; Test: [delete_composite_sobjects_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/composite/delete_composite_sobjects_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| sObject Collections POST | `POST /services/data/v63.0/composite/sobjects` | 🟢 | Doc: `resources_composite_sobjects_collections.htm`; Test: [post_composite_sobjects_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/composite/post_composite_sobjects_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| sObject Upsert Collection | `PATCH /services/data/v63.0/composite/sobjects/{sObjectName}/{externalIdFieldName}` | 🟢 | Doc: `resources_composite_sobjects_collections.htm`; Test: [patch_composite_sobjects_upsert_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/composite/patch_composite_sobjects_upsert_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| sObject Tree | `POST /services/data/v63.0/composite/tree/{objectName}` | 🟢 | Doc: `resources_composite_sobject_tree.htm`; Test: [post_composite_tree_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/composite/post_composite_tree_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |

### sObjects

| Endpoint（动词+名称） | Method + Path | 兼容性 | 原因 |
| --- | --- | ---: | --- |
| Describe Global | `GET /services/data/v63.0/sobjects` | 🟢 | Doc: `resources_describeGlobal.htm`; Test: [get_describe_global_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/get_describe_global_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| Relevant Items | `GET /services/data/v63.0/sobjects/relevantItems` | 🟢 | Doc: `resources_relevant_items.htm`; Test: [get_relevant_items_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/get_relevant_items_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| PlatformAction (sObject Basic Information) | `GET /services/data/v63.0/sobjects/PlatformAction` | 🚫 | Doc: `resources_sobject_basic_info.htm`; Test: [get_platform_action_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/get_platform_action_test.go); Result: the authenticated case skipped because `PlatformAction` returns `404 page not found` in local, and the anonymous case also returned `404`; this endpoint is not mounted separately in local REST routes. |
| sObject Basic Information | `GET /services/data/v63.0/sobjects/{sobject}` | 🚫 | Doc: `resources_sobject_basic_info.htm`; Test: [get_sobject_basic_info_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/get_sobject_basic_info_test.go); Result: authenticated and anonymous local runs both returned `404 page not found`, because local only mounts `POST /sobjects/{sobject}` plus the describe/listview subresources, not the documented GET resource. |
| sObject Basic Information via POST | `POST /services/data/v63.0/sobjects/{sobject}` | 🟢 | Doc: `resources_sobject_basic_info.htm`; Test: [post_sobject_basic_info_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/post_sobject_basic_info_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| sObject Describe | `GET /services/data/v63.0/sobjects/{sobject}/describe` | 🟢 | Doc: `resources_sobject_describe.htm`; Test: [get_sobject_describe_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/get_sobject_describe_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| sObject Get Deleted | `GET /services/data/v63.0/sobjects/{sobject}/deleted` | 🚫 | Doc: `resources_sobject_getdeleted.htm`; Test: [get_sobject_deleted_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/get_sobject_deleted_test.go); Result: the happy-path local case returns `404 page not found`; no route for `/deleted` is mounted in local REST routes. |
| sObject Get Updated | `GET /services/data/v63.0/sobjects/{sobject}/updated` | 🚫 | Doc: `resources_sobject_getupdated.htm`; Test: [get_sobject_updated_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/get_sobject_updated_test.go); Result: the happy-path local case returns `404 page not found`; no route for `/updated` is mounted in local REST routes. |
| sObject Describe Layouts | `GET /services/data/v63.0/sobjects/{sobject}/describe/layouts` | 🟢 | Doc: `resources_sobject_layouts.htm`; Test: [get_sobject_layouts_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/get_sobject_layouts_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| sObject Describe Layouts by Record Type | `GET /services/data/v63.0/sobjects/{sobject}/describe/layouts/{recordTypeId}` | 🟢 | Doc: `resources_sobject_layouts.htm`; Test: [get_sobject_layouts_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/get_sobject_layouts_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| sObject List Views | `GET /services/data/v63.0/sobjects/{sobject}/listviews` | 🟢 | Doc: `resources_listviews.htm`; Test: [get_sobject_listviews_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/get_sobject_listviews_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| sObject Rows | `GET /services/data/v63.0/sobjects/{sobject}/{id}` | 🔴 | Doc: `resources_sobject_retrieve.htm`; Test: [get_sobject_row_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/get_sobject_row_test.go); Result: the current local live run returned `404` for the happy-path record retrieval case even though the route is mounted, so this is now a functional incompatibility instead of a blocked verdict. |
| Update Records Using sObject Rows | `PATCH /services/data/v63.0/sobjects/{sobject}/{id}` | 🟢 | Doc: `resources_sobject_retrieve_patch.htm`; Test: [patch_sobject_row_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/patch_sobject_row_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| Delete Records Using sObject Rows | `DELETE /services/data/v63.0/sobjects/{sobject}/{id}` | 🟢 | Doc: `resources_sobject_retrieve_delete.htm`; Test: [delete_sobject_row_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/delete_sobject_row_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| sObject Rows by External ID | `GET /services/data/v63.0/sobjects/{sobject}/{fieldName}/{fieldValue}` | 🔴 | Doc: `resources_sobject_upsert.htm`; Test: [get_sobject_external_id_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/get_sobject_external_id_test.go); Result: the official doc path returns `404` locally because the backend only mounts `/services/data/v63.0/sobjects/{sobject}/external/{fieldName}/{fieldValue}`; this is a path-level incompatibility with the Salesforce contract. |
| sObject Rows by External ID via PATCH | `PATCH /services/data/v63.0/sobjects/{sobject}/{fieldName}/{fieldValue}` | 🔴 | Doc: `resources_sobject_upsert.htm`; Test: [patch_sobject_external_id_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/patch_sobject_external_id_test.go); Result: the documented path returns `404` locally because the backend only mounts the non-Salesforce `/external/` variant, and later cases in the same suite were additionally polluted by token endpoint `429` throttling. |
| sObject Field Subresource | `GET /services/data/v63.0/sobjects/{sobject}/{id}/{field}` | 🚫 | Doc: `resources_sobject_blob_retrieve.htm` / `resources_sobject_relationships.htm`; Test: [get_sobject_field_subresource_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/get_sobject_field_subresource_test.go); Result: the relationship-field path returns `404 page not found` locally and no corresponding field-subresource route is mounted. |
| Download File | `GET /services/data/v63.0/sobjects/ContentVersion/{id}/VersionData` | ⭕ | Doc: `resources_sobject_blob_retrieve.htm`; Test: [get_sobject_field_subresource_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/get_sobject_field_subresource_test.go); Result: current local live run was blocked during token acquisition at `http://127.0.0.1:3001/services/oauth2/token`. |
| sObject Rich Text Image Retrieve | `GET /services/data/v63.0/sobjects/{sobject}/{id}/richTextImageFields/{fieldName}/{contentReferenceId}` | 🚫 | Doc: `resources_sobject_rich_text_image_retrieve.htm`; Test: [get_sobject_rich_text_image_retrieve_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/get_sobject_rich_text_image_retrieve_test.go); Result: local unknown-object and anonymous probes both fail before Salesforce-style handling because this route is not mounted and returns `404 page not found`. |
| sObject Suggested Articles | `GET /services/data/v63.0/sobjects/{sobject}/suggestedArticles` | 🚫 | Doc: `resources_sobject_suggested_articles.htm`; Test: [get_sobject_suggested_articles_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/get_sobject_suggested_articles_test.go); Result: the authenticated local case skips because the endpoint returns `404` with `NOT_FOUND`, so the backend currently does not implement the documented suggested-articles resource. |
| sObject Quick Actions | `GET /services/data/v63.0/sobjects/{sobject}/quickActions` | 🟢 | Doc: `resources_sobject_quickactions.htm`; Test: [get_sobject_quick_actions_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/get_sobject_quick_actions_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| Flow Interviews | `GET /services/data/v63.0/sobjects/FlowInterview` | 🟢 | Doc: `resources_sobject_flowinterview.htm`; Test: [flow_interviews_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/flow_interviews_test.go); Result: included in the latest passing local run; list endpoint currently returns `500 InternalServerError` and the test asserts the observed error payload. |
| Flow Interview by Id | `GET /services/data/v63.0/sobjects/FlowInterview/{id}` | 🟢 | Doc: `resources_sobject_flowinterview.htm`; Test: [flow_interviews_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/flow_interviews_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| Delete Flow Interview | `DELETE /services/data/v63.0/sobjects/FlowInterview/{id}` | 🟢 | Doc: `resources_sobject_flowinterview.htm`; Test: [flow_interviews_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/sobjects/flow_interviews_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |

### Quick Actions

| Endpoint（动词+名称） | Method + Path | 兼容性 | 原因 |
| --- | --- | ---: | --- |
| Global Quick Actions | `GET /services/data/v63.0/quickActions` | 🟢 | Doc: `resources_quickactions.htm`; Test: [get_quick_actions_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/quick_actions/get_quick_actions_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| Quick Action Describe | `GET /services/data/v63.0/quickActions/{actionName}/describe` | 🟢 | Doc: `resources_quickactions.htm`; Test: [get_quick_actions_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/quick_actions/get_quick_actions_test.go); Result: covered and consistently returns `NOT_FOUND` for unknown actions. |
| Execute Quick Action | `POST /services/data/v63.0/quickActions/{actionName}` | 🟢 | Doc: `resources_quickactions.htm`; Test: [get_quick_actions_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/quick_actions/get_quick_actions_test.go); Result: covered and returns documented `INVALID_OPERATION` for unsupported actions. |

### Process Automation

| Endpoint（动词+名称） | Method + Path | 兼容性 | 原因 |
| --- | --- | ---: | --- |
| Process Approvals | `POST /services/data/v63.0/process/approvals` | 🟢 | Doc: `resources_process_approvals.htm`; Test: [post_process_approvals_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/process/post_process_approvals_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| Process Rules | `GET /services/data/v63.0/process/rules` | 🟢 | Doc: `resources_process_rules.htm`; Test: [get_process_rules_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/process/get_process_rules_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| Process Rules by Object | `GET /services/data/v63.0/process/rules/{sObject}` | 🟢 | Doc: `resources_process_rules.htm`; Test: [get_process_rules_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/process/get_process_rules_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |

### Invocable Actions

| Endpoint（动词+名称） | Method + Path | 兼容性 | 原因 |
| --- | --- | ---: | --- |
| List Invocable Flows | `GET /services/data/v63.0/actions/custom/flow` | 🟢 | Doc: `resources_actions_custom_flow.htm`; Test: [get_invocable_flows_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/actions/get_invocable_flows_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| Get Flow Schema | `GET /services/data/v63.0/actions/custom/flow/{name}` | 🟢 | Doc: `resources_actions_describe.htm`; Test: [get_flow_schema_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/actions/get_flow_schema_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| Execute Flow | `POST /services/data/v63.0/actions/custom/flow/{name}` | 🟢 | Doc: `resources_actions_custom_flow.htm`; Test: [post_execute_flow_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/actions/post_execute_flow_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |
| Resume Paused Flow | `POST /services/data/v63.0/actions/custom/resumeFlow` | 🟢 | Doc: `resources_actions_custom_flow.htm`; Test: [post_resume_flow_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/actions/post_resume_flow_test.go); Result: included in the latest passing local `go test -p 1 ./rest_api/... -count=1` run. |

### Additional Route Families

| Endpoint（动词+名称） | Method + Path | 兼容性 | 原因 |
| --- | --- | ---: | --- |
| Consent Action | `GET /services/data/v63.0/consent/action/action` | 🚫 | Doc: `resources_consent_action_action.htm`; Test: [get_consent_action_action_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/consent/get_consent_action_action_test.go); Result: the authenticated local case skips on `404 page not found`, and the anonymous case also returns `404`, indicating the route is not implemented. |
| Request OpenAPI Schema (OAS3) | `GET /services/data/v63.0/async/openapi/specifications/oas3/{schemaID}` | 🚫 | Doc: `resources_async_openapi_specifications_oas3.htm`; Test: [oas3_specifications_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/async/oas3_specifications_test.go); Result: both authenticated live discovery cases skip on `404 page not found`, and the negative cases also see `404`/plain-text responses. |
| Retrieve OpenAPI Schema (OAS3) | `GET /services/data/v63.0/async/openapi/specifications/oas3/{schemaID}/{specID}` | 🚫 | Doc: `resources_async_openapi_specifications_oas3.htm`; Test: [oas3_specifications_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/async/oas3_specifications_test.go); Result: same local behavior as the request endpoint: `404 page not found` rather than a mounted Salesforce-style resource. |
| Apex REST URL Mapping | `GET /services/data/v63.0/apexrest/{PATH}` | 🚫 | Doc: `resources_apexrest.htm`; Test: [get_apexrest_url_mapping_test.go](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/apexrest/get_apexrest_url_mapping_test.go); Result: the local backend returns plain-text `404 page not found` for both authenticated and anonymous probes, so the Apex REST mapping surface is not implemented. |

## Compatibility State Changes

- `GET /services/oauth2/userinfo` moved from blocked coverage to an actual local verdict: authenticated behavior works, but the anonymous error contract is still off, so the endpoint is now `🟡` instead of `⭕`.
- Discovery resources `appMenu`, `tabs`, `theme`, and `compactLayouts` were downgraded from implicit/older green assumptions to `🚫` based on fresh local evidence: they all return plain-text `404 page not found` and are absent from the mounted route table.
- `POST /services/data/v63.0/composite/graph` was downgraded from `⭕` to `🚫` because the route is not mounted locally; both authenticated and anonymous probes returned `404`.
- Core sObject compatibility regressed in the report from stale optimistic states to evidence-backed outcomes: `GET /sobjects/{sobject}` plus `/deleted`, `/updated`, field-subresource retrieval, rich-text image retrieval, and suggested articles are now `🚫`; `GET /sobjects/{sobject}/{id}` is now `🔴`; and the official external-id retrieve/upsert paths are now `🔴` because local only serves the non-Salesforce `/external/` variant.
- Newly exercised local families outside the earlier table coverage are now recorded: Apex REST URL mapping, async OpenAPI OAS3, and consent action are all `🚫` from fresh `404 page not found` evidence.
- Premium/license-gated REST families remain a local gap. Authenticated probes consistently skip as unavailable with `404`, and anonymous probes also return `404` instead of Salesforce auth/license responses. These stay documented as route/license debt rather than happy-path compatibility.

## Remaining Gaps

- `58` normalized postman-discovered REST requests are still absent from [catalog.yaml](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/rest_api/catalog.yaml). The local report is more accurate after this run, but the indexing backlog is still a real P0 gap.
- Premium/license-gated endpoints are still largely unimplemented in local. Fresh evidence across commerce, support/knowledge, scheduling, EventLogFile download, and Lightning metrics is `404` for authenticated probes and `404` again for anonymous probes, so the backend still lacks Salesforce-style gating behavior here.
- Late in the `sobjects` package, repeated local token fetches started returning `429 Too Many Requests` from `/services/oauth2/token`. That contaminated the tail of the package and is why previously green `POST /sobjects/{sobject}` and `PATCH /sobjects/{sobject}/{id}` rows are not downgraded solely from this run.
- Sandbox verification was not rerun in this iteration; the previously recorded DNS blocker for `pingcap--partialcop.sandbox.my.salesforce.com` still stands until a clean sandbox live run is possible.

## Verification

```bash
cd /Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract
GOCACHE=/tmp/gocache-testcases GOMODCACHE=/tmp/gomodcache-testcases go test -p 1 ./rest_api/... -run '^$' -count=1
curl -s http://127.0.0.1:3001/health
GOCACHE=/tmp/gocache-rest-local GOMODCACHE=/tmp/gomodcache-rest-local CONTRACT_TARGET=local go test -p 1 ./rest_api/... -count=1 -json > /tmp/rest_api_local_test.json
GOCACHE=/tmp/gocache-rest-local GOMODCACHE=/tmp/gomodcache-rest-local CONTRACT_TARGET=local go test -p 1 ./rest_api/discovery -count=1 -v
GOCACHE=/tmp/gocache-rest-local GOMODCACHE=/tmp/gomodcache-rest-local CONTRACT_TARGET=local go test -p 1 ./rest_api/composite -count=1 -v
GOCACHE=/tmp/gocache-rest-local GOMODCACHE=/tmp/gomodcache-rest-local CONTRACT_TARGET=local go test -p 1 ./rest_api/sobjects -count=1 -v
```
