# Bulk API V2 Contract Compatibility Report

Last updated: 2026-03-21

## Scope

This report tracks the Bulk API V2 live contract suite under [`tests/contract/bulk_api_v2`](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/bulk_api_v2). Compatibility status is updated only from three pieces of evidence together:

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

Current inventory from [`catalog.yaml`](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/bulk_api_v2/catalog.yaml):

- `9` tracked endpoints
- `0` `doc: todo` rows

## This Run

- Re-read the current Bulk API V2 artifacts: [`catalog.yaml`](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/bulk_api_v2/catalog.yaml), all live tests under [`tests/contract/bulk_api_v2`](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/bulk_api_v2), and the previous report.
- Revalidated the local backend health at `http://127.0.0.1:3001/health` as `{"db":"connected","server":"golang","status":"ok"}` before the live run.
- Ran the full local live Bulk API V2 suite with `GOCACHE=/tmp/gocache-bulk-local GOMODCACHE=/tmp/gomodcache-bulk-local CONTRACT_TARGET=local go test -p 1 ./bulk_api_v2/... -count=1 -json > /tmp/bulk_api_v2_local_test.json`.
- The first live run exposed a test-side decoding bug in [`auth/get_jobs_query_job_id_without_authorization_test.go`](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/bulk_api_v2/auth/get_jobs_query_job_id_without_authorization_test.go): the local backend correctly returned a Salesforce-style unauthorized error array, but the test tried to unmarshal it into a map.
- After fixing that test to decode the actual error array shape, the full local suite passed.
- Revalidated compile-only coverage with `GOCACHE=/tmp/gocache-bulk-local GOMODCACHE=/tmp/gomodcache-bulk-local go test -p 1 ./bulk_api_v2/... -run '^$' -count=1`, which passed.

## Compatibility Legend

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

## Local Backend Compatibility Assessment

### Auth

| Endpoint | Method + Path | 兼容性 | Reason |
| --- | --- | ---: | --- |
| Issue Client Credentials Token | `POST /services/oauth2/token` | 🟢 | Test: [`auth/post_services_oauth2_token_test.go`](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/bulk_api_v2/auth/post_services_oauth2_token_test.go); both the form-encoded and JSON branches passed against the local backend in the latest run. |
| Reject Missing Bulk Authorization Header | `GET /services/data/v63.0/jobs/query/{jobId}` | 🟢 | Test: [`auth/get_jobs_query_job_id_without_authorization_test.go`](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/bulk_api_v2/auth/get_jobs_query_job_id_without_authorization_test.go); the local backend returns a Salesforce-style `401` with an `INVALID_SESSION_ID` error array, and the test now decodes that shape correctly. |

### Query

| Endpoint | Method + Path | 兼容性 | Reason |
| --- | --- | ---: | --- |
| Create Query Job | `POST /services/data/v63.0/jobs/query` | 🟢 | Test: [`query/post_jobs_query_test.go`](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/bulk_api_v2/query/post_jobs_query_test.go); the local backend created the live query job successfully in the latest run. |
| Get Query Job | `GET /services/data/v63.0/jobs/query/{jobId}` | 🟢 | Test: [`query/get_jobs_query_job_id_test.go`](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/bulk_api_v2/query/get_jobs_query_job_id_test.go); created jobs were retrievable and the negative path stayed consistent with the suite. |
| Get Query Job Results | `GET /services/data/v63.0/jobs/query/{jobId}/results` | 🟢 | Test: [`query/get_jobs_query_job_id_results_test.go`](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/bulk_api_v2/query/get_jobs_query_job_id_results_test.go); the local backend returned the expected result payload shape for completed jobs. |

### Ingest

| Endpoint | Method + Path | 兼容性 | Reason |
| --- | --- | ---: | --- |
| Create Ingest Job | `POST /services/data/v63.0/jobs/ingest` | 🟢 | Test: [`ingest/post_jobs_ingest_test.go`](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/bulk_api_v2/ingest/post_jobs_ingest_test.go); the local backend accepted the ingest job request and returned an open job payload. |
| Get Ingest Job | `GET /services/data/v63.0/jobs/ingest/{jobId}` | 🟢 | Test: [`ingest/get_jobs_ingest_job_id_test.go`](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/bulk_api_v2/ingest/get_jobs_ingest_job_id_test.go); created ingest jobs were readable in the latest run. |
| Close Ingest Job | `PATCH /services/data/v63.0/jobs/ingest/{jobId}` | 🟢 | Test: [`ingest/patch_jobs_ingest_job_id_test.go`](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/bulk_api_v2/ingest/patch_jobs_ingest_job_id_test.go); the local backend handled valid and invalid state transitions as expected by the suite. |
| Upload Ingest Job Data | `PUT /services/data/v63.0/jobs/ingest/{jobId}/batches` | 🟢 | Test: [`ingest/put_jobs_ingest_job_id_batches_test.go`](/Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract/bulk_api_v2/ingest/put_jobs_ingest_job_id_batches_test.go); the local backend accepted CSV uploads for open jobs and rejected invalid lifecycle states correctly. |

## Compatibility State Changes

- The previous local failure in `auth/get_jobs_query_job_id_without_authorization_test.go` was a test decoding bug, not a backend compatibility issue. The local backend already returned the correct Salesforce-style unauthorized error array.
- After fixing that test, the full local Bulk API V2 suite is now green.
- The report now uses the shared five-state legend and the same high-level structure as the refreshed REST and UI API reports.

## Remaining Gaps

- No current endpoint-level gaps remain in the local Bulk API V2 suite.
- The catalog is already closed at `9/9` covered with no `doc: todo` rows.

## Verification

```bash
cd /Users/liangzhiyuan/Projects/MetaDrivenPlatform4AI/tests/contract
GOCACHE=/tmp/gocache-bulk-local GOMODCACHE=/tmp/gomodcache-bulk-local go test -p 1 ./bulk_api_v2/... -run '^$' -count=1
GOCACHE=/tmp/gocache-bulk-local GOMODCACHE=/tmp/gomodcache-bulk-local CONTRACT_TARGET=local go test -p 1 ./bulk_api_v2/... -count=1 -json > /tmp/bulk_api_v2_local_test.json
```
