docs/specs/20260709-122902-agent-feature.mdadded---
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.