--- spec: agent-feature status: done owner: feature-pipeline-agent related-routes: files: - routes - controller - validator - service - routes - controller - service - routes - controller - service --- # agent-feature ## Goal Add three read/create REST endpoints in API2 for the existing xyz.Asset table: POST create, GET single, and GET list (cursor-paginated), all scoped under /api/v2/projects/:projectId/assets and gated on project membership. No new tables are introduced — Asset already exists in the schema. Work is API2 + Postgres (new procs/functions only). ## Behavior changes - POST /api/v2/projects/{projectId}/assets - 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 - Update (PUT/PATCH) and Delete (DELETE) asset endpoints. - Role-differentiated permissions — all project members have equal access in v1. - Cross-project asset queries. - Any changes to the xyz.Asset table schema (columns/constraints) — the table already exists and is used as-is. - AssetType creation/management endpoints (assetTypeId is expected to already exist). ## 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 - Modelled the API2 surface directly on the committed AssetType CR endpoints (PAPI-3523), which are the closest sibling (project-scoped, cursor-paginated, FK-gated create). Kept naming/structure identical for reviewer familiarity. - Asset shape: `assetId`, `name`, `assetTypeId` (FK), `createdBy`, `insertedOn`, `lastModifiedOn`, `lastModifiedBy`. POST body is `{ name, assetTypeId }`. `assetTypeId` plays the same role `commissioningWorkflowId` plays for AssetType: it must already exist, and a missing FK surfaces as `NotFoundError` (mapped from a DB error message containing `AssetType with id`). - DB access follows the established convention of calling Postgres functions `xyz."fn_GetAssetList"`, `xyz."fn_GetAsset"`, `xyz."fn_InsertAsset"`. These procs are owned by the DB migration source (not this repo — confirmed the AssetType fns are likewise absent here), so they are not created in this change. - Authorisation: list/get gated on `PROJECT_VIEW`, create on `PROJECT_EDIT` (plus `INTERNAL_ROLE`), matching every project-scoped sibling. Per spec, all members have equal access — no role differentiation. - Could not run `tsc`/lint/tests: `node_modules` is not installed in this environment and the task brief says not to install a toolchain. The pipeline runs the suite afterward.