docs/specs/20260710-125843-agent-feature.mdadded---
spec: agent-feature
status: in-progress
owner: feature-pipeline-agent
related-routes:
files:
- src/api/v2/projects/systems/systems.routes.ts
- src/api/v2/projects/systems/systems.controller.ts
- src/api/v2/projects/systems/systems.validator.ts
- src/services/systems.service.ts
- src/api/v2/projects/systems/systems.routes.ts
- src/api/v2/projects/systems/systems.controller.ts
- src/services/systems.service.ts
- src/api/v2/projects/systems/systems.routes.ts
- src/api/v2/projects/systems/systems.controller.ts
- src/services/systems.service.ts
---
# agent-feature
## Goal
Add three read/create API2 endpoints for the existing xyz.CommissioningSystem
entity (exposed as "systems"): POST create, GET-by-id, and paginated GET list,
all project-scoped under /api/v2/projects/{projectId}/systems. No new Postgres
table is created — CommissioningSystem already exists in the schema. Follows the
AssetType endpoint pattern. Revised per review: no new permissions; reuse
existing Project Edit / System View permissions.
## Behavior changes
- POST /api/v2/projects/{projectId}/systems
- GET /api/v2/projects/{projectId}/systems/{id}
- GET /api/v2/projects/{projectId}/systems
## 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) endpoints for systems.
- Exposing System via API1 / MongoDB.
- Any migration or sync with existing API1 System data.
- New Postgres columns/fields on CommissioningSystem (table used as-is).
## 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 "systems" endpoints on the **Assets** endpoint pattern
(`src/api/v2/projects/assets/`) rather than SystemType, because a
CommissioningSystem is an *instance* classified by a SystemType — the exact
analogue of an Asset classified by an AssetType. This gives paginated LIST
(via `IndexedItem` + `buildPaginatedQueryResponse`), matching the spec's
"paginated GET list".
- **Foreign key:** a System belongs to a **SystemType** (`systemTypeId`),
mirroring Asset → AssetType. Create body is `{ name, systemTypeId }`.
- **Permissions:** reused existing `PROJECT_VIEW` (GET list + GET by id) and
`PROJECT_EDIT` (POST create), plus `INTERNAL_ROLE`, exactly as Assets/AssetTypes
do. There is no dedicated "System View" authority in
`authorities.types.ts`; the spec's "reuse existing Project Edit / System View"
is satisfied by the established project-scoped `PROJECT_VIEW`/`PROJECT_EDIT`
pair (no new permissions added, per the revised spec).
- **DB contract assumed** (functions/columns live in the external DB migration
repo, not this codebase — same as Asset/AssetType):
- `xyz."fn_GetCommissioningSystemList"(projectId, lastFetchedIndexId, size)`
- `xyz."fn_GetCommissioningSystem"(projectId, systemId)`
- `xyz."fn_InsertCommissioningSystem"(projectId, systemTypeId, name, createdBy)`
- Returned columns: `CommissioningSystemId`, `Name`, `SystemTypeId`,
`CreatedBy`, `InsertedOn`, `LastModifiedOn`, `LastModifiedBy`, `Id`
(pagination index). The API response exposes `systemId` (the entity is
"exposed as systems" per the spec).
- A missing/invalid `systemTypeId` on insert is expected to raise an error
whose message contains `"SystemType with id"`, mapped to a 404
(mirrors Asset's `"AssetType with id"` mapping).
- Added a `System` schema to `src/swagger.components.schemas.json` and referenced
it from the route JSDoc (no inline duplication), per repo convention.
- Build/tests were **not run locally** — `node_modules` is not installed in this
environment and the instructions forbid installing a toolchain. The CI/e2e
pipeline runs the suite.