node-autotask 0.30.0 → 0.32.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 +39 -0
- package/MCP_TOOL_CATALOG.json +6 -6
- package/MCP_TOOL_MANIFEST.md +26 -28
- package/MCP_TOOL_OVERRIDES.json +0 -12
- package/N8N_MCP_MANIFEST.json +8 -8
- package/N8N_MCP_MANIFEST.md +8 -8
- package/README.md +7 -5
- package/capabilities.json +1473 -1449
- package/dist/capabilities.cjs +2 -2
- package/dist/capabilities.js +1 -1
- package/dist/{chunk-EDVSWL32.cjs → chunk-DCTHO7CQ.cjs} +1472 -1448
- package/dist/{chunk-RS7QMPRO.cjs → chunk-FTF2FEQ6.cjs} +526 -490
- package/dist/{chunk-P4PC32RJ.js → chunk-FVHPN7ZR.js} +61 -25
- package/dist/{chunk-LLIB4JGK.cjs → chunk-IKPFR6K2.cjs} +6 -6
- package/dist/{chunk-TZC4ZAA6.js → chunk-M2EGFPGF.js} +1472 -1448
- package/dist/{chunk-L4TDVUJM.cjs → chunk-QCB4LYKD.cjs} +143 -143
- package/dist/{chunk-QQPCJT2L.js → chunk-R6HLJCI2.js} +3 -3
- package/dist/{chunk-2ETR5GSO.js → chunk-T6EDJRLT.js} +2 -2
- package/dist/{index-B9VNv-EP.d.cts → index-Cw4aNNMo.d.ts} +65 -14
- package/dist/{index-DkpaFqyu.d.ts → index-OkbCWcef.d.cts} +65 -14
- package/dist/{index-CJ36PwRG.d.cts → index-m-7fOwFl.d.cts} +1 -1
- package/dist/{index-CJ36PwRG.d.ts → index-m-7fOwFl.d.ts} +1 -1
- package/dist/index.cjs +22 -22
- package/dist/index.d.cts +52 -5
- package/dist/index.d.ts +52 -5
- package/dist/index.js +4 -4
- package/dist/operations/index.cjs +112 -112
- package/dist/operations/index.d.cts +4 -4
- package/dist/operations/index.d.ts +4 -4
- package/dist/operations/index.js +2 -2
- package/dist/pool.cjs +9 -9
- package/dist/pool.d.cts +2 -2
- package/dist/pool.d.ts +2 -2
- package/dist/pool.js +4 -4
- package/dist/resources/index.cjs +4 -4
- package/dist/resources/index.d.cts +2 -2
- package/dist/resources/index.d.ts +2 -2
- package/dist/resources/index.js +3 -3
- package/dist/types/index.d.cts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/docs/API.md +61 -36
- package/package.json +1 -1
package/docs/API.md
CHANGED
|
@@ -300,7 +300,7 @@ drift payloads (the `operations.recovery` `candidateIds` refusal, the #13
|
|
|
300
300
|
shape-drift marker info). A non-pinned surface gets no `details` at all
|
|
301
301
|
(no speculation). On the MCP tools' served error payload, `details` is
|
|
302
302
|
passed through verbatim (live-verified 2026-10-04: the W-D3 pointer note
|
|
303
|
-
rides a real `time_entries.getPosted` vendor 500 on the wire) and the
|
|
303
|
+
rides a real `time_entries.getPosted` vendor 500 on the wire; that 500 is gone since 0.32.0, the pointer-note mechanism is unchanged) and the
|
|
304
304
|
deep-redacted `vendorError` body rides under a fixed key (issue #33: the
|
|
305
305
|
vendor's own field-level failure text — what separates a deterministic
|
|
306
306
|
zone wall from a transient outage) — a tool caller sees the same typed
|
|
@@ -2162,8 +2162,8 @@ so the answer to "why is this empty?" is data, not speculation:
|
|
|
2162
2162
|
field" — 2026-10-06; creates succeeded 2026-10-21, pair not recorded); `authenticate.get` W2:
|
|
2163
2163
|
designator-only;
|
|
2164
2164
|
`time_entries.getPosted` / `time_entries.getUnposted` W-D3: this zone's
|
|
2165
|
-
TimeEntry entity
|
|
2166
|
-
|
|
2165
|
+
TimeEntry entity has no `postedDate` — the ops derive posted state from the
|
|
2166
|
+
`billing_items.timeEntryID` join instead (§11.13) — NO `emptyReason` on any pointer
|
|
2167
2167
|
row, by design: a false reason would be worse than none).
|
|
2168
2168
|
- **the closed kind set** — `EmptyReasonKind`
|
|
2169
2169
|
(`'not-found' | 'blind-surface' | 'tenant-empty-for-user' |
|
|
@@ -2305,30 +2305,50 @@ clause that stops this fact from being lost a second time. The create op's
|
|
|
2305
2305
|
registry record carries the same typed block as `metadata.createRequirements`
|
|
2306
2306
|
(the `autotask_describe` channel).
|
|
2307
2307
|
|
|
2308
|
-
### 11.13
|
|
2309
|
-
|
|
2310
|
-
- **W-D3 (live, ww29, 2026-10-
|
|
2311
|
-
|
|
2312
|
-
`
|
|
2313
|
-
`
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2308
|
+
### 11.13 Posted state from billing items (W-D3), `getPosted` / `getUnposted` / `postedWithin`, and drifted-create marker recovery (issues #10/#13/#237)
|
|
2309
|
+
|
|
2310
|
+
- **W-D3 (live, ww29, re-verified 2026-10-27)** — this zone's TimeEntry entity
|
|
2311
|
+
has **no posted-state field**: time-entry reads carry no `postedDate` /
|
|
2312
|
+
`postedOnTime` key, and `postedDate exist` / `notExist` filters fail with
|
|
2313
|
+
`SERVER_ERROR: Unable to find postedDate in the TimeEntry Entity` (earlier
|
|
2314
|
+
2026-10-04 oracle: `postingStatus` and `status` are rejected too; only
|
|
2315
|
+
`dateWorked` / `resourceID` / `ticketID` / `taskID` resolve as filter
|
|
2316
|
+
fields). `billingApprovalDateTime` exists on the entity but is not
|
|
2317
|
+
populated on this tenant, so it cannot gate posted state. Earlier text claiming `postedWithin` was "live-verified" with "25
|
|
2318
|
+
unposted rows, 0 posted" came from the defect itself: `postedDate` was never
|
|
2319
|
+
present, so every row counted as unposted.
|
|
2320
|
+
- **Posted state is derived from `billing_items.timeEntryID`.** An entry is
|
|
2321
|
+
posted when a billing item references it, for **every** entry read;
|
|
2322
|
+
approval is not consulted. Live ww29 (week 2026-03-02..08): 1321 entries,
|
|
2323
|
+
none with `billingApprovalDateTime`, yet 817 referenced by billing items —
|
|
2324
|
+
so an approval-gated join would call everything unposted. No `postedDate`
|
|
2325
|
+
condition is ever sent. The join is one `BillingItems` query per 250 ids;
|
|
2326
|
+
the entry read is capped at 500, so a call costs at most 1 read + 2 joins
|
|
2327
|
+
and a window with more than 500 entries returns the first 500 with
|
|
2328
|
+
`hasMore` / `truncated` true. A 429 or vendor fault propagates as a typed
|
|
2329
|
+
error. The API user therefore needs BillingItems read permission; a permission fault propagates as a typed error.
|
|
2330
|
+
- **`time_entries.getPosted(opts?)` / `getUnposted(opts?)`** — `opts` is
|
|
2331
|
+
`{ limit?, ticketID?, dateFrom?, dateTo? }` (`dateFrom`/`dateTo`:
|
|
2332
|
+
inclusive `dateWorked` days, `YYYY-MM-DD`, never tz-shifted). They return
|
|
2333
|
+
`{ items, hasMore, window, approvedCount, unapprovedCount }` (a breaking
|
|
2334
|
+
change from the bare `TimeEntry[]`, 0.32.0): `getPosted` items are entries
|
|
2335
|
+
a billing item references; `getUnposted` items are entries none references.
|
|
2336
|
+
`approvedCount` / `unapprovedCount` are informational (items with / without
|
|
2337
|
+
`billingApprovalDateTime`) and are **not** posted state. `window` echoes the
|
|
2338
|
+
bounds (`null` for a bound not given); `hasMore` true means the result is
|
|
2339
|
+
partial (entry read capped, or a join page truncated — unconfirmed entries
|
|
2340
|
+
are withheld, never called unposted). `dateFrom`/`dateTo` are optional, but a call without dates reads the tenant's first 500 time entries (effectively the oldest): a near-empty, misleading slice with `hasMore` true — pass a window.
|
|
2341
|
+
- **`time_entries.postedWithin(from, to, opts?)`** — an inclusive UTC
|
|
2342
|
+
`dateWorked` window (`from`/`to` are `YYYY-MM-DD` date strings — the S1c
|
|
2343
|
+
guard forbids Date positionals), one bounded read (`limit` 1-500, default
|
|
2344
|
+
500 — the hard cap, issue #128: a larger window needs `time_entries.query`
|
|
2345
|
+
with the same `dateWorked` filter, its 2500-row walk cap) returning
|
|
2346
|
+
`{ items, postedCount, unpostedCount, window, truncated }`; the counts come
|
|
2347
|
+
from the billing-item join (any billing item referencing the entry), `opts.posted` narrows client-side after the join
|
|
2348
|
+
(true = posted only, false = unposted only, omitted = both); the counts still split every entry read (before the narrowing), so `items.length` can differ from their sum and `ticketID` /
|
|
2349
|
+
`resourceID` narrow the read. Live evidence for the visibility class
|
|
2350
|
+
(unfiltered query 0 rows, windowed read has data) from 2026-10-06 still
|
|
2351
|
+
stands; the posted/unposted split from that period does not.
|
|
2332
2352
|
- **`truncated` + the `dateWorkedWindow` alias + `tz` (issue #66)** — the
|
|
2333
2353
|
result is now `{ items, postedCount, unpostedCount, window, truncated }`:
|
|
2334
2354
|
`truncated` is true when the bounded read came back with a live
|
|
@@ -3029,13 +3049,17 @@ additive, and mirrors the family:
|
|
|
3029
3049
|
fields, not the invoice date).
|
|
3030
3050
|
- **The zone contract (shared)** — `opts.tz` takes an explicit IANA zone
|
|
3031
3051
|
(e.g. `'Australia/Sydney'`); OMITTED `tz` = UTC, the current behaviour
|
|
3032
|
-
bit-for-bit (the regression pin).
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
(
|
|
3037
|
-
|
|
3038
|
-
|
|
3052
|
+
bit-for-bit (the regression pin). All three families are DATE-ONLY
|
|
3053
|
+
(`dateWorked`, `itemDate`, `invoiceDateTime` are stored at T00:00:00Z): the
|
|
3054
|
+
zone picks which calendar DATES a relative window means (what today / last
|
|
3055
|
+
full month is in that zone) and the wire bounds are whole UTC days of them
|
|
3056
|
+
(second-precision UTC ISO); explicit `from`/`to` days are never shifted and
|
|
3057
|
+
`tz` is only validated. `time_entries` has worked this way since 0.24.0;
|
|
3058
|
+
`billing_items` and `invoices` since 0.32.0 (behaviour change: before, a zone
|
|
3059
|
+
behind UTC, e.g. America/New_York, sent a zone-converted instant window that
|
|
3060
|
+
dropped the first day and added an extra day; zones ahead of UTC returned the
|
|
3061
|
+
right rows by accident). A zone-converted instant window picks the wrong day
|
|
3062
|
+
behind UTC. DST is
|
|
3039
3063
|
handled by inverting local midnights to UTC instants (a local day that
|
|
3040
3064
|
gains or loses an hour still pins both boundaries to its TRUE midnights —
|
|
3041
3065
|
never clock-hour arithmetic); `last24h` is rolling (`now − 24h → now`)
|
|
@@ -3290,8 +3314,9 @@ returns the contract's reconciled P&L over a date window:
|
|
|
3290
3314
|
(ticket `createDate`) as UTC instants, and bucketing slices the ISO
|
|
3291
3315
|
string — in a UTC+10/11 tenant a ticket created late local time buckets
|
|
3292
3316
|
one UTC day (possibly one month) earlier than its local date. The
|
|
3293
|
-
`time_entries.getPosted` / `getUnposted`
|
|
3294
|
-
|
|
3317
|
+
`time_entries.getPosted` / `getUnposted` ops are NEVER called (the
|
|
3318
|
+
profitability fold already holds the billing items, so the join is
|
|
3319
|
+
in-memory with no extra wire); posted/unposted derives from the
|
|
3295
3320
|
`billingItems.timeEntryID` join (unposted = no billing item exists yet).
|
|
3296
3321
|
The structural exclusions (`/Services/`, `/ExpenseReports/`,
|
|
3297
3322
|
`/BillingCodes/` list reads, getPosted/getUnposted) are pinned by the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-autotask",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.32.0",
|
|
4
4
|
"description": "Fully-typed TypeScript SDK for the Autotask (Datto) PSA REST API. Zero runtime dependencies. Built for building MCP servers and integrations.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|