--- spec: agent-feature status: done owner: feature-pipeline-agent related-routes: files: - src/api/v2/projects/assettypes/systemtypemappings/asset.type.systemtype.mappings.routes.ts - src/api/v2/projects/assettypes/systemtypemappings/asset.type.systemtype.mappings.controller.ts - src/api/v2/projects/assettypes/systemtypemappings/asset.type.systemtype.mappings.validator.ts - src/services/asset.type.systemtype.mappings.service.ts - src/api/v2/projects/assettypes/systemtypemappings/asset.type.systemtype.mappings.routes.ts - src/api/v2/projects/assettypes/systemtypemappings/asset.type.systemtype.mappings.controller.ts - src/services/asset.type.systemtype.mappings.service.ts - src/api/v2/projects/assettypes/systemtypemappings/asset.type.systemtype.mappings.routes.ts - src/api/v2/projects/assettypes/systemtypemappings/asset.type.systemtype.mappings.controller.ts - src/services/asset.type.systemtype.mappings.service.ts - src/api/v2/projects/assettypes/systemtypemappings/asset.type.systemtype.mappings.routes.ts - src/api/v2/projects/assettypes/systemtypemappings/asset.type.systemtype.mappings.controller.ts - src/services/asset.type.systemtype.mappings.service.ts - src/services/asset.service.ts - src/models/egress.ts - src/services/asset.service.ts - src/models/egress.ts --- # agent-feature ## Goal Adds four API2 endpoints to manage AssetType↔SystemType mappings (create, delete, list, get-by-id) backed by the existing xyz.AssetTypeSystemTypeMapping table, and augments both Asset GET endpoints to include a scalar systemId field derived from the asset's AssetType→SystemType mapping (null when no mapping exists). No new tables are introduced — all target tables already exist. This is a modify feature entirely on API2 + Postgres. ## Behavior changes - POST /api/v2/projects/{projectId}/asset-types/system-type-mappings - DELETE /api/v2/projects/{projectId}/asset-types/system-type-mappings/{mappingId} - GET /api/v2/projects/{projectId}/asset-types/system-type-mappings/{mappingId} - GET /api/v2/projects/{projectId}/asset-types/system-type-mappings - GET /api/v2/projects/{projectId}/assets/{assetId} - GET /api/v2/projects/{projectId}/assets ## Acceptance criteria - [ ] The behavior described above is implemented on the listed files. - [ ] Existing behavior is unchanged when the new feature is not exercised. - [ ] Unit and (where observable) e2e tests cover the new behavior. ## Out of scope - Updating Asset write endpoints (POST/PUT/PATCH) to accept systemId. - Returning a nested SystemType object (only the scalar systemId is returned). - Bulk create/delete of mappings. - Cascade/blocking behavior when an AssetType or SystemType is deleted. ## Notes / open questions - Generated by the feature pipeline from the approved architect plan. If any acceptance criterion is ambiguous, ask the human before implementing. ## Decisions - **New router placement.** The `system-type-mappings` router is mounted at `/:projectId/asset-types/system-type-mappings` in `api.v2.routes.ts` *before* the `/:projectId/asset-types` router so the more specific mappings path is not swallowed by the asset-types `GET /:assetTypeId` route. - **`systemId` semantics.** The spec names the new Asset field `systemId` but describes it as being derived from the AssetType→SystemType mapping, which yields a *SystemType* id. Implemented literally: field name `systemId`, value = the `SystemTypeId` of the mapping for the asset's assetType (or null). Flagged as an open question for the reviewer. - **`systemId` is read-only and optional.** Added to the `Asset` interface as `systemId?: string | null`, populated only on the GET (list/get-by-id) paths. POST/PATCH responses are left byte-for-byte unchanged (regression safety and in line with the "write endpoints unchanged" out-of-scope note). - **Derivation query.** `assets.service` calls a new `getAssetTypeToSystemTypeMap(projectId)` helper (one query returning all project mappings) and looks up each asset's `assetTypeId`. Simple and avoids a per-asset query. - **DB layer.** Mappings service assumes the sibling naming convention for the existing table: `fn_GetAssetTypeSystemTypeMappingList`, `fn_GetAssetTypeSystemTypeMapping`, `fn_InsertAssetTypeSystemTypeMapping`, `usp_DeleteAssetTypeSystemTypeMapping`. No new tables (per spec). - **egress.ts.** Left untouched — Asset/mapping shapes follow the repo convention of living in their service files, not `models/egress.ts`. Noted as a deviation from the spec's `files:` list.