Categories
ETL (13)
- docs/features/ETL/brink-pos-first-integration.md
- docs/features/ETL/etl-source-adapter-framework.md
- docs/features/ETL/fleet/fleet-customer-upload-contract.md
- docs/features/ETL/fleet/fleet-pre-ingestion-processing-architecture.md
- docs/features/ETL/how-to-add-etl-source-adapter.md
- docs/features/ETL/index.md
- docs/features/ETL/kds-cdc/branch-direction-and-flow.md
- docs/features/ETL/kds-cdc/debezium-payload-compatibility-notes.md
- docs/features/ETL/kds-cdc/implementation-breakdown.md
- docs/features/ETL/kds-cdc/index.md
- docs/features/ETL/kds-cdc/kds-cdc-scaling-and-incremental-curation.md
- docs/features/ETL/kds-cdc/performance-and-scaling-notes.md
- docs/features/ETL/tenant-warehouse-schema-evolution.md
# Fleet Customer Upload Contract
1. Purpose
This document defines what the customer-side Fleet system must upload to KDSAI so that one source data file can be accepted, validated, and prepared for the standard ETL process.
Fleet is a customer-facing pre-ingestion area. The customer uploads files to Fleet landing only. KDSAI publishes accepted data to the internal standard ETL raw area only after schema approval and data validation pass.
Supported source data formats for the initial contract are:
Excel
CSV
JSON
JSON Lines
XML2. Core Rules
- One upload package represents one logical dataset upload.
- One
upload-manifest.jsondescribes exactly one source data file. - One upload creates one processing batch in KDSAI.
- Multiple source data files in one manifest are not supported in the initial contract.
- If the customer needs to send several datasets, entities, or worksheets, they must send separate uploads with separate
upload_idvalues. - The customer declares the dataset schema version in the manifest using
schema.version. - The customer must increase
schema.versionwhenever the file structure changes. - KDSAI owns schema approval, validation, and the internal approved contract registry.
- The customer uploads all files first and uploads
metadata/upload-manifest.jsonlast. - KDSAI treats
metadata/upload-manifest.jsonas the signal that the upload is complete. - The customer must not overwrite or replace files in an existing upload path.
- Corrections are sent as new uploads with a new
upload_id.
13. The customer must not write directly to standard ETL raw, load, curated, or failed prefixes.
3. Target Upload Location
The customer uploads files only to the assigned Fleet landing prefix.
Recommended structure:
s3://kds-warehouse-ai-test/fleet/landing/company_id={company_id}/tenant_id={tenant_id}/dataset={dataset}/upload_id={upload_id}/received_at={yyyy-MM-ddTHH-mm-ssZ}/Example:
s3://kds-warehouse-ai-test/fleet/landing/company_id=company-123/tenant_id=tenant-456/dataset=employees/upload_id=upl_20260602_001/received_at=2026-06-02T10-00-00Z/Required package structure:
source/
employees.xlsx
employees_schema.json # optional
metadata/
upload-manifest.json # required; uploaded last4. Upload Manifest
Every upload must include:
metadata/upload-manifest.jsonThe manifest tells KDSAI:
- who sent the data,
- which company and tenant the data belongs to,
- which dataset the file represents,
- which customer-declared schema version the file follows,
- which single source file should be processed,
- how the file should be parsed,
- whether the upload corrects a previous upload.
The customer does not send contract_id or contract_version. KDSAI creates and manages the internal approved contract for each accepted company_id + tenant_id + dataset + schema.version combination.
4.1 Example manifest
{
"manifest_version": "1.0",
"upload_id": "upl_20260602_001",
"company_id": "company-123",
"tenant_id": "tenant-456",
"dataset": "employees",
"source_system": "customer-fleet-agent",
"created_at_utc": "2026-06-02T10:00:00Z",
"schema": {
"version": "1.0.0",
"previous_version": null,
"change_description": null
},
"data_file": {
"file_name": "employees.xlsx",
"relative_path": "source/employees.xlsx",
"file_type": "excel",
"sheet_name": "Employees",
"has_header": true,
"row_count": 1520,
"sha256": "REPLACE_WITH_FILE_HASH"
}
}4.2 Manifest field requirements
| Field | Required | When to provide | Description |
|---|---|---|---|
manifest_version | Yes | Always | Version of this manifest structure. Current value: 1.0. |
upload_id | Yes | Always | Customer-generated idempotency key. Must be unique for the tenant. |
company_id | Yes | Always | Company identifier assigned by KDSAI. Must match the assigned S3 prefix. |
tenant_id | Yes | Always | Tenant identifier assigned by KDSAI. Must match the assigned S3 prefix. |
dataset | Yes | Always | Business dataset name, for example employees, orders, or inventory. |
source_system | Recommended | When known | Name of the customer-side system or agent that produced the export. |
created_at_utc | Yes | Always | UTC timestamp when the export or upload package was created. |
schema | Yes | Always | Customer-declared schema information for this dataset upload. |
schema.version | Yes | Always | Customer-owned schema version. Must change whenever the file structure changes. This is not an approval flag. |
schema.previous_version | Conditional | When this upload introduces a new structure based on a previous version | Previous customer-declared schema version, if known. |
schema.change_description | Recommended | For first uploads and changed structures | Human-readable description of the initial schema or structural change. |
correction | Conditional | When this upload corrects a previous upload | Links the corrected upload to the previous upload. |
data_file | Yes | Always | The single source data file to process. |
schema_file | Optional | Recommended for a new dataset or a new schema version | Optional schema description used by KDSAI during schema proposal and approval. |
5. data_file Requirements
data_file is required and must describe exactly one source data file.
| Field | Required | Applies to | Description |
|---|---|---|---|
file_name | Yes | All formats | Name of the uploaded file. |
relative_path | Yes | All formats | Path relative to the upload root, for example source/employees.xlsx. |
file_type | Yes | All formats | One of: excel, csv, json, jsonl, xml. |
sheet_name | Conditional | Excel | Required for Excel files. Identifies the worksheet to process. |
has_header | Conditional | Excel, CSV | Required for Excel and CSV files. Indicates whether the first row contains column names. |
encoding | Conditional | CSV, text-like files | Required for CSV. UTF-8 is preferred. |
delimiter | Conditional | CSV | Required for CSV. Example: ,, ;, or \t. |
row_count | Optional | All formats | Expected number of data rows. Used for consistency checks when available. |
sha256 | Optional | All formats | File hash. Used to detect incomplete uploads or accidental changes. |
Rules:
- One manifest cannot contain more than one
data_file. - One Excel upload should point to one worksheet only.
- If multiple worksheets must be processed, each worksheet should be sent as a separate upload.
- Excel files should not contain merged cells, totals, comments, or notes inside the data range.
- CSV files should use consistent delimiter, encoding, date format, and decimal format.
- JSON, JSON Lines, and XML files must contain data records, not only schema or metadata.
6. Supported Source File Types
| Type | Extension | Required manifest details | Notes |
|---|---|---|---|
| Excel | .xlsx | sheet_name, has_header | One worksheet per upload. |
| CSV | .csv | delimiter, encoding, has_header | UTF-8 is preferred. |
| JSON | .json | file_type=json | Must contain structured data records. |
| JSON Lines | .jsonl | file_type=jsonl | Preferred for large semi-structured exports. |
| XML | .xml | file_type=xml | XML is treated as a source data format. Mapping rules are handled by KDSAI. |
7. Optional Schema File
A schema_file can be provided when the customer knows the expected structure of the source data.
It is recommended when:
- this is the first upload of a dataset,
- this is a new
schema.version, - the file structure has intentionally changed,
- a column was added, removed, renamed, or changed,
- the customer wants to help KDSAI approve the schema faster.
Example:
{
"schema_file": {
"file_name": "employees_schema.json",
"relative_path": "source/employees_schema.json",
"file_type": "json",
"sha256": "REPLACE_WITH_FILE_HASH"
}
}The schema file does not need to match the final KDSAI internal contract exactly. It is input for schema proposal, review, and approval.
Example schema file content:
{
"dataset": "employees",
"columns": [
{
"name": "Employee no.",
"type": "string",
"required": true
},
{
"name": "First name",
"type": "string",
"required": true
},
{
"name": "Employment date",
"type": "date",
"required": false,
"formats": ["yyyy-MM-dd", "dd.MM.yyyy"]
}
]
}8. Schema Version and Approval Handling
8.1 Ownership model
The customer owns the declared schema version.
KDSAI owns schema approval and validation.
This means:
- The customer sends
schema.versionin every upload. - The customer increases
schema.versionwhenever the file structure changes. - KDSAI checks whether this
company_id + tenant_id + dataset + schema.versionis already approved internally. - If it is approved, KDSAI validates the file against the approved internal contract.
- If it is not approved yet, KDSAI treats it as a new schema version and routes it to schema profiling, review, and approval.
- KDSAI publishes the upload to standard ETL raw only after the schema version is approved and the data passes validation.
8.2 Decision table
| Customer upload | KDSAI behavior |
|---|---|
dataset=employees, schema.version=1.0.0, version already approved | Validate data against the approved internal contract and process if valid. |
dataset=employees, schema.version=1.1.0, version not known | Treat as a new schema version, profile/review/approve before ETL publication. |
Same schema.version as before, but file structure changed | Treat as schema drift and reject or quarantine. The customer should send a new upload with a new schema.version. |
Same schema.version and same structure, but invalid values | Treat as data validation error, not schema change. |
Same schema.version and same structure, corrected values | Treat as correction if the correction object is provided. |
8.3 Versioning rule
schema.version must represent the structure of the file, not the business date, export date, or upload sequence.
Good examples:
1.0.0 initial employees file structure
1.1.0 added optional middle_name column
2.0.0 renamed employee_number and changed primary key rulesBad examples:
2026-06-02 daily upload date used as schema version
001 upload sequence used as schema version
latest non-versioned alias9. Upload Scenarios
9.1 First upload of a new dataset
Use when KDSAI has not approved any schema version for this dataset yet.
Customer action:
- Use a new
upload_id. - Set
schema.version, usually to1.0.0. - Provide
schema.change_description. - Include
schema_filewhen available.
Manifest fragment:
{
"dataset": "employees",
"schema": {
"version": "1.0.0",
"previous_version": null,
"change_description": "Initial schema for the employees dataset."
},
"schema_file": {
"file_name": "employees_schema.json",
"relative_path": "source/employees_schema.json",
"file_type": "json"
}
}KDSAI profiles the file, proposes an internal contract, waits for approval if required, validates the data, and only then publishes accepted data to standard ETL raw.
9.2 Repeated upload with the same structure
Use when the dataset is already onboarded and the file structure has not changed.
Customer action:
- Use a new
upload_id. - Send the same
schema.versionas the approved structure. - Do not include
schema_fileunless requested by KDSAI. - Do not change
schema.versionfor ordinary daily, hourly, or repeated data uploads.
Manifest fragment:
{
"dataset": "employees",
"schema": {
"version": "1.0.0"
}
}KDSAI validates the file against the approved internal contract for this dataset and schema version. If validation passes, KDSAI publishes the accepted package to standard ETL raw.
9.3 Upload with a changed structure
Use when the dataset is the same business dataset, but the file structure changed.
Examples:
- a column was added,
- a column was removed,
- a column was renamed,
- a column type changed,
- date or decimal format changed,
- Excel sheet name changed,
- CSV delimiter or encoding changed.
Customer action:
- Upload to the same Fleet landing pattern for the dataset.
- Use a new
upload_id. - Increase
schema.version. - Include
schema.previous_versionif known. - Include
schema.change_description. - Include
schema_filewhen available.
Manifest fragment:
{
"dataset": "employees",
"schema": {
"version": "1.1.0",
"previous_version": "1.0.0",
"change_description": "Added Middle name column and changed Employment date format."
},
"schema_file": {
"file_name": "employees_schema_v1_1_0.json",
"relative_path": "source/employees_schema_v1_1_0.json",
"file_type": "json"
}
}KDSAI does not publish this upload to standard ETL raw until the new schema version is reviewed, approved, and validated.
9.4 Data correction without schema change
Use when the file structure is unchanged, but previous data values were wrong.
Examples:
- invalid dates were corrected,
- missing values were filled,
- wrong amounts were corrected,
- duplicate records were removed.
Customer action:
- Use a new
upload_id. - Use the same
schema.versionas the corrected upload. - Include
correction.is_correction=true. - Include
correction.correction_of_upload_id. - Do not increase
schema.versionunless the file structure also changed.
Manifest fragment:
{
"upload_id": "upl_20260611_001",
"dataset": "employees",
"schema": {
"version": "1.0.0"
},
"correction": {
"is_correction": true,
"correction_of_upload_id": "upl_20260603_001",
"correction_reason": "Corrected invalid employment date values."
}
}The correction metadata belongs in metadata/upload-manifest.json.
9.5 Accidental schema drift
Use when the customer sends the same schema.version, but the actual file structure is different from the approved structure.
Example:
Previous approved structure: employees schema.version=1.0.0
Incoming manifest: schema.version=1.0.0
Incoming file: contains an extra required column or renamed columnKDSAI treats this as schema drift. The upload is not processed as a normal data upload.
The customer should either:
- send a corrected file that matches the declared
schema.version, or - send a new upload with a new
schema.versionand a change description.
10. Upload Completion and Idempotency
The upload is complete only when metadata/upload-manifest.json exists.
Required upload order:
- Upload the source data file under
source/. - Upload the optional schema file under
source/if needed. - Upload
metadata/upload-manifest.jsonlast.
Idempotency rules:
upload_idmust be unique for the tenant.- The same
upload_idcannot be reused with different files. - Files inside an existing
upload_idpath must not be replaced. - A corrected file must be sent as a new upload.
- KDSAI may use
upload_id,dataset,received_at,schema.version, and file hash to detect duplicate or inconsistent uploads.
11. KDSAI Processing Behavior
After the manifest is uploaded, KDSAI performs the following checks:
- The manifest exists and is valid JSON.
company_id,tenant_id, anddatasetare present.- The manifest values match the assigned S3 prefix.
upload_idhas not been reused with different files.- Exactly one
data_fileis declared. - The declared source file exists.
- The file type is supported.
- Required parsing metadata is present for the file type.
schema.versionis present.- KDSAI checks whether the declared schema version is already approved internally.
- If the schema version is not approved yet, the upload is routed to schema profiling, review, and approval.
- If the schema version is approved, the file structure is validated against the approved internal contract.
- Data validation passes before publication.
KDSAI publishes data to standard ETL raw only after:
the schema version is approved
the source file structure matches the approved schema version
the source file data passes validation
the accepted package is ready for ETL processing12. Customer-Facing Status Expectation
The customer should consider the upload accepted only after KDSAI reports that the upload was validated and published to the standard ETL raw area.
Uploading files to Fleet landing does not mean that the data has been accepted into the warehouse.
Recommended customer-visible states are:
| State | Meaning |
|---|---|
Uploaded | Files and manifest were received in Fleet landing. |
Rejected | Manifest, file structure, schema version, or data validation failed. |
WaitingForSchemaApproval | A new schema version requires approval before processing. |
AcceptedForEtl | Data passed Fleet validation and was published to standard ETL raw. |
Loaded | Standard ETL loaded the data into the warehouse. |
The exact way of exposing these statuses can be implemented through portal, API, report file, or operational handover. It is not required for the customer-side upload process to query this status before every upload.
13. Key Rule
The customer uploads one source data file plus one manifest to Fleet landing.
The customer owns:
upload_id,dataset,- declared
schema.version, - source file content,
- correction reference when needed.
KDSAI owns:
- schema approval,
- internal approved contract registry,
- schema version validation,
- data validation,
- publication to standard ETL raw,
- loading into Redshift.