# Check Import Source Async Frontend API Plan

## Analysis

### Impact Table

| Area | File | Change | Verification | Success Criteria |
|------|------|--------|--------------|------------------|
| Premium import OpenAPI contract | `idl/idl/dataflow/adminapi/v1beta2/import_into.proto` | Add frontend-facing async RPCs for starting and polling import source checks while keeping the existing `CheckImportSource` contract intact | `make generate-idl` | Generated protobuf / gateway / swagger artifacts include the new RPCs and messages without manual edits in generated files |
| Precheck task persistence | `internal/db/entity/entity.go`, `migrate/record_202604201140_add_import_into_precheck_task.go`, `migrate/init_schema.go` | Add a dedicated table for import source precheck task context keyed by `task_id`, so polling APIs only need `task_id` and cluster scope | `make generate-entity` | A new DB table exists for precheck task context, migration is idempotent, and empty database initialization includes the table |
| Import source check service logic | `internal/openapi/service/importadmin/import_into.go` | Extract shared request normalization helpers, persist async task context on create, and make polling load the original context from DB instead of requiring it in the request | `go test ./internal/openapi/service/importadmin -run '^(TestBuildCheckImportSource|TestPersistCheckImportSourcePrecheckTask|TestJoinSourceURI_PreservesQuery|TestNormalizeAzureBlobInput)$'` | Sync and async entry points produce the same task IDs and async polling returns the same final payload semantics without extra request context |
| Service tests | `internal/openapi/service/importadmin/import_into_test.go` | Add helper-level tests for task context persistence and response shaping | `go test ./internal/openapi/service/importadmin -run '^(TestBuildCheckImportSource|TestPersistCheckImportSourcePrecheckTask|TestJoinSourceURI_PreservesQuery|TestNormalizeAzureBlobInput)$'` | The new helpers are deterministic and the async polling response matches the sync result mapping |

### Symbols To Keep / Introduce

Keep:

- `buildCheckImportSourceTaskID`
- `buildCheckImportSourceSuccessResp`
- Existing `CheckImportSource` RPC and response contract

Introduce:

- `CreateCheckImportSourceTask`
- `GetCheckImportSourceTask`
- `CreateCheckImportSourceTaskReq`
- `CreateCheckImportSourceTaskResp`
- `GetCheckImportSourceTaskReq`
- `GetCheckImportSourceTaskResp`
- `ImportIntoPrecheckTask`
- `buildCheckImportSourceTaskRequest`
- `createImportIntoPrecheckTask`
- `getImportIntoPrecheckTask`

### Scope Notes

- The agent-side async task APIs already exist. This change only exposes frontend-friendly start/poll methods from dataflow-service.
- The existing `CheckImportSource` endpoint should continue to work for current callers. Its internals should reuse the new shared helper path instead of keeping a parallel implementation.
- Task identity must remain deterministic for the same normalized `(clusterID, source, table metas)` input so repeated frontend polls can target the same underlying agent task.
- Polling should not require the caller to resend `source` or `table_metas`; those should be persisted once when the async task is created.

## Execution Steps

1. Extend the Premium import proto with explicit async start/poll RPCs and messages.
   - Add one RPC to create the import source check task.
   - Add one RPC to poll the import source check task by `task_id`.
   - Keep the poll request minimal: cluster scope plus `task_id`, without repeating original source/table-meta payloads.
   - Reuse the existing result shape semantics where practical so frontend handling stays straightforward.
   - Verification:
     - `make generate-idl`
     - Expected: generated `pb.go`, `grpc.pb.go`, `pb.gw.go`, and swagger files update cleanly.

2. Add a dedicated DB table for import source precheck task context.
   - Define a new internal entity keyed by `task_id`, storing the cluster id plus the minimal context required to render the final polling response.
   - Add a migration record and include the table in empty-schema initialization.
   - Prefer storing serialized request context rather than duplicating agent runtime state.
   - Verification:
     - `make generate-entity`
     - `make app-unit-test-local`
     - Expected: the new table schema is generated and the migration compiles cleanly.

3. Refactor import source check request normalization into shared helpers.
   - Centralize source URI normalization, wildcard resolution, task meta construction, and deterministic task ID generation.
   - Make both sync and async entry points call the same helper so behavior cannot drift.
   - Verification:
     - `go test ./internal/openapi/service/importadmin -run '^(TestBuildCheckImportSource|TestPersistCheckImportSourcePrecheckTask)$'`
     - Expected: helper tests prove identical inputs create identical task IDs and normalized metas.

4. Implement frontend-facing async RPCs in `ImportIntoService`.
   - `CreateCheckImportSourceTask` should validate/normalize input, create the agent task idempotently, persist the polling context, and return the derived `task_id`.
   - `GetCheckImportSourceTask` should load the persisted context, poll the agent task, and map running / failed / succeeded states into a frontend-safe response.
   - Verification:
     - `go test ./internal/openapi/service/importadmin -run '^(TestPersistCheckImportSourcePrecheckTask|TestBuildCheckImportSourceSuccessResp)$'`
     - Expected: the polling response exposes running state and final result payload consistently without repeated caller context.

5. Rewire the existing `CheckImportSource` RPC onto the shared helper flow.
   - Keep the current API behavior, but remove duplicated normalization/task handling logic.
   - Verification:
     - `go test ./internal/openapi/service/importadmin`
     - Expected: existing tests still pass with the refactored implementation.

6. Run repository-required verification for Go changes.
   - Verification:
     - `make app-unit-test-local`
      - Expected: command completes successfully without new regressions.

## Risks

- Frontend and existing callers may interpret `success` differently from `status`; the async poll response should mirror current semantics to avoid ambiguity.
- If persisted precheck context diverges from task-id derivation inputs, the poll path could return a result that does not match the created task. Creation and persistence must come from the same normalized helper output.
- Swagger/gateway generation can surface field-naming differences that are not obvious from proto alone, so generated artifacts must be checked as part of verification.
