feat(api-spec): implement PATCH and PUT API specifications for occupations#504
Conversation
There was a problem hiding this comment.
Pull request overview
Implements the missing PUT and PATCH operation API specifications for Occupation instance endpoints (/esco/occupation/{id}), including AJV request/response schemas, error-code enums/constants, type wiring, and schema validation tests/snapshots. It also expands test coverage for related Occupation sub-resources (parent + skills) and introduces a shared constant for code-pattern max lengths.
Changes:
- Add
PUT/PATCHoperation modules underapi-specifications/src/esco/occupation/[id]/(schemas, types, errors, constants, and index wiring). - Introduce
CODE_PATTERN_MAX_LENGTHand apply it to occupation code/group-code validation across request schemas and snapshots. - Add/expand schema tests and snapshots for Occupation skills and parent sub-resources.
Reviewed changes
Copilot reviewed 30 out of 30 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| api-specifications/src/esco/occupation/POST/schema.request.ts | Uses shared max-length constant for code/group-code pattern validation. |
| api-specifications/src/esco/occupation/[id]/skills/POST/schema.response.test.ts | Adds response schema tests for occupation→skills POST payload shape. |
| api-specifications/src/esco/occupation/[id]/skills/POST/schema.request.test.ts | Adds request schema tests for occupation→skills POST payload validation. |
| api-specifications/src/esco/occupation/[id]/skills/snapshots/index.test.ts.snap | Snapshot update to include the new constant export. |
| api-specifications/src/esco/occupation/[id]/PUT/schema.response.ts | Adds PUT response schema (base response schema + $id). |
| api-specifications/src/esco/occupation/[id]/PUT/schema.response.test.ts | Adds PUT response schema validation tests. |
| api-specifications/src/esco/occupation/[id]/PUT/schema.request.ts | Adds PUT request schema with conditional code/group-code validation by occupationType. |
| api-specifications/src/esco/occupation/[id]/PUT/schema.request.test.ts | Adds PUT request schema validation tests. |
| api-specifications/src/esco/occupation/[id]/PUT/index.ts | Exposes PUT operation (Schemas/Types/Errors/Constants/Enums). |
| api-specifications/src/esco/occupation/[id]/PUT/index.test.ts | Verifies PUT operation module exports. |
| api-specifications/src/esco/occupation/[id]/PUT/enums.ts | Defines PUT-specific error code enums by status. |
| api-specifications/src/esco/occupation/[id]/PUT/constants.ts | Defines PUT-specific payload sizing constants. |
| api-specifications/src/esco/occupation/[id]/PATCH/schema.response.ts | Adds PATCH response schema (base response schema + $id). |
| api-specifications/src/esco/occupation/[id]/PATCH/schema.response.test.ts | Adds PATCH response schema validation tests. |
| api-specifications/src/esco/occupation/[id]/PATCH/schema.request.ts | Adds PATCH request schema with conditional code/group-code validation by occupationType. |
| api-specifications/src/esco/occupation/[id]/PATCH/schema.request.test.ts | Adds PATCH request schema validation tests (including empty payload). |
| api-specifications/src/esco/occupation/[id]/PATCH/index.ts | Exposes PATCH operation (Schemas/Types/Errors/Constants/Enums). |
| api-specifications/src/esco/occupation/[id]/PATCH/index.test.ts | Verifies PATCH operation module exports. |
| api-specifications/src/esco/occupation/[id]/PATCH/enums.ts | Defines PATCH-specific error code enums by status. |
| api-specifications/src/esco/occupation/[id]/PATCH/constants.ts | Defines PATCH-specific payload sizing constants. |
| api-specifications/src/esco/occupation/[id]/parent/POST/schema.response.test.ts | Adds response schema tests for occupation→parent POST. |
| api-specifications/src/esco/occupation/[id]/parent/POST/schema.request.test.ts | Adds request schema tests for occupation→parent POST. |
| api-specifications/src/esco/occupation/[id]/parent/snapshots/index.test.ts.snap | Snapshot update to include the new constant export. |
| api-specifications/src/esco/occupation/[id]/index.ts | Wires PUT and PATCH into the occupation instance API aggregator. |
| api-specifications/src/esco/occupation/[id]/children/snapshots/index.test.ts.snap | Snapshot update to include the new constant export. |
| api-specifications/src/esco/occupation/[id]/snapshots/index.test.ts.snap | Snapshot update to include PUT/PATCH modules and the new constant export. |
| api-specifications/src/esco/occupation/_shared/types.ts | Adds Detail.PUT and Detail.PATCH request/response payload type aliases. |
| api-specifications/src/esco/occupation/_shared/constants.ts | Introduces CODE_PATTERN_MAX_LENGTH. |
| api-specifications/src/esco/occupation/snapshots/index.test.ts.snap | Snapshot update to include PUT/PATCH modules and the new constant export. |
| api-specifications/src/error/types.ts | Extends global error-code unions to include occupation PUT/PATCH error codes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| occupationGroupCode: { | ||
| type: "string", | ||
| maxLength: OccupationConstants.CODE_PATTERN_MAX_LENGTH, | ||
| pattern: OccupationRegexes.Str.LOCAL_GROUP_CODE, | ||
| }, |
| occupationGroupCode: { | ||
| type: "string", | ||
| maxLength: OccupationConstants.CODE_PATTERN_MAX_LENGTH, | ||
| pattern: OccupationRegexes.Str.LOCAL_GROUP_CODE, | ||
| }, |
| if: { | ||
| properties: { | ||
| occupationType: { const: OccupationEnums.OccupationType.ESCOOccupation }, | ||
| }, | ||
| }, |
| else: { | ||
| properties: { | ||
| code: { | ||
| type: "string", | ||
| maxLength: OccupationConstants.CODE_PATTERN_MAX_LENGTH, | ||
| pattern: OccupationRegexes.Str.ESCO_LOCAL_OR_LOCAL_OCCUPATION_CODE, | ||
| }, | ||
| occupationGroupCode: { | ||
| type: "string", | ||
| maxLength: OccupationConstants.CODE_PATTERN_MAX_LENGTH, | ||
| pattern: OccupationRegexes.Str.LOCAL_GROUP_CODE, | ||
| }, | ||
| }, | ||
| }, |
|
@irumvanselme and @rav3n11 we are accidentaly not accessing our slack account we were using when contributing to this repository, sorry for the delay and please be patient until we resolve the issue |
| if (!mongoose.Types.ObjectId.isValid(id)) return null; | ||
| const doc = await this.Model.findOne({ _id: id, modelId: modelId }).exec(); | ||
| if (!doc) return null; | ||
| doc.set(spec); |
There was a problem hiding this comment.
Bug: The update() and patch() methods use a string modelId in a query where an ObjectId is expected, causing all update operations to fail.
Severity: CRITICAL
Suggested Fix
Explicitly convert the modelId string parameter to a Mongoose ObjectId before using it in the findOne query. Create a new ObjectId like so: const modelIdObj = new mongoose.Types.ObjectId(modelId); and use modelIdObj in the query filter. This aligns with the pattern used in other methods within the same repository file.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: backend/src/esco/occupations/repository/occupation.repository.ts#L604
Potential issue: In the `update()` and `patch()` methods of the occupation repository,
the `findOne()` query uses a string `modelId` to filter against a schema field defined
as `mongoose.Schema.Types.ObjectId`. Other methods in the same repository explicitly
cast the `modelId` to an `ObjectId` before querying, indicating that automatic casting
is not relied upon in this codebase. This type mismatch will cause the query to fail to
find any documents, resulting in all PUT and PATCH requests failing with a 404 Not Found
error, even for valid and existing occupations.
Also affects:
backend/src/esco/occupations/repository/occupation.repository.ts:623~623
a9bcef7 to
a928a29
Compare
…tions with associated schema validations and tests
…codes and update validation tests
…ding modelId checks and error handling
a928a29 to
762dae7
Compare
| ? ObjectTypes.ESCOOccupation | ||
| : ObjectTypes.LocalOccupation, | ||
| modelId: payload.modelId, | ||
| UUIDHistory: payload.UUIDHistory, | ||
| occupationGroupCode: payload.occupationGroupCode, | ||
| definition: payload.definition, | ||
| scopeNote: payload.scopeNote, |
There was a problem hiding this comment.
Bug: The PUT/PATCH endpoints allow clients to submit an arbitrary UUIDHistory, which is not validated against actual historical data, potentially corrupting the version history.
Severity: MEDIUM
Suggested Fix
The server should validate the incoming UUIDHistory in PUT/PATCH requests. Before updating, the server could fetch the existing document and ensure the new history is a logical extension of the old one, or implement a server-managed history update similar to the CREATE operation, where the server controls the addition of new UUIDs to the history.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: backend/src/esco/occupations/[id]/PUT/index.ts#L128-L134
Potential issue: The PUT and PATCH endpoints for occupations allow a client to provide a
`UUIDHistory` array in the request payload. This array is saved directly without
server-side validation to ensure the UUIDs correspond to actual previous versions of the
occupation. A client could submit fabricated UUIDs, leading to semantic data corruption.
This would cause functions like `getHistory()` to return an inaccurate or incomplete
version history for the occupation model.
… history references and clean up redundant IDs.
762dae7 to
f8d4c9a
Compare
This pull request contains