# TASK 2.1: Extend credential payload storage, mapping, and binding models with custom headers

## Summary

Implement the payload-model, encryption-envelope, admin mapping, and runtime binding changes required to carry custom headers from the admin API into the repository-backed Brink credential binding.

This is the core data-contract task for the slice.

## Dependencies

- [TASK 1.1](./TASK1.1.md)
- [TASK 1.2](./TASK1.2.md)

## Files to Modify

### 1. Admin API contract and validation

- `backend/Kds.Ai.ApiService/Endpoints/AdminCustomerEndpoints.cs`

### 2. Customer credential create/update/read service

- `backend/Kds.Ai.ApiService/Services/CustomerManagementService.cs`
- `backend/Kds.Ai.ApiService/Services/CustomerEtlProvisioningService.cs` if payload reads need no-op compatibility verification

### 3. Encrypted credential payload model

- `backend/Kds.Ai.Data/Credentials/BrinkPosCredentialPayload.cs`
- `backend/Kds.Ai.Data/Credentials/CustomerCredentialEnvelopeFactory.cs`

### 4. Runtime binding path

- `backend/Kds.Ai.Integrations/BrinkPos/IBrinkCredentialReadService.cs`
- `backend/Kds.Ai.Integrations/BrinkPos/CustomerCredentialBackedBrinkCredentialReadService.cs`
- `backend/Kds.Ai.Integrations/BrinkPos/RepositoryBackedBrinkConnectionBindingService.cs`
- `backend/integrations/Kds.Ai.Integrations.BrinkPos/Models/BrinkConnectionDefinition.cs`

## Required Changes

### Payload model

- add `customHeaders` to `BrinkPosCredentialPayload`,
- choose a deterministic in-memory type such as `IReadOnlyDictionary<string, string>` or `Dictionary<string, string>` based on serializer and update-flow needs,
- keep backward compatibility for already stored payloads that do not contain the field.

### Admin request/response models

- extend `BrinkPosCredentialPayloadRequest` and `BrinkPosCredentialPayloadResponse`,
- validate `customHeaders` according to the locked rules,
- return redacted values in read responses,
- keep existing `accessToken` and `locationToken` behavior unchanged.

### Update merge semantics

- extend `ResolveCredentialCommand` so existing stored custom header values can be preserved on update,
- use case-insensitive key matching for preservation logic,
- keep full replacement semantics for the header set unless a narrower patch contract already exists.

### Runtime binding

- extend `BrinkCredentialBinding` and `BrinkConnectionDefinition` with custom headers,
- map stored payload headers through `CustomerCredentialBackedBrinkCredentialReadService`,
- keep the repository-backed resolution priority unchanged.

## Acceptance Criteria

- [ ] New payloads can persist custom headers in the encrypted envelope
- [ ] Existing payloads without `customHeaders` still deserialize successfully
- [ ] Admin read models redact all custom header values
- [ ] Update flows preserve existing secret header values when `[REDACTED]` is sent for matching headers
- [ ] Runtime binding models expose custom headers to the integration layer

## Notes

- Keep the data shape minimal and close to existing records.
- Avoid introducing a new credential-envelope versioning framework unless the current shape truly requires it.
