@dsptch-work/api-client 0.34.0 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,260 @@ All notable changes to `@dsptch-work/api-client` are documented here. The format
5
5
  [Semantic Versioning](https://semver.org) — currently `0.x`, so breaking changes may land in a
6
6
  minor bump until `1.0.0`. See [RELEASING.md](./RELEASING.md) for the release and versioning process.
7
7
 
8
+ ## [0.36.0] - 2026-10-13
9
+
10
+ ### Added
11
+
12
+ - New class `ProjectDocuments`: `listProjectDocuments()`, `createProjectDocument()`,
13
+ `getProjectDocument()`, `updateProjectDocument()`, `deleteProjectDocument()`, and
14
+ `listProjectDocumentVersions()`. `ProjectDocumentParameters` requires `file` and
15
+ `performed_by_user_id`; get the signed file id through `DirectUploads.createDirectUpload()`
16
+ with `DirectUploadParameters.resource: 'projects.documents'`. `ProjectDocumentUpdateParameters`
17
+ accepts an optional replacement file and nullable `filename` / `description`.
18
+ `ProjectDocumentResponseObject.file` is nullable and exposes download metadata and `url`.
19
+ `ProjectDocumentVersionResponseObject` records audit events (`'create' | 'update' | 'destroy'`),
20
+ actor, and timestamp. List methods support cursor pagination; documents also support created/updated
21
+ date filters. Grant the appropriate `projects.documents:read` / `:create` / `:update` / `:delete`
22
+ scopes and `projects.documents.versions:read` for history. Corresponding operation types and Zod
23
+ schemas are exported.
24
+ - `PayPeriods.getPayPeriod()` reads an individual period with `path: { id }` and the existing
25
+ `pay_periods:read` scope. New `PayPeriodResponseObject` and `zPayPeriodResponseObject` are shared
26
+ by show and list responses. `ListPayPeriodsData.query` adds
27
+ `'filter[timekeeping_pay_period_config_id]'` to select a pay schedule family; use the same id each
28
+ period returns as `timekeeping_pay_period_config_id`.
29
+ - `ListEmploymentsData.query` adds `'filter[companies_department_id]'`. It selects the department
30
+ in the employment version at now or the supplied `'as_of[valid]'` time, so historical queries
31
+ follow historical assignments.
32
+
33
+ ### Changed
34
+
35
+ - **Breaking:** `TimeEntryCreateParameters` is now a standalone object requiring
36
+ `timekeeping_time_card_id`, `start_time`, and `end_time` for
37
+ `TimeEntries.createTimeEntry()`. `TimeEntryUpdateParameters` keeps every field optional for
38
+ `updateTimeEntry()`. Both make `feature_ids` a nonnullable array; create's
39
+ `feature_allocation_acknowledged` and update's `confirm_allocation_conflict` accept booleans only.
40
+ Pass `[]` to clear feature allocations and omit the field to retain them on update. The generated
41
+ Zod schemas validate the split objects and required create timestamps; timestamp strings are
42
+ parsed by the server rather than restricted to Zod's ISO date-time format. Missing required
43
+ fields return `400`; wrong JSON types return `422` with field pointers, and unparseable timestamp
44
+ strings return `422 invalid_date`. Correct the values before retrying.
45
+ - **Breaking:** `Users.updateCompany()` and `removeUserFromCompany()` take
46
+ `path: { user_id, id }` rather than `path: { user_id, company_id }`.
47
+ Update `UpdateCompanyData` / `RemoveUserFromCompanyData` call sites and their path-schema inputs;
48
+ `id` still holds the company id, so the actual HTTP URL is unchanged.
49
+ - **Breaking:** `UserCompanyParameters.type` and `UserCompanyCreateParameters.type` are
50
+ `'EMPLOYEE' | 'CONTRACTOR'`, without `null`. Omit the value for the create default or to retain it
51
+ on update. `Users.createCompany()` / `updateCompany()` now reject wrong JSON types before saving:
52
+ send pay and benefit amounts as decimal strings, minute amounts as integers, and enrollment /
53
+ overtime flags as booleans. Creating requires a valid `hire_date`; on an administrative update,
54
+ null or blank `hire_date` still retains the employment start. Custom-field rows require nonblank
55
+ `custom_field_config_id` and string-or-null `value`; send a list of row objects, not an indexed
56
+ object. Malformed values return `422` with a field pointer; missing required fields return `400`.
57
+ - **Breaking:** `UserParameters.group_ids` no longer accepts `null`. `Users.createUser()`,
58
+ `Groups.addUsersToGroup()`, `TimeEntries.createTimeEntry()` / `updateTimeEntry()`,
59
+ `ComplianceChecks.updateCheck()`, and form-assignment writes require unique nonblank IDs in
60
+ their group, feature, and assignee arrays. Null, blank, duplicate, or wrong-typed members now
61
+ return `422` before any write. Omit optional replacement arrays to retain them on update or send
62
+ `[]` to clear them; `UserGroupParameters.user_ids` must contain at least one ID. Corresponding
63
+ Zod schemas validate nonblank members and the group-add minimum; uniqueness remains server-side.
64
+ - **Breaking:** `AssetsTransfers.createTransfer()` validates endpoint IDs and `line_items`
65
+ before moving stock. Supply at most one endpoint per side and at least one side; endpoint IDs
66
+ must be nonblank strings. Supply a nonempty array of rows with `assets_item_id` and integer
67
+ `quantity >= 1`; indexed row objects, fractional quantities, numeric strings, and unknown row
68
+ keys return `422` with pointers. Missing `line_items` or required row fields returns `400`.
69
+ `AssetsTransferParameters.from_assets_sub_location_id` / `to_assets_sub_location_id` now allow
70
+ `null` for unbinned stock, matching their generated Zod schemas.
71
+ - **Breaking:** `ApprenticeshipWageSchedules.createWageSchedule()` / `updateWageSchedule()` and
72
+ `ApprenticeshipWageSchedulePeriods.createPeriod()` / `updatePeriod()` validate JSON types,
73
+ nullable fields, units, and nonnegative period values before saving. Send `periods_attributes`
74
+ as an array of row objects. Missing required fields return `400`; malformed or unknown nested
75
+ fields return `422` with pointers. A period must retain at least one of `min_minutes`,
76
+ `max_minutes`, or `num_competencies`, including after clearing values. `UpdateWageScheduleErrors`
77
+ now declares `422: Problem`; `CreatePeriodErrors` now declares `404: Problem` for a missing or
78
+ inaccessible schedule.
79
+ - **Breaking:** `AssetsAttributes.createAttribute()` / `updateAttribute()`,
80
+ `Certifications.createCertification()` / `updateCertification()`,
81
+ `Projects.createProject()` / `updateProject()`, `ComplianceChecks.updateCheck()`, and
82
+ `Users.updateUser()` reject wrong JSON types and undeclared body fields before saving.
83
+ Supply nonblank required names, booleans for flags, and only declared keys; nested option-row
84
+ failures return `422` with a row pointer instead of `400`. The corresponding generated Zod
85
+ schemas validate nonblank names and IDs. Project date fields require real `YYYY-MM-DD` strings
86
+ or null; timestamps, loose dates, and empty strings return `422 validation_failed` with a pointer.
87
+ Send an IANA zone or null for `tz_name` and an integer `0`–`6` or null for `billing_start_day`.
88
+ `zUserUpdateParameters.birth_date` now validates
89
+ a `YYYY-MM-DD` calendar date or null; timestamps are not dates.
90
+ - **Breaking:** `Timecodes` writes validate documented flags as booleans and reject blank names,
91
+ malformed values, and undeclared fields before saving. The create, correction, scheduled-change,
92
+ and genesis Zod schemas accept temporal strings for server parsing rather than enforcing ISO
93
+ date-time syntax locally. Omit create's `effective_date` to use now; sending null now returns
94
+ `422 validation_failed` instead of defaulting. Unparseable strings return `422 invalid_date`.
95
+ `updateTimecode()`, `scheduleTimecodeChange()`, and `shiftTimecodeGenesis()` validate the body
96
+ before `If-Match`, so malformed requests can return `400` / `422` ahead of `428`. Preserve the
97
+ header for valid writes and correct body errors before retrying.
98
+ - **Breaking:** `UserCertifications.approveUserCertification()` requires a company key to name
99
+ a nonblank `UserCertificationApprovalParameters.approved_by_user_id`; a user key must omit it
100
+ and approves as itself. A company key's omitted approver is `400`; supplied null or malformed
101
+ values are `422` with `#/approved_by_user_id`, while a user key naming an approver is `403`.
102
+ Correct the body for the key type rather than retrying a refused actor.
103
+ - **Breaking:** `People.updateCustomField()` requires a nonempty `custom_fields` array.
104
+ Missing the list or either row field (`custom_field_config_id` / `value`) now returns
105
+ `400 parameter_missing`, and extra row keys return `422 validation_failed` with a row-field
106
+ pointer. Body validation precedes `If-Match`; keep the precondition header for valid batches.
107
+ - **Breaking:** `JobWageDeterminations` and `ProjectWageDeterminations` writes validate
108
+ subtype fields before saving. Send decimal-string cents, nonblank classifications and trade
109
+ IDs, and lowercase `construction_category` values. Required create-field omissions now return
110
+ `400 parameter_missing`; malformed values return `422 validation_failed` with exact pointers.
111
+ Federal create requests must omit `regional_fields`; even `{}` is refused. On edits,
112
+ scheduled changes, and genesis shifts, invalid calendar dates (`effective_from` /
113
+ `effective_date`) now return `validation_failed` instead of `invalid_date`, before `If-Match`
114
+ failures. Send real `YYYY-MM-DD` dates and handle `Problem.errors` before retrying.
115
+ - **Breaking:** manager and safety-manager user keys no longer receive selectable packages from
116
+ `PayRateRulePackages.listPayRateRulePackages()`. `getPayRateRulePackage()` and the corresponding
117
+ `PayRateRules.listPayRateRules()`, `getPayRateRule()`, and `listPayRateRuleHistory()` lookups return
118
+ `404`. Use an administrator user key for reusable recipe details. Administrator user keys,
119
+ company keys, and existing reads of hidden determination packages retain their access.
120
+
121
+ ### Removed
122
+
123
+ - **Breaking:** `TimeEntryParameters` and `zTimeEntryParameters` are removed. Use
124
+ `TimeEntryCreateParameters` / `zTimeEntryCreateParameters` for creates and
125
+ `TimeEntryUpdateParameters` / `zTimeEntryUpdateParameters` for edits.
126
+ - **Breaking:** `RegionalWageDeterminationFields` and `zRegionalWageDeterminationFields` are
127
+ removed. Regional write fields are inline in the owning create, update, or scheduled-change
128
+ type. Derive a reusable type with
129
+ `NonNullable<RegionalJobWageDeterminationParameters['regional_fields']>` or its project
130
+ counterpart. Categorized-fringe fields now allow null in the TypeScript and Zod shape; the
131
+ server still requires nonnull fringe values for regions that require them and rejects fields
132
+ the region does not support.
133
+
134
+ ### Fixed
135
+
136
+ - `TimecodeScheduledChangeParameters.name` is optional. `Timecodes.scheduleTimecodeChange()`
137
+ can change flags or another attribute without resending the name; only `effective_date` is
138
+ required. `zTimecodeScheduledChangeParameters` matches this accepted partial write.
139
+ - `ApprenticeshipWageScheduleParameters.periods_attributes` makes `period_number`, `wage_percent`,
140
+ and `wage_cents` optional in nested rows, including edits or removals of existing periods.
141
+ Standalone `ApprenticeshipWageSchedulePeriods.createPeriod()` still requires all three.
142
+ `ApprenticeshipWageScheduleUpdateParameters.periods_attributes` and
143
+ its Zod schema now use simple row objects, so partial edits need not repeat a progression
144
+ threshold. The server validates the resulting period rather than just the supplied fields.
145
+ - `ProjectParameters.budget` and `ProjectUpdateParameters.budget` allow null, including through
146
+ their generated Zod schemas. Send null to clear a budget, a decimal string to set it, or omit
147
+ it on update to retain it.
148
+ - `FederalJobWageDeterminationParameters` and `FederalProjectWageDeterminationParameters`
149
+ expose optional nullable `overtime_package_id`. `RegionalJobWageDeterminationParameters` and
150
+ `RegionalProjectWageDeterminationParameters` expose optional nullable `class_code` and
151
+ `construction_category`. Corresponding create Zod schemas retain those fields instead of
152
+ stripping them. Regional `class_code` / `construction_category` remain ignored by the server,
153
+ and Federal creates still refuse a non-null overtime package; these are schema corrections.
154
+ Method names and response types are unchanged.
155
+ - `zComplianceCheckParameters.time_due` accepts a string or null instead of requiring ISO
156
+ date-time syntax. The server parses supplied dates and returns a validation problem for
157
+ malformed input; consumers using the schema can submit the server's accepted date forms.
158
+ - `AssetsProducts` writes with an out-of-range `default_minimum_quantity` and
159
+ `ProductionCompletions` writes with an out-of-range `quantity_completed` now return
160
+ `422 validation_failed` instead of `500 internal_error`. These range problems have no field
161
+ `errors` array; correct the number rather than retrying a server failure.
162
+
163
+ See the [API changelog](https://dsptch.app/support/docs/developers/api-changelog#2026-10-13) for the
164
+ complete REST contract details and error behavior.
165
+
166
+ ## [0.35.0] - 2026-10-12
167
+
168
+ ### Added
169
+
170
+ - `CompetencyCriterionParameters` adds optional nullable `assessment_method` for
171
+ `CompetenciesCriteria.createCriterion()` / `updateCriterion()`.
172
+ `CompetencyCriterionResponseObject` adds the required nullable field on reads, writes, and
173
+ `moveCompetencyCriterion()`. Its union is `'direct_observation' | 'simulation' |
174
+ 'oral_questioning' | 'written_questioning' | 'products_of_work' | 'recognized_prior_learning' |
175
+ 'witness_testimony' | 'other' | null`; the corresponding Zod schemas include it. Add the key to
176
+ typed response fixtures. Available to companies with Competencies enabled; the method is a
177
+ suggestion, and criteria writes still require a draft revision.
178
+
179
+ ### Changed
180
+
181
+ - **Breaking:** `ProductionCompletionParameters` is one object rather than a union of feature and
182
+ quantity request types. `ProductionCompletions.createCompletion()` still requires
183
+ `production_job_scope_price_id` and `performed_by_user_id`; its optional `completable_attributes`
184
+ exposes both `feature_id` and `quantity_completed`. The job decides which field to send.
185
+ `zProductionCompletionParameters` now validates this object instead of the ambiguous `oneOf`.
186
+ Both create and update Zod schemas validate a supplied `quantity_completed` as an integer of at
187
+ least `1`, and validate nonblank create scope-price and feature ids.
188
+ - **Breaking:** `ProductionCompletions.createCompletion()` rejects null or malformed `work_date`
189
+ with `422 validation_failed` instead of using today; omit the key for today's date in the job's
190
+ time zone. Create and update also reject coerced quantities, non-string notes, and malformed
191
+ `completable_attributes`. Subtype failures now carry a pointer for each refused field in
192
+ `Problem.errors`; updating `completable_attributes.feature_id` returns `validation_failed` instead
193
+ of `subtype_foreign_keys`. Correct malformed values rather than retrying them.
194
+ - **Breaking:** `AssetsCategories.createCategory()` / `updateCategory()`,
195
+ `AssetsItems.createItem()` / `updateItem()` / `createServiceEvent()` / `updateServiceEvent()`, and
196
+ `AssetsProducts.createProduct()` / `updateProduct()` validate documented JSON types before saving.
197
+ Supply arrays for `category_attributes`, `attribute_values`, `images_attributes`, and
198
+ `attachments_attributes`; lone and index-keyed objects now return `422`. Unknown nested row
199
+ fields return `422` with a field pointer instead of `400`. Attribute values must be string or
200
+ null, with a nonblank `assets_attribute_id`; missing attribute ids now return `400`, and blank
201
+ ids `422`. Create without a required item/product name, item product id, service date, or category
202
+ name now returns `400` rather than model `422`. Corresponding Zod schemas validate nonblank names,
203
+ attribute ids, and supplied attachment signed ids. The server refuses undeclared keys.
204
+ - **Breaking:** `AssetsItems.updateItem()` refuses serial-only fields on bulk items with
205
+ `422 subtype_foreign_keys` and a pointer per field instead of succeeding and silently dropping
206
+ them. Omit `serial_number`, `status`, `purchase_date`, `purchase_price_cents`, `external_id`, and
207
+ `external_system_url` when updating bulk inventory.
208
+ - **Breaking:** `PayRateRules.shiftPayRateRuleGenesis()` / `schedulePayRateRuleTermination()` return
209
+ `422 validation_failed` with `#/effective_date` for invalid dates instead of `422 invalid_date`.
210
+ Missing dates still return `400 parameter_missing`, now with the same pointer. Handle field
211
+ validation before retrying with `If-Match`; valid requests and method signatures are unchanged.
212
+ - **Breaking:** `PayRateRules.createPayRateRule()`, `updatePayRateRule()`,
213
+ `schedulePayRateRuleChange()`, `JobWageDeterminationRateRules.createRateRule()`, and
214
+ `ProjectWageDeterminationRateRules.createProjectWageDeterminationRateRule()` validate recipes
215
+ before saving. In `PayRatesRuleParameters`, `PayRatesRuleUpdateParameters`,
216
+ `PayRatesRuleScheduledChangeParameters`, and `RateRuleParameters`, send string `effect.amount_cents`,
217
+ integer days (`0`–`6`, nonempty), zero-padded `HH:MM` times, integer apprentice periods (`1`–`100`),
218
+ integer apprentice-hour bounds (`0`–`100000`), and string overtime multipliers (`'1.5' | '2.0'`).
219
+ Send only fields for the condition's `type`; wrong-kind or unknown nested fields now return
220
+ `422` with an exact pointer, and missing required recipe fields return `400` instead of model
221
+ `422`. The corresponding generated Zod schemas validate the new bounds and time pattern.
222
+ Valid recipe shapes and generated method names are unchanged.
223
+ - **Breaking:** malformed `effective_date` / `effective_from` on those five recipe writes returns
224
+ `422 validation_failed` with a field pointer instead of `invalid_date`.
225
+ `PayRateRules.updatePayRateRule()` and `schedulePayRateRuleChange()` validate the body before
226
+ `If-Match`, so an invalid recipe with no header now returns `400` / `422` instead of `428`.
227
+ Preserve the existing header for valid writes; omitting recipe halves on edits still retains them.
228
+
229
+ ### Removed
230
+
231
+ - **Breaking:** `ProductionCompletionBaseParameters`, `ProductionFeatureCompletionParameters`,
232
+ `ProductionQuantityCompletionParameters`, `zProductionCompletionBaseParameters`,
233
+ `zProductionFeatureCompletionParameters`, and `zProductionQuantityCompletionParameters` are removed. Use
234
+ `ProductionCompletionParameters` and `zProductionCompletionParameters` for create payloads.
235
+ - **Breaking:** `AssetsAttachmentParameters` and `zAssetsAttachmentParameters` are removed.
236
+ Image and attachment rows are inline in their owning request types. Derive a row type from the
237
+ relevant field, for example
238
+ `NonNullable<AssetsItemParameters['images_attributes']>[number]`.
239
+
240
+ ### Fixed
241
+
242
+ - `AssetsCategoryParameters` and `AssetsCategoryUpdateParameters` make each `category_attributes`
243
+ row's `assets_attribute_id` and `fillable_on` optional, matching accepted requests. Their Zod
244
+ schemas no longer require these fields; the server still skips a row without an attribute id.
245
+ - `AssetsItemParameters.serial_number` is optional and nullable. Item create/update types and Zod
246
+ schemas also allow null for `description`, `purchase_date`, `purchase_price_cents`, `external_id`,
247
+ and `external_system_url`; the update type allows null for `serial_number` as well. Create
248
+ placement ids (`assets_site_id`, `user_id`, `container_item_id`, `assets_sub_location_id`) are
249
+ nullable. `zAssetsItemParameters` / `zAssetsItemUpdateParameters` treat `purchase_date` as a nullable
250
+ string rather than requiring a date-time. These match input the server already accepted.
251
+
252
+ ### Security
253
+
254
+ - Asset image and service-attachment writes check the upload behind every accepted row. Supply a
255
+ signed id registered for the owning resource (`assets.items`, `assets.products`, or
256
+ `assets.items.service_events`); a signed id for another resource or company returns
257
+ `422 invalid_signed_id`. Index-keyed row objects are now refused under the array contract above.
258
+
259
+ See the [API changelog](https://dsptch.app/support/docs/developers/api-changelog#2026-10-12) for the
260
+ complete REST contract details.
261
+
8
262
  ## [0.34.0] - 2026-10-09
9
263
 
10
264
  ### Added