node-autotask 0.26.0 → 0.27.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 +47 -0
- package/MCP_TOOL_CATALOG.json +921 -30
- package/MCP_TOOL_MANIFEST.md +69 -16
- package/N8N_MCP_MANIFEST.json +39 -8
- package/N8N_MCP_MANIFEST.md +9 -8
- package/README.md +11 -9
- package/capabilities.json +13316 -7733
- package/capabilities.schema.json +125 -0
- package/dist/capabilities.cjs +2 -2
- package/dist/capabilities.js +1 -1
- package/dist/{chunk-SSUECUVN.js → chunk-42ZUISDH.js} +947 -128
- package/dist/{chunk-WM6E5O55.cjs → chunk-5CC7LGNM.cjs} +13315 -7732
- package/dist/{chunk-SG4LIVMG.cjs → chunk-5GGCSRT4.cjs} +848 -439
- package/dist/{chunk-QXWIQ67O.js → chunk-F7FVOXPQ.js} +13315 -7732
- package/dist/{chunk-7DOSJS6S.js → chunk-GURC52J7.js} +23 -2
- package/dist/{chunk-5OGJTS2E.cjs → chunk-UHTZLUDE.cjs} +157 -136
- package/dist/{chunk-VVQ6NJYZ.js → chunk-ZGTFVZL5.js} +433 -24
- package/dist/{chunk-HQGE4WAV.cjs → chunk-ZJ4ONAQF.cjs} +1054 -235
- package/dist/{index-CKYr0unq.d.cts → index-BIWy9m-a.d.ts} +379 -49
- package/dist/{index-C8QH3BkP.d.ts → index-D4XYtn4s.d.cts} +379 -49
- package/dist/{index-1zBdJIEy.d.cts → index-DQ9NgraW.d.cts} +281 -1
- package/dist/{index-1zBdJIEy.d.ts → index-DQ9NgraW.d.ts} +281 -1
- package/dist/index.cjs +44 -24
- package/dist/index.d.cts +11 -5
- package/dist/index.d.ts +11 -5
- package/dist/index.js +26 -6
- package/dist/operations/index.cjs +147 -120
- package/dist/operations/index.d.cts +136 -7
- package/dist/operations/index.d.ts +136 -7
- package/dist/operations/index.js +33 -6
- package/dist/pool.cjs +42 -9
- package/dist/pool.d.cts +14 -3
- package/dist/pool.d.ts +14 -3
- package/dist/pool.js +38 -5
- package/dist/resources/index.cjs +19 -5
- package/dist/resources/index.d.cts +2 -2
- package/dist/resources/index.d.ts +2 -2
- package/dist/resources/index.js +18 -4
- package/dist/types/index.cjs +1 -1
- package/dist/types/index.d.cts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.js +1 -1
- package/docs/API.md +207 -9
- package/examples/mcp/schemas.ts +16 -7
- package/package.json +1 -1
- /package/dist/{chunk-S643FDOR.cjs → chunk-IXF7AKOJ.cjs} +0 -0
- /package/dist/{chunk-2TWKEB2L.js → chunk-RMG55JTF.js} +0 -0
- /package/dist/{chunk-W3K5BEVY.cjs → chunk-SDYRQFGL.cjs} +0 -0
- /package/dist/{chunk-EBCHCNPK.js → chunk-WLTLB2ND.js} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CAPABILITIES
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-F7FVOXPQ.js";
|
|
4
4
|
|
|
5
5
|
// src/auth.ts
|
|
6
6
|
var AUTH_HEADERS = {
|
|
@@ -583,6 +583,111 @@ var MoveRefusedError = class extends AutotaskError {
|
|
|
583
583
|
}
|
|
584
584
|
};
|
|
585
585
|
|
|
586
|
+
// src/cache.ts
|
|
587
|
+
var READ_CACHE_MAX_ENTRIES = 4096;
|
|
588
|
+
var ReadCache = class {
|
|
589
|
+
/** The configured TTL in ms (the fallback for resources without an override). */
|
|
590
|
+
ttlMs;
|
|
591
|
+
/** The per-resource TTL overrides (issue #32; absent = every resource uses `ttlMs`). */
|
|
592
|
+
perResourceTtlMs;
|
|
593
|
+
store = /* @__PURE__ */ new Map();
|
|
594
|
+
epochCounter = 0;
|
|
595
|
+
constructor(ttlMs, perResourceTtlMs) {
|
|
596
|
+
if (!Number.isInteger(ttlMs) || ttlMs <= 0) {
|
|
597
|
+
throw new AutotaskConfigError(`cache.ttlMs must be a positive integer (got ${ttlMs})`);
|
|
598
|
+
}
|
|
599
|
+
if (perResourceTtlMs !== void 0) {
|
|
600
|
+
if (perResourceTtlMs === null || typeof perResourceTtlMs !== "object" || Array.isArray(perResourceTtlMs)) {
|
|
601
|
+
throw new AutotaskConfigError(
|
|
602
|
+
`cache.perResourceTtlMs must be an object of resource key -> ms (got ${String(perResourceTtlMs)})`
|
|
603
|
+
);
|
|
604
|
+
}
|
|
605
|
+
for (const [key, value] of Object.entries(perResourceTtlMs)) {
|
|
606
|
+
if (key === "") {
|
|
607
|
+
throw new AutotaskConfigError("cache.perResourceTtlMs keys must be non-empty resource keys");
|
|
608
|
+
}
|
|
609
|
+
if (!Number.isInteger(value) || value <= 0) {
|
|
610
|
+
throw new AutotaskConfigError(
|
|
611
|
+
`cache.perResourceTtlMs.${key} must be a positive integer (got ${String(value)})`
|
|
612
|
+
);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
this.ttlMs = ttlMs;
|
|
617
|
+
this.perResourceTtlMs = perResourceTtlMs;
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* The TTL (ms) for a resource plan key: the `perResourceTtlMs` override
|
|
621
|
+
* when the map is present and names the resource, else the base
|
|
622
|
+
* `ttlMs` (absent map, absent key, and `undefined` all fall back).
|
|
623
|
+
*/
|
|
624
|
+
ttlFor(resource) {
|
|
625
|
+
if (resource !== void 0 && this.perResourceTtlMs !== void 0) {
|
|
626
|
+
const override = this.perResourceTtlMs[resource];
|
|
627
|
+
if (override !== void 0) return override;
|
|
628
|
+
}
|
|
629
|
+
return this.ttlMs;
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* Read-through lookup: the live entry's value, or `undefined` (absent OR
|
|
633
|
+
* expired — an expired entry is purged lazily on this read).
|
|
634
|
+
*/
|
|
635
|
+
get(key) {
|
|
636
|
+
const entry = this.store.get(key);
|
|
637
|
+
if (entry === void 0) return void 0;
|
|
638
|
+
if (entry.expiresAt <= Date.now()) {
|
|
639
|
+
this.store.delete(key);
|
|
640
|
+
return void 0;
|
|
641
|
+
}
|
|
642
|
+
return structuredClone(entry.value);
|
|
643
|
+
}
|
|
644
|
+
/** Store a successful read payload under `key`, live for `ttlFor(resource)`:
|
|
645
|
+
* the per-resource override (issue #32) when named, else `ttlMs`.
|
|
646
|
+
* `epoch` is the invalidation epoch the caller captured BEFORE its wire
|
|
647
|
+
* read: a read that straddled a `clear()` (a write) is dropped, never
|
|
648
|
+
* re-stored with its pre-write body. */
|
|
649
|
+
set(key, value, resource, epoch = this.epochCounter) {
|
|
650
|
+
if (epoch !== this.epochCounter) return;
|
|
651
|
+
if (this.store.size >= READ_CACHE_MAX_ENTRIES && this.purgeExpired() === 0) {
|
|
652
|
+
const oldest = this.store.keys().next();
|
|
653
|
+
if (!oldest.done) this.store.delete(oldest.value);
|
|
654
|
+
}
|
|
655
|
+
this.store.delete(key);
|
|
656
|
+
this.store.set(key, { value: structuredClone(value), expiresAt: Date.now() + this.ttlFor(resource) });
|
|
657
|
+
}
|
|
658
|
+
/** Drop every expired entry (returns the number removed). */
|
|
659
|
+
purgeExpired() {
|
|
660
|
+
const now = Date.now();
|
|
661
|
+
let removed = 0;
|
|
662
|
+
for (const [key, entry] of this.store) {
|
|
663
|
+
if (entry.expiresAt <= now) {
|
|
664
|
+
this.store.delete(key);
|
|
665
|
+
removed += 1;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
return removed;
|
|
669
|
+
}
|
|
670
|
+
/** Current entry count (live + not-yet-purged expired). */
|
|
671
|
+
get size() {
|
|
672
|
+
return this.store.size;
|
|
673
|
+
}
|
|
674
|
+
/** Drop one key (issue #36: a later positive outcome clears a stale 'absent' marker). */
|
|
675
|
+
delete(key) {
|
|
676
|
+
return this.store.delete(key);
|
|
677
|
+
}
|
|
678
|
+
/** The invalidation epoch: bumped by `clear()`; capture it before a wire
|
|
679
|
+
* read and pass it to `set` so a read in flight across a write cannot
|
|
680
|
+
* re-store its stale answer. */
|
|
681
|
+
get epoch() {
|
|
682
|
+
return this.epochCounter;
|
|
683
|
+
}
|
|
684
|
+
/** Drop everything (e.g. a caller that knows the tenant was reset). */
|
|
685
|
+
clear() {
|
|
686
|
+
this.epochCounter += 1;
|
|
687
|
+
this.store.clear();
|
|
688
|
+
}
|
|
689
|
+
};
|
|
690
|
+
|
|
586
691
|
// src/config/zones.ts
|
|
587
692
|
var ZONE_CATALOG = {
|
|
588
693
|
"pre-release": "https://webservices2.autotask.net/atservicesrest",
|
|
@@ -689,6 +794,7 @@ var DEFAULT_PER_RESOURCE_TTL_MS = {
|
|
|
689
794
|
"appointments": 3e5,
|
|
690
795
|
"authenticate": 3e5,
|
|
691
796
|
"billing_codes": 36e5,
|
|
797
|
+
"billing_item_approval_levels": 3e5,
|
|
692
798
|
"billing_items": 3e5,
|
|
693
799
|
"change_request_links": 3e5,
|
|
694
800
|
"checklist_libraries": 3e5,
|
|
@@ -747,12 +853,16 @@ var DEFAULT_PER_RESOURCE_TTL_MS = {
|
|
|
747
853
|
"holiday_sets": 3e5,
|
|
748
854
|
"holidays": 3e5,
|
|
749
855
|
"inventory_products": 3e5,
|
|
856
|
+
"invoice_templates": 3e5,
|
|
750
857
|
"invoices": 3e5,
|
|
751
858
|
"modules": 3e5,
|
|
752
859
|
"notification_history": 3e5,
|
|
753
860
|
"opportunities": 3e5,
|
|
754
861
|
"opportunity_attachments": 3e5,
|
|
755
862
|
"opportunity_categories": 3e5,
|
|
863
|
+
"organizational_level1s": 3e5,
|
|
864
|
+
"organizational_level2s": 3e5,
|
|
865
|
+
"organizational_level_associations": 3e5,
|
|
756
866
|
"phases": 36e5,
|
|
757
867
|
"product_vendors": 3e5,
|
|
758
868
|
"products": 3e5,
|
|
@@ -775,6 +885,7 @@ var DEFAULT_PER_RESOURCE_TTL_MS = {
|
|
|
775
885
|
"resource_time_off_balances": 3e5,
|
|
776
886
|
"resources": 3e5,
|
|
777
887
|
"roles": 36e5,
|
|
888
|
+
"sales_orders": 3e5,
|
|
778
889
|
"service_call_task_resources": 3e5,
|
|
779
890
|
"service_call_tasks": 3e5,
|
|
780
891
|
"service_call_ticket_resources": 3e5,
|
|
@@ -792,6 +903,7 @@ var DEFAULT_PER_RESOURCE_TTL_MS = {
|
|
|
792
903
|
"tags": 3e5,
|
|
793
904
|
"task_secondary_resources": 3e5,
|
|
794
905
|
"tasks": 3e5,
|
|
906
|
+
"tax_regions": 3e5,
|
|
795
907
|
"threshold_information": 3e5,
|
|
796
908
|
"ticket_additional_configuration_items": 3e5,
|
|
797
909
|
"ticket_additional_contacts": 3e5,
|
|
@@ -819,6 +931,7 @@ var DEFAULT_PER_RESOURCE_TTL_MS = {
|
|
|
819
931
|
var RESOURCE_KEY_BY_PATH = {
|
|
820
932
|
"/V1.0/Appointments": "appointments",
|
|
821
933
|
"/V1.0/BillingCodes": "billing_codes",
|
|
934
|
+
"/V1.0/BillingItemApprovalLevels": "billing_item_approval_levels",
|
|
822
935
|
"/V1.0/BillingItems": "billing_items",
|
|
823
936
|
"/V1.0/ChangeRequestLinks": "change_request_links",
|
|
824
937
|
"/V1.0/ChecklistLibraries": "checklist_libraries",
|
|
@@ -876,11 +989,15 @@ var RESOURCE_KEY_BY_PATH = {
|
|
|
876
989
|
"/V1.0/HolidaySets": "holiday_sets",
|
|
877
990
|
"/V1.0/Holidays": "holidays",
|
|
878
991
|
"/V1.0/InventoryProducts": "inventory_products",
|
|
992
|
+
"/V1.0/InvoiceTemplates": "invoice_templates",
|
|
879
993
|
"/V1.0/Invoices": "invoices",
|
|
880
994
|
"/V1.0/NotificationHistory": "notification_history",
|
|
881
995
|
"/V1.0/Opportunities": "opportunities",
|
|
882
996
|
"/V1.0/OpportunityAttachments": "opportunity_attachments",
|
|
883
997
|
"/V1.0/OpportunityCategories": "opportunity_categories",
|
|
998
|
+
"/V1.0/OrganizationalLevel1s": "organizational_level1s",
|
|
999
|
+
"/V1.0/OrganizationalLevel2s": "organizational_level2s",
|
|
1000
|
+
"/V1.0/OrganizationalLevelAssociations": "organizational_level_associations",
|
|
884
1001
|
"/V1.0/Phases": "phases",
|
|
885
1002
|
"/V1.0/ProductVendors": "product_vendors",
|
|
886
1003
|
"/V1.0/Products": "products",
|
|
@@ -903,6 +1020,7 @@ var RESOURCE_KEY_BY_PATH = {
|
|
|
903
1020
|
"/V1.0/ResourceTimeOffBalances": "resource_time_off_balances",
|
|
904
1021
|
"/V1.0/Resources": "resources",
|
|
905
1022
|
"/V1.0/Roles": "roles",
|
|
1023
|
+
"/V1.0/SalesOrders": "sales_orders",
|
|
906
1024
|
"/V1.0/ServiceCallTaskResources": "service_call_task_resources",
|
|
907
1025
|
"/V1.0/ServiceCallTasks": "service_call_tasks",
|
|
908
1026
|
"/V1.0/ServiceCallTicketResources": "service_call_ticket_resources",
|
|
@@ -920,6 +1038,7 @@ var RESOURCE_KEY_BY_PATH = {
|
|
|
920
1038
|
"/V1.0/Tags": "tags",
|
|
921
1039
|
"/V1.0/TaskSecondaryResources": "task_secondary_resources",
|
|
922
1040
|
"/V1.0/Tasks": "tasks",
|
|
1041
|
+
"/V1.0/TaxRegions": "tax_regions",
|
|
923
1042
|
"/V1.0/TicketAdditionalConfigurationItems": "ticket_additional_configuration_items",
|
|
924
1043
|
"/V1.0/TicketAdditionalContacts": "ticket_additional_contacts",
|
|
925
1044
|
"/V1.0/TicketAttachments": "ticket_attachments",
|
|
@@ -1247,111 +1366,6 @@ function cooldownDurationMs(retryAfterSecs, opts) {
|
|
|
1247
1366
|
return Math.min(rawMs, opts.maxMs);
|
|
1248
1367
|
}
|
|
1249
1368
|
|
|
1250
|
-
// src/cache.ts
|
|
1251
|
-
var READ_CACHE_MAX_ENTRIES = 4096;
|
|
1252
|
-
var ReadCache = class {
|
|
1253
|
-
/** The configured TTL in ms (the fallback for resources without an override). */
|
|
1254
|
-
ttlMs;
|
|
1255
|
-
/** The per-resource TTL overrides (issue #32; absent = every resource uses `ttlMs`). */
|
|
1256
|
-
perResourceTtlMs;
|
|
1257
|
-
store = /* @__PURE__ */ new Map();
|
|
1258
|
-
epochCounter = 0;
|
|
1259
|
-
constructor(ttlMs, perResourceTtlMs) {
|
|
1260
|
-
if (!Number.isInteger(ttlMs) || ttlMs <= 0) {
|
|
1261
|
-
throw new AutotaskConfigError(`cache.ttlMs must be a positive integer (got ${ttlMs})`);
|
|
1262
|
-
}
|
|
1263
|
-
if (perResourceTtlMs !== void 0) {
|
|
1264
|
-
if (perResourceTtlMs === null || typeof perResourceTtlMs !== "object" || Array.isArray(perResourceTtlMs)) {
|
|
1265
|
-
throw new AutotaskConfigError(
|
|
1266
|
-
`cache.perResourceTtlMs must be an object of resource key -> ms (got ${String(perResourceTtlMs)})`
|
|
1267
|
-
);
|
|
1268
|
-
}
|
|
1269
|
-
for (const [key, value] of Object.entries(perResourceTtlMs)) {
|
|
1270
|
-
if (key === "") {
|
|
1271
|
-
throw new AutotaskConfigError("cache.perResourceTtlMs keys must be non-empty resource keys");
|
|
1272
|
-
}
|
|
1273
|
-
if (!Number.isInteger(value) || value <= 0) {
|
|
1274
|
-
throw new AutotaskConfigError(
|
|
1275
|
-
`cache.perResourceTtlMs.${key} must be a positive integer (got ${String(value)})`
|
|
1276
|
-
);
|
|
1277
|
-
}
|
|
1278
|
-
}
|
|
1279
|
-
}
|
|
1280
|
-
this.ttlMs = ttlMs;
|
|
1281
|
-
this.perResourceTtlMs = perResourceTtlMs;
|
|
1282
|
-
}
|
|
1283
|
-
/**
|
|
1284
|
-
* The TTL (ms) for a resource plan key: the `perResourceTtlMs` override
|
|
1285
|
-
* when the map is present and names the resource, else the base
|
|
1286
|
-
* `ttlMs` (absent map, absent key, and `undefined` all fall back).
|
|
1287
|
-
*/
|
|
1288
|
-
ttlFor(resource) {
|
|
1289
|
-
if (resource !== void 0 && this.perResourceTtlMs !== void 0) {
|
|
1290
|
-
const override = this.perResourceTtlMs[resource];
|
|
1291
|
-
if (override !== void 0) return override;
|
|
1292
|
-
}
|
|
1293
|
-
return this.ttlMs;
|
|
1294
|
-
}
|
|
1295
|
-
/**
|
|
1296
|
-
* Read-through lookup: the live entry's value, or `undefined` (absent OR
|
|
1297
|
-
* expired — an expired entry is purged lazily on this read).
|
|
1298
|
-
*/
|
|
1299
|
-
get(key) {
|
|
1300
|
-
const entry = this.store.get(key);
|
|
1301
|
-
if (entry === void 0) return void 0;
|
|
1302
|
-
if (entry.expiresAt <= Date.now()) {
|
|
1303
|
-
this.store.delete(key);
|
|
1304
|
-
return void 0;
|
|
1305
|
-
}
|
|
1306
|
-
return structuredClone(entry.value);
|
|
1307
|
-
}
|
|
1308
|
-
/** Store a successful read payload under `key`, live for `ttlFor(resource)`:
|
|
1309
|
-
* the per-resource override (issue #32) when named, else `ttlMs`.
|
|
1310
|
-
* `epoch` is the invalidation epoch the caller captured BEFORE its wire
|
|
1311
|
-
* read: a read that straddled a `clear()` (a write) is dropped, never
|
|
1312
|
-
* re-stored with its pre-write body. */
|
|
1313
|
-
set(key, value, resource, epoch = this.epochCounter) {
|
|
1314
|
-
if (epoch !== this.epochCounter) return;
|
|
1315
|
-
if (this.store.size >= READ_CACHE_MAX_ENTRIES && this.purgeExpired() === 0) {
|
|
1316
|
-
const oldest = this.store.keys().next();
|
|
1317
|
-
if (!oldest.done) this.store.delete(oldest.value);
|
|
1318
|
-
}
|
|
1319
|
-
this.store.delete(key);
|
|
1320
|
-
this.store.set(key, { value: structuredClone(value), expiresAt: Date.now() + this.ttlFor(resource) });
|
|
1321
|
-
}
|
|
1322
|
-
/** Drop every expired entry (returns the number removed). */
|
|
1323
|
-
purgeExpired() {
|
|
1324
|
-
const now = Date.now();
|
|
1325
|
-
let removed = 0;
|
|
1326
|
-
for (const [key, entry] of this.store) {
|
|
1327
|
-
if (entry.expiresAt <= now) {
|
|
1328
|
-
this.store.delete(key);
|
|
1329
|
-
removed += 1;
|
|
1330
|
-
}
|
|
1331
|
-
}
|
|
1332
|
-
return removed;
|
|
1333
|
-
}
|
|
1334
|
-
/** Current entry count (live + not-yet-purged expired). */
|
|
1335
|
-
get size() {
|
|
1336
|
-
return this.store.size;
|
|
1337
|
-
}
|
|
1338
|
-
/** Drop one key (issue #36: a later positive outcome clears a stale 'absent' marker). */
|
|
1339
|
-
delete(key) {
|
|
1340
|
-
return this.store.delete(key);
|
|
1341
|
-
}
|
|
1342
|
-
/** The invalidation epoch: bumped by `clear()`; capture it before a wire
|
|
1343
|
-
* read and pass it to `set` so a read in flight across a write cannot
|
|
1344
|
-
* re-store its stale answer. */
|
|
1345
|
-
get epoch() {
|
|
1346
|
-
return this.epochCounter;
|
|
1347
|
-
}
|
|
1348
|
-
/** Drop everything (e.g. a caller that knows the tenant was reset). */
|
|
1349
|
-
clear() {
|
|
1350
|
-
this.epochCounter += 1;
|
|
1351
|
-
this.store.clear();
|
|
1352
|
-
}
|
|
1353
|
-
};
|
|
1354
|
-
|
|
1355
1369
|
// src/resourceNameCache.ts
|
|
1356
1370
|
var RESOURCE_NAME_CACHE_MAX_ENTRIES = 1024;
|
|
1357
1371
|
var RESOURCE_NAME_CACHE_BLIND_TTL_MS = 6e4;
|
|
@@ -1835,12 +1849,10 @@ function resolveResolution(config, agent) {
|
|
|
1835
1849
|
}
|
|
1836
1850
|
function resolveCaches(config) {
|
|
1837
1851
|
const cacheBlock = config.cache === false || config.cache === void 0 ? void 0 : config.cache;
|
|
1852
|
+
resolveReadCacheStore(cacheBlock);
|
|
1838
1853
|
const fieldCacheBlock = config.fieldCache === false || config.fieldCache === void 0 ? void 0 : config.fieldCache;
|
|
1839
1854
|
const resourceNameCacheBlock = config.resourceNameCache === false || config.resourceNameCache === void 0 ? void 0 : config.resourceNameCache;
|
|
1840
|
-
const readCache = config.cache === false ? void 0 :
|
|
1841
|
-
cacheBlock?.ttlMs ?? DEFAULT_READ_CACHE_TTL_MS,
|
|
1842
|
-
{ ...DEFAULT_PER_RESOURCE_TTL_MS, ...cacheBlock?.perResourceTtlMs }
|
|
1843
|
-
);
|
|
1855
|
+
const readCache = config.cache === false ? void 0 : cacheBlock?.store ?? buildReadCache(config);
|
|
1844
1856
|
const fieldCache = config.fieldCache === false ? void 0 : new FieldCache(
|
|
1845
1857
|
fieldCacheBlock?.ttlMs ?? DEFAULT_FIELD_CACHE_TTL_MS,
|
|
1846
1858
|
fieldCacheBlock?.maxEntities ?? FIELD_CACHE_MAX_ENTITIES
|
|
@@ -1851,6 +1863,27 @@ function resolveCaches(config) {
|
|
|
1851
1863
|
);
|
|
1852
1864
|
return { readCache, fieldCache, resourceNameCache };
|
|
1853
1865
|
}
|
|
1866
|
+
function resolveReadCacheStore(cacheBlock) {
|
|
1867
|
+
if (cacheBlock === void 0 || cacheBlock === false || cacheBlock.store === void 0) return;
|
|
1868
|
+
if (!(cacheBlock.store instanceof ReadCache)) {
|
|
1869
|
+
throw new AutotaskConfigError(
|
|
1870
|
+
"cache.store must be a ReadCache instance (import { ReadCache } from the SDK; the pool supplies its own)"
|
|
1871
|
+
);
|
|
1872
|
+
}
|
|
1873
|
+
if (cacheBlock.ttlMs !== void 0 || cacheBlock.perResourceTtlMs !== void 0) {
|
|
1874
|
+
throw new AutotaskConfigError(
|
|
1875
|
+
"cache.store cannot be combined with cache.ttlMs or cache.perResourceTtlMs \u2014 the supplied ReadCache instance owns its TTLs"
|
|
1876
|
+
);
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
function buildReadCache(config) {
|
|
1880
|
+
if (config.cache === false) return void 0;
|
|
1881
|
+
const cacheBlock = config.cache === void 0 ? void 0 : config.cache;
|
|
1882
|
+
return new ReadCache(
|
|
1883
|
+
cacheBlock?.ttlMs ?? DEFAULT_READ_CACHE_TTL_MS,
|
|
1884
|
+
{ ...DEFAULT_PER_RESOURCE_TTL_MS, ...cacheBlock?.perResourceTtlMs }
|
|
1885
|
+
);
|
|
1886
|
+
}
|
|
1854
1887
|
function resolveConfig(config) {
|
|
1855
1888
|
if (config === null || typeof config !== "object") {
|
|
1856
1889
|
throw new AutotaskConfigError("AutotaskConfig is required");
|
|
@@ -2355,6 +2388,52 @@ var RELATIONSHIP_MAP = {
|
|
|
2355
2388
|
"deleteBoundary": null,
|
|
2356
2389
|
"markerField": null
|
|
2357
2390
|
},
|
|
2391
|
+
"billing_item_approval_levels": {
|
|
2392
|
+
"resource": "billing_item_approval_levels",
|
|
2393
|
+
"apiEntity": "BillingItemApprovalLevel",
|
|
2394
|
+
"kind": "entity",
|
|
2395
|
+
"path": "BillingItemApprovalLevels",
|
|
2396
|
+
"parentScoped": false,
|
|
2397
|
+
"tier": "extended",
|
|
2398
|
+
"workflowResource": false,
|
|
2399
|
+
"group": "B",
|
|
2400
|
+
"parent": null,
|
|
2401
|
+
"children": [],
|
|
2402
|
+
"naturalKeys": {
|
|
2403
|
+
"hasSearch": false,
|
|
2404
|
+
"searchCovers": null,
|
|
2405
|
+
"findBy": []
|
|
2406
|
+
},
|
|
2407
|
+
"blindSurfaces": null,
|
|
2408
|
+
"zoneFacts": {
|
|
2409
|
+
"createGuidance": {
|
|
2410
|
+
"createOp": "billing_item_approval_levels.create",
|
|
2411
|
+
"parentScoped": false,
|
|
2412
|
+
"liveProvenPrefix": [],
|
|
2413
|
+
"unproven": true,
|
|
2414
|
+
"blocker": {
|
|
2415
|
+
"kind": "unknown",
|
|
2416
|
+
"message": "never live-probed: this entity reached the plan on 2026-10-26 (feat/time-entry-approve) after the stage-11 apply matrix closed, so no create has been attempted against a tenant. The vendor documents the conditions (timeEntryID and approvalResourceID must reference existing objects) and the side effect (TimeEntry.BillingApprovalLevelMostRecent is updated; approvalDateTime / approvalResourceID are not), but the acceptance of the model body is unverified.",
|
|
2417
|
+
"remedy": "attempt one create against a time entry in a non-production tenant (dry-run first), then promote createGuidance to kind ok with its liveProvenPrefix; a refusal arrives as a vendor 500 whose errors[] text names the failing field."
|
|
2418
|
+
},
|
|
2419
|
+
"vendorEvidence": [
|
|
2420
|
+
'Vendor help, BillingItemApprovalLevels entity page (fetched 2026-10-26): "describes a multi-level approval record for an Autotask time entry ... This option is only available through the REST API."',
|
|
2421
|
+
'Vendor help, BillingItemApprovalLevels entity page (fetched 2026-10-26): "When the BillingItemApprovalLevels entity is created, the TimeEntry.BillingApprovalLevelMostRecent field is updated, but approvalDateTime and approvalResourceID are not. Instead, the approvalDateTime and approvalResourceID fields are editable on the TimeEntry entity. Workaround: ... create the BillingItemApprovalLevel and then follow that call up with an update to the TimeEntry to set the BillingApprovalDateTime and BillingApprovalResourceID fields."',
|
|
2422
|
+
"api-docs.json: POST /V1.0/BillingItemApprovalLevels consumes definitions.BillingItemApprovalLevelModel and answers OperationResultModel \u2014 the entity defines no PUT, PATCH or DELETE path."
|
|
2423
|
+
],
|
|
2424
|
+
"deleteBoundary": {
|
|
2425
|
+
"available": false,
|
|
2426
|
+
"note": "the vendor defines no DELETE for billing_item_approval_levels (spec-derived) \u2014 an approval level cannot be removed or corrected through the API; record cleanup is UI-only."
|
|
2427
|
+
},
|
|
2428
|
+
"zone": "ww29"
|
|
2429
|
+
}
|
|
2430
|
+
},
|
|
2431
|
+
"deleteBoundary": {
|
|
2432
|
+
"note": "the vendor defines no DELETE for billing_item_approval_levels (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 an approval level cannot be removed or corrected through the API; record cleanup is UI-only.",
|
|
2433
|
+
"proof": "spec-derived"
|
|
2434
|
+
},
|
|
2435
|
+
"markerField": null
|
|
2436
|
+
},
|
|
2358
2437
|
"billing_items": {
|
|
2359
2438
|
"resource": "billing_items",
|
|
2360
2439
|
"apiEntity": "BillingItems",
|
|
@@ -5078,8 +5157,8 @@ var RELATIONSHIP_MAP = {
|
|
|
5078
5157
|
"unproven": false,
|
|
5079
5158
|
"blocker": {
|
|
5080
5159
|
"kind": "ok",
|
|
5081
|
-
"message": "live-PROVEN 2026-10-06 (confirm-100, marker CONF100-1791187382): the W-A6 'blind parent' was companyID \u2014 an OWNED company satisfies it (seed 30132785). Proven contractType values: 1, 3 (Fixed Price), 4 (Block hours), 6 (Retainer), 7 (Recurring Services), 8 (PerTicket incident)
|
|
5082
|
-
"remedy": "live-proven on ww29 2026-10-06 (confirm-100, marker CONF100-1791187382) \u2014
|
|
5160
|
+
"message": "live-PROVEN 2026-10-06 (confirm-100, marker CONF100-1791187382): the W-A6 'blind parent' was companyID \u2014 an OWNED company satisfies it (seed 30132785). Proven contractType values: 1, 3 (Fixed Price), 4 (Block hours), 6 (Retainer), 7 (Recurring Services), 8 (PerTicket incident). The type-conditioned field gates are declared in requiresByValue / rejectedValues on this row (issue #219 N3) \u2014 they are no longer restated in prose here. Proven ids 30131842-30131847 (residue \u2014 no vendor DELETE for contracts).",
|
|
5161
|
+
"remedy": "live-proven on ww29 2026-10-06 (confirm-100, marker CONF100-1791187382) \u2014 send the body with the contractType you need and satisfy that value's requiresByValue gate (plus the contractPeriodType value it names); residue records are ledgered (.run/confirm-100-20261006/CONFIRMATION-LEDGER.md section E; UI cleanup)"
|
|
5083
5162
|
},
|
|
5084
5163
|
"vendorEvidence": [
|
|
5085
5164
|
'{"error":true,"code":"SERVER_ERROR","category":"server","retryable":true,"httpStatus":500,"operation":"contracts.create","suggestedAction":"Retry with backoff; the server error is transient.","correlationId":"25d4a730-6d6c-49ff-a038-96d3fd09165d","message":"Value does not exist for the required fiel',
|
|
@@ -5089,7 +5168,75 @@ var RELATIONSHIP_MAP = {
|
|
|
5089
5168
|
"available": false,
|
|
5090
5169
|
"note": "the vendor defines no DELETE for contracts (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only."
|
|
5091
5170
|
},
|
|
5092
|
-
"zone": "ww29"
|
|
5171
|
+
"zone": "ww29",
|
|
5172
|
+
"requiresByValue": [
|
|
5173
|
+
{
|
|
5174
|
+
"field": "contractType",
|
|
5175
|
+
"value": 1,
|
|
5176
|
+
"requires": {
|
|
5177
|
+
"allOf": [
|
|
5178
|
+
"estimatedRevenue",
|
|
5179
|
+
"estimatedHours",
|
|
5180
|
+
"estimatedCost"
|
|
5181
|
+
]
|
|
5182
|
+
}
|
|
5183
|
+
},
|
|
5184
|
+
{
|
|
5185
|
+
"field": "contractType",
|
|
5186
|
+
"value": 3,
|
|
5187
|
+
"requires": {
|
|
5188
|
+
"allOf": [
|
|
5189
|
+
"estimatedRevenue"
|
|
5190
|
+
]
|
|
5191
|
+
}
|
|
5192
|
+
},
|
|
5193
|
+
{
|
|
5194
|
+
"field": "contractType",
|
|
5195
|
+
"value": 4,
|
|
5196
|
+
"requires": {
|
|
5197
|
+
"allOf": [
|
|
5198
|
+
"estimatedRevenue"
|
|
5199
|
+
]
|
|
5200
|
+
}
|
|
5201
|
+
},
|
|
5202
|
+
{
|
|
5203
|
+
"field": "contractType",
|
|
5204
|
+
"value": 6,
|
|
5205
|
+
"requires": {
|
|
5206
|
+
"allOf": [
|
|
5207
|
+
"estimatedRevenue"
|
|
5208
|
+
]
|
|
5209
|
+
}
|
|
5210
|
+
},
|
|
5211
|
+
{
|
|
5212
|
+
"field": "contractType",
|
|
5213
|
+
"value": 7,
|
|
5214
|
+
"requires": {
|
|
5215
|
+
"allOf": [
|
|
5216
|
+
"contractPeriodType",
|
|
5217
|
+
"setupFee"
|
|
5218
|
+
]
|
|
5219
|
+
},
|
|
5220
|
+
"values": {
|
|
5221
|
+
"contractPeriodType": 2
|
|
5222
|
+
}
|
|
5223
|
+
},
|
|
5224
|
+
{
|
|
5225
|
+
"field": "contractType",
|
|
5226
|
+
"value": 8,
|
|
5227
|
+
"requires": {
|
|
5228
|
+
"allOf": [
|
|
5229
|
+
"estimatedRevenue"
|
|
5230
|
+
]
|
|
5231
|
+
}
|
|
5232
|
+
}
|
|
5233
|
+
],
|
|
5234
|
+
"rejectedValues": [
|
|
5235
|
+
{
|
|
5236
|
+
"field": "contractType",
|
|
5237
|
+
"value": 5
|
|
5238
|
+
}
|
|
5239
|
+
]
|
|
5093
5240
|
}
|
|
5094
5241
|
},
|
|
5095
5242
|
"deleteBoundary": {
|
|
@@ -5527,6 +5674,27 @@ var RELATIONSHIP_MAP = {
|
|
|
5527
5674
|
"deleteBoundary": null,
|
|
5528
5675
|
"markerField": null
|
|
5529
5676
|
},
|
|
5677
|
+
"invoice_templates": {
|
|
5678
|
+
"resource": "invoice_templates",
|
|
5679
|
+
"apiEntity": "InvoiceTemplate",
|
|
5680
|
+
"kind": "entity",
|
|
5681
|
+
"path": "InvoiceTemplates",
|
|
5682
|
+
"parentScoped": false,
|
|
5683
|
+
"tier": "advanced",
|
|
5684
|
+
"workflowResource": false,
|
|
5685
|
+
"group": "B",
|
|
5686
|
+
"parent": null,
|
|
5687
|
+
"children": [],
|
|
5688
|
+
"naturalKeys": {
|
|
5689
|
+
"hasSearch": false,
|
|
5690
|
+
"searchCovers": null,
|
|
5691
|
+
"findBy": []
|
|
5692
|
+
},
|
|
5693
|
+
"blindSurfaces": null,
|
|
5694
|
+
"zoneFacts": null,
|
|
5695
|
+
"deleteBoundary": null,
|
|
5696
|
+
"markerField": null
|
|
5697
|
+
},
|
|
5530
5698
|
"invoices": {
|
|
5531
5699
|
"resource": "invoices",
|
|
5532
5700
|
"apiEntity": "Invoice",
|
|
@@ -5717,6 +5885,138 @@ var RELATIONSHIP_MAP = {
|
|
|
5717
5885
|
"deleteBoundary": null,
|
|
5718
5886
|
"markerField": null
|
|
5719
5887
|
},
|
|
5888
|
+
"organizational_level1s": {
|
|
5889
|
+
"resource": "organizational_level1s",
|
|
5890
|
+
"apiEntity": "OrganizationalLevel1",
|
|
5891
|
+
"kind": "entity",
|
|
5892
|
+
"path": "OrganizationalLevel1s",
|
|
5893
|
+
"parentScoped": false,
|
|
5894
|
+
"tier": "advanced",
|
|
5895
|
+
"workflowResource": false,
|
|
5896
|
+
"group": "B",
|
|
5897
|
+
"parent": null,
|
|
5898
|
+
"children": [],
|
|
5899
|
+
"naturalKeys": {
|
|
5900
|
+
"hasSearch": false,
|
|
5901
|
+
"searchCovers": null,
|
|
5902
|
+
"findBy": []
|
|
5903
|
+
},
|
|
5904
|
+
"blindSurfaces": null,
|
|
5905
|
+
"zoneFacts": {
|
|
5906
|
+
"createGuidance": {
|
|
5907
|
+
"createOp": "organizational_level1s.create",
|
|
5908
|
+
"parentScoped": false,
|
|
5909
|
+
"liveProvenPrefix": [],
|
|
5910
|
+
"unproven": true,
|
|
5911
|
+
"blocker": {
|
|
5912
|
+
"kind": "unknown",
|
|
5913
|
+
"message": "never live-probed: this entity reached the plan on 2026-10-26 (feat/guidance-contract-027) after the stage-11 apply matrix closed, so no create has been attempted against a tenant. The vendor documents the model body (definitions.OrganizationalLevel1Model) and answers OperationResultModel, but acceptance of the body is unverified; the spec defines no DELETE on the entity's paths.",
|
|
5914
|
+
"remedy": "attempt one create against a non-production tenant (dry-run first), then promote createGuidance to kind ok with its liveProvenPrefix; a refusal arrives as a vendor 500 whose errors[] text names the failing field."
|
|
5915
|
+
},
|
|
5916
|
+
"vendorEvidence": [
|
|
5917
|
+
"api-docs.json: POST /V1.0/OrganizationalLevel1s consumes definitions.OrganizationalLevel1Model and answers OperationResultModel \u2014 the entity defines no DELETE path."
|
|
5918
|
+
],
|
|
5919
|
+
"deleteBoundary": {
|
|
5920
|
+
"available": false,
|
|
5921
|
+
"note": "the vendor defines no DELETE for organizational_level1s (spec-derived) \u2014 a record cannot be removed or corrected through the API; cleanup is UI-only."
|
|
5922
|
+
},
|
|
5923
|
+
"zone": "ww29"
|
|
5924
|
+
}
|
|
5925
|
+
},
|
|
5926
|
+
"deleteBoundary": {
|
|
5927
|
+
"note": "the vendor defines no DELETE for organizational_level1s (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
5928
|
+
"proof": "spec-derived"
|
|
5929
|
+
},
|
|
5930
|
+
"markerField": null
|
|
5931
|
+
},
|
|
5932
|
+
"organizational_level2s": {
|
|
5933
|
+
"resource": "organizational_level2s",
|
|
5934
|
+
"apiEntity": "OrganizationalLevel2",
|
|
5935
|
+
"kind": "entity",
|
|
5936
|
+
"path": "OrganizationalLevel2s",
|
|
5937
|
+
"parentScoped": false,
|
|
5938
|
+
"tier": "advanced",
|
|
5939
|
+
"workflowResource": false,
|
|
5940
|
+
"group": "B",
|
|
5941
|
+
"parent": null,
|
|
5942
|
+
"children": [],
|
|
5943
|
+
"naturalKeys": {
|
|
5944
|
+
"hasSearch": false,
|
|
5945
|
+
"searchCovers": null,
|
|
5946
|
+
"findBy": []
|
|
5947
|
+
},
|
|
5948
|
+
"blindSurfaces": null,
|
|
5949
|
+
"zoneFacts": {
|
|
5950
|
+
"createGuidance": {
|
|
5951
|
+
"createOp": "organizational_level2s.create",
|
|
5952
|
+
"parentScoped": false,
|
|
5953
|
+
"liveProvenPrefix": [],
|
|
5954
|
+
"unproven": true,
|
|
5955
|
+
"blocker": {
|
|
5956
|
+
"kind": "unknown",
|
|
5957
|
+
"message": "never live-probed: this entity reached the plan on 2026-10-26 (feat/guidance-contract-027) after the stage-11 apply matrix closed, so no create has been attempted against a tenant. The vendor documents the model body (definitions.OrganizationalLevel2Model) and answers OperationResultModel, but acceptance of the body is unverified; the spec defines no DELETE on the entity's paths.",
|
|
5958
|
+
"remedy": "attempt one create against a non-production tenant (dry-run first), then promote createGuidance to kind ok with its liveProvenPrefix; a refusal arrives as a vendor 500 whose errors[] text names the failing field."
|
|
5959
|
+
},
|
|
5960
|
+
"vendorEvidence": [
|
|
5961
|
+
"api-docs.json: POST /V1.0/OrganizationalLevel2s consumes definitions.OrganizationalLevel2Model and answers OperationResultModel \u2014 the entity defines no DELETE path."
|
|
5962
|
+
],
|
|
5963
|
+
"deleteBoundary": {
|
|
5964
|
+
"available": false,
|
|
5965
|
+
"note": "the vendor defines no DELETE for organizational_level2s (spec-derived) \u2014 a record cannot be removed or corrected through the API; cleanup is UI-only."
|
|
5966
|
+
},
|
|
5967
|
+
"zone": "ww29"
|
|
5968
|
+
}
|
|
5969
|
+
},
|
|
5970
|
+
"deleteBoundary": {
|
|
5971
|
+
"note": "the vendor defines no DELETE for organizational_level2s (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
5972
|
+
"proof": "spec-derived"
|
|
5973
|
+
},
|
|
5974
|
+
"markerField": null
|
|
5975
|
+
},
|
|
5976
|
+
"organizational_level_associations": {
|
|
5977
|
+
"resource": "organizational_level_associations",
|
|
5978
|
+
"apiEntity": "OrganizationalLevelAssociation",
|
|
5979
|
+
"kind": "entity",
|
|
5980
|
+
"path": "OrganizationalLevelAssociations",
|
|
5981
|
+
"parentScoped": false,
|
|
5982
|
+
"tier": "advanced",
|
|
5983
|
+
"workflowResource": false,
|
|
5984
|
+
"group": "B",
|
|
5985
|
+
"parent": null,
|
|
5986
|
+
"children": [],
|
|
5987
|
+
"naturalKeys": {
|
|
5988
|
+
"hasSearch": false,
|
|
5989
|
+
"searchCovers": null,
|
|
5990
|
+
"findBy": []
|
|
5991
|
+
},
|
|
5992
|
+
"blindSurfaces": null,
|
|
5993
|
+
"zoneFacts": {
|
|
5994
|
+
"createGuidance": {
|
|
5995
|
+
"createOp": "organizational_level_associations.create",
|
|
5996
|
+
"parentScoped": false,
|
|
5997
|
+
"liveProvenPrefix": [],
|
|
5998
|
+
"unproven": true,
|
|
5999
|
+
"blocker": {
|
|
6000
|
+
"kind": "unknown",
|
|
6001
|
+
"message": "never live-probed: this entity reached the plan on 2026-10-26 (feat/guidance-contract-027) after the stage-11 apply matrix closed, so no create has been attempted against a tenant. The vendor documents the model body (definitions.OrganizationalLevelAssociationModel) and answers OperationResultModel, but acceptance of the body is unverified; the spec defines no DELETE on the entity's paths.",
|
|
6002
|
+
"remedy": "attempt one create against a non-production tenant (dry-run first), then promote createGuidance to kind ok with its liveProvenPrefix; a refusal arrives as a vendor 500 whose errors[] text names the failing field."
|
|
6003
|
+
},
|
|
6004
|
+
"vendorEvidence": [
|
|
6005
|
+
"api-docs.json: POST /V1.0/OrganizationalLevelAssociations consumes definitions.OrganizationalLevelAssociationModel and answers OperationResultModel \u2014 the entity defines no DELETE path."
|
|
6006
|
+
],
|
|
6007
|
+
"deleteBoundary": {
|
|
6008
|
+
"available": false,
|
|
6009
|
+
"note": "the vendor defines no DELETE for organizational_level_associations (spec-derived) \u2014 a record cannot be removed or corrected through the API; cleanup is UI-only."
|
|
6010
|
+
},
|
|
6011
|
+
"zone": "ww29"
|
|
6012
|
+
}
|
|
6013
|
+
},
|
|
6014
|
+
"deleteBoundary": {
|
|
6015
|
+
"note": "the vendor defines no DELETE for organizational_level_associations (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
6016
|
+
"proof": "spec-derived"
|
|
6017
|
+
},
|
|
6018
|
+
"markerField": null
|
|
6019
|
+
},
|
|
5720
6020
|
"product_vendors": {
|
|
5721
6021
|
"resource": "product_vendors",
|
|
5722
6022
|
"apiEntity": "ProductVendors",
|
|
@@ -5869,7 +6169,13 @@ var RELATIONSHIP_MAP = {
|
|
|
5869
6169
|
"blocker": {
|
|
5870
6170
|
"kind": "blind-parent",
|
|
5871
6171
|
"message": "vendor 500 (stage-11 apply-matrix, marker FULL100W-1791110339): the create consumed the vendor field ladder and then failed on the parent reference \u2014 the parent table is blind (0 rows) for this API user, so no valid parent id exists to satisfy it (W-A6). The exact final vendor response is preserved verbatim in vendorEvidence (campaign receipt artifact, as recorded on disk).",
|
|
5872
|
-
"remedy": "provision a parent record in the Autotask UI first \u2014 the projects table is blind (0 rows) for this API user (W-A6), so no valid parent id can be read back; then retry the create with the real parent id."
|
|
6172
|
+
"remedy": "provision a parent record in the Autotask UI first \u2014 the projects table is blind (0 rows) for this API user (W-A6), so no valid parent id can be read back; then retry the create with the real parent id.",
|
|
6173
|
+
"requires": {
|
|
6174
|
+
"anyOf": [
|
|
6175
|
+
"productID",
|
|
6176
|
+
"billingCodeID"
|
|
6177
|
+
]
|
|
6178
|
+
}
|
|
5873
6179
|
},
|
|
5874
6180
|
"vendorEvidence": [
|
|
5875
6181
|
'{"error":true,"code":"SERVER_ERROR","category":"server","retryable":true,"httpStatus":500,"operation":"project_charges.create","suggestedAction":"Retry with backoff; the server error is transient.","correlationId":"664ab2ea-408f-4834-a331-eb5dd55ac557","message":"A productID or a billingCodeID must '
|
|
@@ -6942,6 +7248,27 @@ var RELATIONSHIP_MAP = {
|
|
|
6942
7248
|
},
|
|
6943
7249
|
"markerField": "name"
|
|
6944
7250
|
},
|
|
7251
|
+
"sales_orders": {
|
|
7252
|
+
"resource": "sales_orders",
|
|
7253
|
+
"apiEntity": "SalesOrder",
|
|
7254
|
+
"kind": "entity",
|
|
7255
|
+
"path": "SalesOrders",
|
|
7256
|
+
"parentScoped": false,
|
|
7257
|
+
"tier": "extended",
|
|
7258
|
+
"workflowResource": false,
|
|
7259
|
+
"group": "B",
|
|
7260
|
+
"parent": null,
|
|
7261
|
+
"children": [],
|
|
7262
|
+
"naturalKeys": {
|
|
7263
|
+
"hasSearch": false,
|
|
7264
|
+
"searchCovers": null,
|
|
7265
|
+
"findBy": []
|
|
7266
|
+
},
|
|
7267
|
+
"blindSurfaces": null,
|
|
7268
|
+
"zoneFacts": null,
|
|
7269
|
+
"deleteBoundary": null,
|
|
7270
|
+
"markerField": null
|
|
7271
|
+
},
|
|
6945
7272
|
"service_call_task_resources": {
|
|
6946
7273
|
"resource": "service_call_task_resources",
|
|
6947
7274
|
"apiEntity": "ServiceCallTaskResource",
|
|
@@ -7622,6 +7949,50 @@ var RELATIONSHIP_MAP = {
|
|
|
7622
7949
|
"deleteBoundary": null,
|
|
7623
7950
|
"markerField": null
|
|
7624
7951
|
},
|
|
7952
|
+
"tax_regions": {
|
|
7953
|
+
"resource": "tax_regions",
|
|
7954
|
+
"apiEntity": "TaxRegion",
|
|
7955
|
+
"kind": "entity",
|
|
7956
|
+
"path": "TaxRegions",
|
|
7957
|
+
"parentScoped": false,
|
|
7958
|
+
"tier": "advanced",
|
|
7959
|
+
"workflowResource": false,
|
|
7960
|
+
"group": "B",
|
|
7961
|
+
"parent": null,
|
|
7962
|
+
"children": [],
|
|
7963
|
+
"naturalKeys": {
|
|
7964
|
+
"hasSearch": false,
|
|
7965
|
+
"searchCovers": null,
|
|
7966
|
+
"findBy": []
|
|
7967
|
+
},
|
|
7968
|
+
"blindSurfaces": null,
|
|
7969
|
+
"zoneFacts": {
|
|
7970
|
+
"createGuidance": {
|
|
7971
|
+
"createOp": "tax_regions.create",
|
|
7972
|
+
"parentScoped": false,
|
|
7973
|
+
"liveProvenPrefix": [],
|
|
7974
|
+
"unproven": true,
|
|
7975
|
+
"blocker": {
|
|
7976
|
+
"kind": "unknown",
|
|
7977
|
+
"message": "never live-probed: this entity reached the plan on 2026-10-26 (feat/guidance-contract-027) after the stage-11 apply matrix closed, so no create has been attempted against a tenant. The vendor documents the model body (definitions.TaxRegionModel) and answers OperationResultModel, but acceptance of the body is unverified; the spec defines no DELETE on the entity's paths.",
|
|
7978
|
+
"remedy": "attempt one create against a non-production tenant (dry-run first), then promote createGuidance to kind ok with its liveProvenPrefix; a refusal arrives as a vendor 500 whose errors[] text names the failing field."
|
|
7979
|
+
},
|
|
7980
|
+
"vendorEvidence": [
|
|
7981
|
+
"api-docs.json: POST /V1.0/TaxRegions consumes definitions.TaxRegionModel and answers OperationResultModel \u2014 the entity defines no DELETE path."
|
|
7982
|
+
],
|
|
7983
|
+
"deleteBoundary": {
|
|
7984
|
+
"available": false,
|
|
7985
|
+
"note": "the vendor defines no DELETE for tax_regions (spec-derived) \u2014 a record cannot be removed or corrected through the API; cleanup is UI-only."
|
|
7986
|
+
},
|
|
7987
|
+
"zone": "ww29"
|
|
7988
|
+
}
|
|
7989
|
+
},
|
|
7990
|
+
"deleteBoundary": {
|
|
7991
|
+
"note": "the vendor defines no DELETE for tax_regions (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
7992
|
+
"proof": "spec-derived"
|
|
7993
|
+
},
|
|
7994
|
+
"markerField": null
|
|
7995
|
+
},
|
|
7625
7996
|
"ticket_additional_configuration_items": {
|
|
7626
7997
|
"resource": "ticket_additional_configuration_items",
|
|
7627
7998
|
"apiEntity": "TicketAdditionalConfigurationItem",
|
|
@@ -7911,7 +8282,13 @@ var RELATIONSHIP_MAP = {
|
|
|
7911
8282
|
"blocker": {
|
|
7912
8283
|
"kind": "blind-parent",
|
|
7913
8284
|
"message": "vendor 500 (stage-11 apply-matrix, marker FULL100W-1791110339): the create consumed the vendor field ladder and then failed on the parent reference \u2014 the parent table is blind (0 rows) for this API user, so no valid parent id exists to satisfy it (W-A6). The exact final vendor response is preserved verbatim in vendorEvidence (campaign receipt artifact, as recorded on disk).",
|
|
7914
|
-
"remedy": "provision a parent record in the Autotask UI first \u2014 the tickets table is blind (0 rows) for this API user (W-A6), so no valid parent id can be read back; then retry the create with the real parent id."
|
|
8285
|
+
"remedy": "provision a parent record in the Autotask UI first \u2014 the tickets table is blind (0 rows) for this API user (W-A6), so no valid parent id can be read back; then retry the create with the real parent id.",
|
|
8286
|
+
"requires": {
|
|
8287
|
+
"anyOf": [
|
|
8288
|
+
"productID",
|
|
8289
|
+
"billingCodeID"
|
|
8290
|
+
]
|
|
8291
|
+
}
|
|
7915
8292
|
},
|
|
7916
8293
|
"vendorEvidence": [
|
|
7917
8294
|
'{"error":true,"code":"SERVER_ERROR","category":"server","retryable":true,"httpStatus":500,"operation":"ticket_charges.create","suggestedAction":"Retry with backoff; the server error is transient.","correlationId":"b9b6939b-ccc5-4e9d-9ea2-e2f47d064f63","message":"A productID or a billingCodeID must b'
|
|
@@ -8977,6 +9354,7 @@ var BLIND_SURFACE_STAMPS = {
|
|
|
8977
9354
|
}
|
|
8978
9355
|
};
|
|
8979
9356
|
var DELETE_BOUNDARY_NOTES = {
|
|
9357
|
+
"billing_item_approval_levels": "the vendor defines no DELETE for billing_item_approval_levels (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 an approval level cannot be removed or corrected through the API; record cleanup is UI-only.",
|
|
8980
9358
|
"companies": "the vendor defines no DELETE for companies (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
8981
9359
|
"company_notes": "the vendor defines no DELETE for company_notes (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
8982
9360
|
"configuration_item_categories": "the vendor defines no DELETE for configuration_item_categories (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
@@ -9000,6 +9378,9 @@ var DELETE_BOUNDARY_NOTES = {
|
|
|
9000
9378
|
"expense_items": "the vendor defines no DELETE for expense_items (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
9001
9379
|
"expense_reports": "the vendor defines no DELETE for expense_reports (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
9002
9380
|
"opportunities": "the vendor defines no DELETE for opportunities (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
9381
|
+
"organizational_level1s": "the vendor defines no DELETE for organizational_level1s (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
9382
|
+
"organizational_level2s": "the vendor defines no DELETE for organizational_level2s (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
9383
|
+
"organizational_level_associations": "the vendor defines no DELETE for organizational_level_associations (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
9003
9384
|
"phases": "the vendor defines no DELETE for phases (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
9004
9385
|
"product_vendors": "the vendor defines no DELETE for product_vendors (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
9005
9386
|
"products": "the vendor defines no DELETE for products (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
@@ -9014,6 +9395,7 @@ var DELETE_BOUNDARY_NOTES = {
|
|
|
9014
9395
|
"roles": "the vendor defines no DELETE for roles (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
9015
9396
|
"services": "the vendor defines no DELETE for services (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
9016
9397
|
"tasks": "the vendor defines no DELETE for tasks (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
9398
|
+
"tax_regions": "the vendor defines no DELETE for tax_regions (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
9017
9399
|
"ticket_checklist_libraries": "the vendor defines no DELETE for ticket_checklist_libraries (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
9018
9400
|
"ticket_notes": "the vendor defines no DELETE for ticket_notes (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only.",
|
|
9019
9401
|
"tickets": "the vendor defines no DELETE for tickets (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only."
|
|
@@ -10515,6 +10897,18 @@ var BLIND_SURFACE_INVENTORY = {
|
|
|
10515
10897
|
"note": "billing_codes count/query are pinned blind in this zone (plan.blindSurfaces pin, byte-identical sentinel) \u2014 the discovery sweep confirmed 0 rows unfiltered (limit-2 read, marker FULL100-SEED-1791096521); get(id) is the authority.",
|
|
10516
10898
|
"proof": "live-verified"
|
|
10517
10899
|
},
|
|
10900
|
+
{
|
|
10901
|
+
"resource": "billing_item_approval_levels",
|
|
10902
|
+
"ops": [
|
|
10903
|
+
"count",
|
|
10904
|
+
"query"
|
|
10905
|
+
],
|
|
10906
|
+
"kind": "unknown",
|
|
10907
|
+
"unfilteredRows": null,
|
|
10908
|
+
"authority": "billing_item_approval_levels.get",
|
|
10909
|
+
"note": "billing_item_approval_levels was added to the plan on 2026-10-26 (feat/time-entry-approve) and has NEVER been swept \u2014 no discovery read has run against this zone, so the surface is unverified, not blind. get(id) is the authority for a specific record; query by timeEntryID is the intended read.",
|
|
10910
|
+
"proof": "spec-derived"
|
|
10911
|
+
},
|
|
10518
10912
|
{
|
|
10519
10913
|
"resource": "billing_items",
|
|
10520
10914
|
"ops": [
|
|
@@ -11175,6 +11569,18 @@ var BLIND_SURFACE_INVENTORY = {
|
|
|
11175
11569
|
"note": "ww29 discovery sweep (marker FULL100-SEED-1791096521, 2026-10-04): the unfiltered limit-2 read returned 1 row(s) \u2014 data-full for this API user (unfiltered reads are safe here; no blind class assigned).",
|
|
11176
11570
|
"proof": "discovery-sweep"
|
|
11177
11571
|
},
|
|
11572
|
+
{
|
|
11573
|
+
"resource": "invoice_templates",
|
|
11574
|
+
"ops": [
|
|
11575
|
+
"count",
|
|
11576
|
+
"query"
|
|
11577
|
+
],
|
|
11578
|
+
"kind": "unknown",
|
|
11579
|
+
"unfilteredRows": null,
|
|
11580
|
+
"authority": "invoice_templates.get",
|
|
11581
|
+
"note": "invoice_templates was added to the plan on 2026-10-26 (feat/guidance-contract-027) and has NEVER been swept \u2014 no discovery read has run against this zone, so the surface is unverified, not blind. get(id) is the authority for a specific record.",
|
|
11582
|
+
"proof": "spec-derived"
|
|
11583
|
+
},
|
|
11178
11584
|
{
|
|
11179
11585
|
"resource": "invoices",
|
|
11180
11586
|
"ops": [
|
|
@@ -11235,6 +11641,42 @@ var BLIND_SURFACE_INVENTORY = {
|
|
|
11235
11641
|
"note": "ww29 discovery sweep (marker FULL100-SEED-1791096521, 2026-10-04): the unfiltered limit-2 read returned 2 row(s) \u2014 data-full for this API user (unfiltered reads are safe here; no blind class assigned).",
|
|
11236
11642
|
"proof": "discovery-sweep"
|
|
11237
11643
|
},
|
|
11644
|
+
{
|
|
11645
|
+
"resource": "organizational_level1s",
|
|
11646
|
+
"ops": [
|
|
11647
|
+
"count",
|
|
11648
|
+
"query"
|
|
11649
|
+
],
|
|
11650
|
+
"kind": "unknown",
|
|
11651
|
+
"unfilteredRows": null,
|
|
11652
|
+
"authority": "organizational_level1s.get",
|
|
11653
|
+
"note": "organizational_level1s was added to the plan on 2026-10-26 (feat/guidance-contract-027) and has NEVER been swept \u2014 no discovery read has run against this zone, so the surface is unverified, not blind. get(id) is the authority for a specific record.",
|
|
11654
|
+
"proof": "spec-derived"
|
|
11655
|
+
},
|
|
11656
|
+
{
|
|
11657
|
+
"resource": "organizational_level2s",
|
|
11658
|
+
"ops": [
|
|
11659
|
+
"count",
|
|
11660
|
+
"query"
|
|
11661
|
+
],
|
|
11662
|
+
"kind": "unknown",
|
|
11663
|
+
"unfilteredRows": null,
|
|
11664
|
+
"authority": "organizational_level2s.get",
|
|
11665
|
+
"note": "organizational_level2s was added to the plan on 2026-10-26 (feat/guidance-contract-027) and has NEVER been swept \u2014 no discovery read has run against this zone, so the surface is unverified, not blind. get(id) is the authority for a specific record.",
|
|
11666
|
+
"proof": "spec-derived"
|
|
11667
|
+
},
|
|
11668
|
+
{
|
|
11669
|
+
"resource": "organizational_level_associations",
|
|
11670
|
+
"ops": [
|
|
11671
|
+
"count",
|
|
11672
|
+
"query"
|
|
11673
|
+
],
|
|
11674
|
+
"kind": "unknown",
|
|
11675
|
+
"unfilteredRows": null,
|
|
11676
|
+
"authority": "organizational_level_associations.get",
|
|
11677
|
+
"note": "organizational_level_associations was added to the plan on 2026-10-26 (feat/guidance-contract-027) and has NEVER been swept \u2014 no discovery read has run against this zone, so the surface is unverified, not blind. get(id) is the authority for a specific record.",
|
|
11678
|
+
"proof": "spec-derived"
|
|
11679
|
+
},
|
|
11238
11680
|
{
|
|
11239
11681
|
"resource": "phases",
|
|
11240
11682
|
"ops": [
|
|
@@ -11475,6 +11917,18 @@ var BLIND_SURFACE_INVENTORY = {
|
|
|
11475
11917
|
"note": "ww29 discovery sweep (marker FULL100-SEED-1791096521, 2026-10-04): the unfiltered limit-2 read returned 2 row(s) \u2014 data-full for this API user (unfiltered reads are safe here; no blind class assigned).",
|
|
11476
11918
|
"proof": "discovery-sweep"
|
|
11477
11919
|
},
|
|
11920
|
+
{
|
|
11921
|
+
"resource": "sales_orders",
|
|
11922
|
+
"ops": [
|
|
11923
|
+
"count",
|
|
11924
|
+
"query"
|
|
11925
|
+
],
|
|
11926
|
+
"kind": "unknown",
|
|
11927
|
+
"unfilteredRows": null,
|
|
11928
|
+
"authority": "sales_orders.get",
|
|
11929
|
+
"note": "sales_orders was added to the plan on 2026-10-26 (feat/guidance-contract-027) and has NEVER been swept \u2014 no discovery read has run against this zone, so the surface is unverified, not blind. get(id) is the authority for a specific record.",
|
|
11930
|
+
"proof": "spec-derived"
|
|
11931
|
+
},
|
|
11478
11932
|
{
|
|
11479
11933
|
"resource": "service_call_task_resources",
|
|
11480
11934
|
"ops": [
|
|
@@ -11679,6 +12133,18 @@ var BLIND_SURFACE_INVENTORY = {
|
|
|
11679
12133
|
"note": "ww29 discovery sweep (marker FULL100-SEED-1791096521, 2026-10-04): the unfiltered limit-2 read returned 2 row(s) \u2014 data-full for this API user (unfiltered reads are safe here; no blind class assigned).",
|
|
11680
12134
|
"proof": "discovery-sweep"
|
|
11681
12135
|
},
|
|
12136
|
+
{
|
|
12137
|
+
"resource": "tax_regions",
|
|
12138
|
+
"ops": [
|
|
12139
|
+
"count",
|
|
12140
|
+
"query"
|
|
12141
|
+
],
|
|
12142
|
+
"kind": "unknown",
|
|
12143
|
+
"unfilteredRows": null,
|
|
12144
|
+
"authority": "tax_regions.get",
|
|
12145
|
+
"note": "tax_regions was added to the plan on 2026-10-26 (feat/guidance-contract-027) and has NEVER been swept \u2014 no discovery read has run against this zone, so the surface is unverified, not blind. get(id) is the authority for a specific record.",
|
|
12146
|
+
"proof": "spec-derived"
|
|
12147
|
+
},
|
|
11682
12148
|
{
|
|
11683
12149
|
"resource": "ticket_additional_configuration_items",
|
|
11684
12150
|
"ops": [
|
|
@@ -11897,7 +12363,7 @@ var BLIND_SURFACE_INVENTORY = {
|
|
|
11897
12363
|
}
|
|
11898
12364
|
],
|
|
11899
12365
|
"counts": {
|
|
11900
|
-
"total":
|
|
12366
|
+
"total": 124,
|
|
11901
12367
|
"dataFull": 46,
|
|
11902
12368
|
"blind": 69,
|
|
11903
12369
|
"pinned": 6
|
|
@@ -11967,6 +12433,7 @@ var REACHABILITY_PROBE_DEFAULTS = {
|
|
|
11967
12433
|
"defaultTargets": [
|
|
11968
12434
|
"appointments",
|
|
11969
12435
|
"billing_codes",
|
|
12436
|
+
"billing_item_approval_levels",
|
|
11970
12437
|
"billing_items",
|
|
11971
12438
|
"change_request_links",
|
|
11972
12439
|
"classification_icons",
|
|
@@ -12002,8 +12469,12 @@ var REACHABILITY_PROBE_DEFAULTS = {
|
|
|
12002
12469
|
"currencies",
|
|
12003
12470
|
"expense_items",
|
|
12004
12471
|
"expense_reports",
|
|
12472
|
+
"invoice_templates",
|
|
12005
12473
|
"invoices",
|
|
12006
12474
|
"notification_history",
|
|
12475
|
+
"organizational_level1s",
|
|
12476
|
+
"organizational_level2s",
|
|
12477
|
+
"organizational_level_associations",
|
|
12007
12478
|
"product_vendors",
|
|
12008
12479
|
"products",
|
|
12009
12480
|
"project_charges",
|
|
@@ -12018,6 +12489,7 @@ var REACHABILITY_PROBE_DEFAULTS = {
|
|
|
12018
12489
|
"resource_roles",
|
|
12019
12490
|
"resource_skills",
|
|
12020
12491
|
"resources",
|
|
12492
|
+
"sales_orders",
|
|
12021
12493
|
"service_call_task_resources",
|
|
12022
12494
|
"service_call_tasks",
|
|
12023
12495
|
"service_call_ticket_resources",
|
|
@@ -12027,6 +12499,7 @@ var REACHABILITY_PROBE_DEFAULTS = {
|
|
|
12027
12499
|
"skills",
|
|
12028
12500
|
"subscription_periods",
|
|
12029
12501
|
"subscriptions",
|
|
12502
|
+
"tax_regions",
|
|
12030
12503
|
"ticket_change_request_approvals",
|
|
12031
12504
|
"ticket_charges",
|
|
12032
12505
|
"ticket_history",
|
|
@@ -12067,6 +12540,28 @@ var CREATE_GUIDANCE = {
|
|
|
12067
12540
|
},
|
|
12068
12541
|
"zone": "ww29"
|
|
12069
12542
|
},
|
|
12543
|
+
{
|
|
12544
|
+
"resource": "billing_item_approval_levels",
|
|
12545
|
+
"createOp": "billing_item_approval_levels.create",
|
|
12546
|
+
"parentScoped": false,
|
|
12547
|
+
"liveProvenPrefix": [],
|
|
12548
|
+
"unproven": true,
|
|
12549
|
+
"blocker": {
|
|
12550
|
+
"kind": "unknown",
|
|
12551
|
+
"message": "never live-probed: this entity reached the plan on 2026-10-26 (feat/time-entry-approve) after the stage-11 apply matrix closed, so no create has been attempted against a tenant. The vendor documents the conditions (timeEntryID and approvalResourceID must reference existing objects) and the side effect (TimeEntry.BillingApprovalLevelMostRecent is updated; approvalDateTime / approvalResourceID are not), but the acceptance of the model body is unverified.",
|
|
12552
|
+
"remedy": "attempt one create against a time entry in a non-production tenant (dry-run first), then promote createGuidance to kind ok with its liveProvenPrefix; a refusal arrives as a vendor 500 whose errors[] text names the failing field."
|
|
12553
|
+
},
|
|
12554
|
+
"vendorEvidence": [
|
|
12555
|
+
'Vendor help, BillingItemApprovalLevels entity page (fetched 2026-10-26): "describes a multi-level approval record for an Autotask time entry ... This option is only available through the REST API."',
|
|
12556
|
+
'Vendor help, BillingItemApprovalLevels entity page (fetched 2026-10-26): "When the BillingItemApprovalLevels entity is created, the TimeEntry.BillingApprovalLevelMostRecent field is updated, but approvalDateTime and approvalResourceID are not. Instead, the approvalDateTime and approvalResourceID fields are editable on the TimeEntry entity. Workaround: ... create the BillingItemApprovalLevel and then follow that call up with an update to the TimeEntry to set the BillingApprovalDateTime and BillingApprovalResourceID fields."',
|
|
12557
|
+
"api-docs.json: POST /V1.0/BillingItemApprovalLevels consumes definitions.BillingItemApprovalLevelModel and answers OperationResultModel \u2014 the entity defines no PUT, PATCH or DELETE path."
|
|
12558
|
+
],
|
|
12559
|
+
"deleteBoundary": {
|
|
12560
|
+
"available": false,
|
|
12561
|
+
"note": "the vendor defines no DELETE for billing_item_approval_levels (spec-derived) \u2014 an approval level cannot be removed or corrected through the API; record cleanup is UI-only."
|
|
12562
|
+
},
|
|
12563
|
+
"zone": "ww29"
|
|
12564
|
+
},
|
|
12070
12565
|
{
|
|
12071
12566
|
"resource": "change_request_links",
|
|
12072
12567
|
"createOp": "change_request_links.create",
|
|
@@ -12998,8 +13493,8 @@ var CREATE_GUIDANCE = {
|
|
|
12998
13493
|
"unproven": false,
|
|
12999
13494
|
"blocker": {
|
|
13000
13495
|
"kind": "ok",
|
|
13001
|
-
"message": "live-PROVEN 2026-10-06 (confirm-100, marker CONF100-1791187382): the W-A6 'blind parent' was companyID \u2014 an OWNED company satisfies it (seed 30132785). Proven contractType values: 1, 3 (Fixed Price), 4 (Block hours), 6 (Retainer), 7 (Recurring Services), 8 (PerTicket incident)
|
|
13002
|
-
"remedy": "live-proven on ww29 2026-10-06 (confirm-100, marker CONF100-1791187382) \u2014
|
|
13496
|
+
"message": "live-PROVEN 2026-10-06 (confirm-100, marker CONF100-1791187382): the W-A6 'blind parent' was companyID \u2014 an OWNED company satisfies it (seed 30132785). Proven contractType values: 1, 3 (Fixed Price), 4 (Block hours), 6 (Retainer), 7 (Recurring Services), 8 (PerTicket incident). The type-conditioned field gates are declared in requiresByValue / rejectedValues on this row (issue #219 N3) \u2014 they are no longer restated in prose here. Proven ids 30131842-30131847 (residue \u2014 no vendor DELETE for contracts).",
|
|
13497
|
+
"remedy": "live-proven on ww29 2026-10-06 (confirm-100, marker CONF100-1791187382) \u2014 send the body with the contractType you need and satisfy that value's requiresByValue gate (plus the contractPeriodType value it names); residue records are ledgered (.run/confirm-100-20261006/CONFIRMATION-LEDGER.md section E; UI cleanup)"
|
|
13003
13498
|
},
|
|
13004
13499
|
"vendorEvidence": [
|
|
13005
13500
|
'{"error":true,"code":"SERVER_ERROR","category":"server","retryable":true,"httpStatus":500,"operation":"contracts.create","suggestedAction":"Retry with backoff; the server error is transient.","correlationId":"25d4a730-6d6c-49ff-a038-96d3fd09165d","message":"Value does not exist for the required fiel',
|
|
@@ -13009,7 +13504,75 @@ var CREATE_GUIDANCE = {
|
|
|
13009
13504
|
"available": false,
|
|
13010
13505
|
"note": "the vendor defines no DELETE for contracts (spec-derived: the vendored api-docs.json defines no DELETE on the entity's paths) \u2014 a create cannot be undone through the API; cleanup is UI-only."
|
|
13011
13506
|
},
|
|
13012
|
-
"zone": "ww29"
|
|
13507
|
+
"zone": "ww29",
|
|
13508
|
+
"requiresByValue": [
|
|
13509
|
+
{
|
|
13510
|
+
"field": "contractType",
|
|
13511
|
+
"value": 1,
|
|
13512
|
+
"requires": {
|
|
13513
|
+
"allOf": [
|
|
13514
|
+
"estimatedRevenue",
|
|
13515
|
+
"estimatedHours",
|
|
13516
|
+
"estimatedCost"
|
|
13517
|
+
]
|
|
13518
|
+
}
|
|
13519
|
+
},
|
|
13520
|
+
{
|
|
13521
|
+
"field": "contractType",
|
|
13522
|
+
"value": 3,
|
|
13523
|
+
"requires": {
|
|
13524
|
+
"allOf": [
|
|
13525
|
+
"estimatedRevenue"
|
|
13526
|
+
]
|
|
13527
|
+
}
|
|
13528
|
+
},
|
|
13529
|
+
{
|
|
13530
|
+
"field": "contractType",
|
|
13531
|
+
"value": 4,
|
|
13532
|
+
"requires": {
|
|
13533
|
+
"allOf": [
|
|
13534
|
+
"estimatedRevenue"
|
|
13535
|
+
]
|
|
13536
|
+
}
|
|
13537
|
+
},
|
|
13538
|
+
{
|
|
13539
|
+
"field": "contractType",
|
|
13540
|
+
"value": 6,
|
|
13541
|
+
"requires": {
|
|
13542
|
+
"allOf": [
|
|
13543
|
+
"estimatedRevenue"
|
|
13544
|
+
]
|
|
13545
|
+
}
|
|
13546
|
+
},
|
|
13547
|
+
{
|
|
13548
|
+
"field": "contractType",
|
|
13549
|
+
"value": 7,
|
|
13550
|
+
"requires": {
|
|
13551
|
+
"allOf": [
|
|
13552
|
+
"contractPeriodType",
|
|
13553
|
+
"setupFee"
|
|
13554
|
+
]
|
|
13555
|
+
},
|
|
13556
|
+
"values": {
|
|
13557
|
+
"contractPeriodType": 2
|
|
13558
|
+
}
|
|
13559
|
+
},
|
|
13560
|
+
{
|
|
13561
|
+
"field": "contractType",
|
|
13562
|
+
"value": 8,
|
|
13563
|
+
"requires": {
|
|
13564
|
+
"allOf": [
|
|
13565
|
+
"estimatedRevenue"
|
|
13566
|
+
]
|
|
13567
|
+
}
|
|
13568
|
+
}
|
|
13569
|
+
],
|
|
13570
|
+
"rejectedValues": [
|
|
13571
|
+
{
|
|
13572
|
+
"field": "contractType",
|
|
13573
|
+
"value": 5
|
|
13574
|
+
}
|
|
13575
|
+
]
|
|
13013
13576
|
},
|
|
13014
13577
|
{
|
|
13015
13578
|
"resource": "departments",
|
|
@@ -13255,6 +13818,66 @@ var CREATE_GUIDANCE = {
|
|
|
13255
13818
|
},
|
|
13256
13819
|
"zone": "ww29"
|
|
13257
13820
|
},
|
|
13821
|
+
{
|
|
13822
|
+
"resource": "organizational_level1s",
|
|
13823
|
+
"createOp": "organizational_level1s.create",
|
|
13824
|
+
"parentScoped": false,
|
|
13825
|
+
"liveProvenPrefix": [],
|
|
13826
|
+
"unproven": true,
|
|
13827
|
+
"blocker": {
|
|
13828
|
+
"kind": "unknown",
|
|
13829
|
+
"message": "never live-probed: this entity reached the plan on 2026-10-26 (feat/guidance-contract-027) after the stage-11 apply matrix closed, so no create has been attempted against a tenant. The vendor documents the model body (definitions.OrganizationalLevel1Model) and answers OperationResultModel, but acceptance of the body is unverified; the spec defines no DELETE on the entity's paths.",
|
|
13830
|
+
"remedy": "attempt one create against a non-production tenant (dry-run first), then promote createGuidance to kind ok with its liveProvenPrefix; a refusal arrives as a vendor 500 whose errors[] text names the failing field."
|
|
13831
|
+
},
|
|
13832
|
+
"vendorEvidence": [
|
|
13833
|
+
"api-docs.json: POST /V1.0/OrganizationalLevel1s consumes definitions.OrganizationalLevel1Model and answers OperationResultModel \u2014 the entity defines no DELETE path."
|
|
13834
|
+
],
|
|
13835
|
+
"deleteBoundary": {
|
|
13836
|
+
"available": false,
|
|
13837
|
+
"note": "the vendor defines no DELETE for organizational_level1s (spec-derived) \u2014 a record cannot be removed or corrected through the API; cleanup is UI-only."
|
|
13838
|
+
},
|
|
13839
|
+
"zone": "ww29"
|
|
13840
|
+
},
|
|
13841
|
+
{
|
|
13842
|
+
"resource": "organizational_level2s",
|
|
13843
|
+
"createOp": "organizational_level2s.create",
|
|
13844
|
+
"parentScoped": false,
|
|
13845
|
+
"liveProvenPrefix": [],
|
|
13846
|
+
"unproven": true,
|
|
13847
|
+
"blocker": {
|
|
13848
|
+
"kind": "unknown",
|
|
13849
|
+
"message": "never live-probed: this entity reached the plan on 2026-10-26 (feat/guidance-contract-027) after the stage-11 apply matrix closed, so no create has been attempted against a tenant. The vendor documents the model body (definitions.OrganizationalLevel2Model) and answers OperationResultModel, but acceptance of the body is unverified; the spec defines no DELETE on the entity's paths.",
|
|
13850
|
+
"remedy": "attempt one create against a non-production tenant (dry-run first), then promote createGuidance to kind ok with its liveProvenPrefix; a refusal arrives as a vendor 500 whose errors[] text names the failing field."
|
|
13851
|
+
},
|
|
13852
|
+
"vendorEvidence": [
|
|
13853
|
+
"api-docs.json: POST /V1.0/OrganizationalLevel2s consumes definitions.OrganizationalLevel2Model and answers OperationResultModel \u2014 the entity defines no DELETE path."
|
|
13854
|
+
],
|
|
13855
|
+
"deleteBoundary": {
|
|
13856
|
+
"available": false,
|
|
13857
|
+
"note": "the vendor defines no DELETE for organizational_level2s (spec-derived) \u2014 a record cannot be removed or corrected through the API; cleanup is UI-only."
|
|
13858
|
+
},
|
|
13859
|
+
"zone": "ww29"
|
|
13860
|
+
},
|
|
13861
|
+
{
|
|
13862
|
+
"resource": "organizational_level_associations",
|
|
13863
|
+
"createOp": "organizational_level_associations.create",
|
|
13864
|
+
"parentScoped": false,
|
|
13865
|
+
"liveProvenPrefix": [],
|
|
13866
|
+
"unproven": true,
|
|
13867
|
+
"blocker": {
|
|
13868
|
+
"kind": "unknown",
|
|
13869
|
+
"message": "never live-probed: this entity reached the plan on 2026-10-26 (feat/guidance-contract-027) after the stage-11 apply matrix closed, so no create has been attempted against a tenant. The vendor documents the model body (definitions.OrganizationalLevelAssociationModel) and answers OperationResultModel, but acceptance of the body is unverified; the spec defines no DELETE on the entity's paths.",
|
|
13870
|
+
"remedy": "attempt one create against a non-production tenant (dry-run first), then promote createGuidance to kind ok with its liveProvenPrefix; a refusal arrives as a vendor 500 whose errors[] text names the failing field."
|
|
13871
|
+
},
|
|
13872
|
+
"vendorEvidence": [
|
|
13873
|
+
"api-docs.json: POST /V1.0/OrganizationalLevelAssociations consumes definitions.OrganizationalLevelAssociationModel and answers OperationResultModel \u2014 the entity defines no DELETE path."
|
|
13874
|
+
],
|
|
13875
|
+
"deleteBoundary": {
|
|
13876
|
+
"available": false,
|
|
13877
|
+
"note": "the vendor defines no DELETE for organizational_level_associations (spec-derived) \u2014 a record cannot be removed or corrected through the API; cleanup is UI-only."
|
|
13878
|
+
},
|
|
13879
|
+
"zone": "ww29"
|
|
13880
|
+
},
|
|
13258
13881
|
{
|
|
13259
13882
|
"resource": "phases",
|
|
13260
13883
|
"createOp": "phases.create",
|
|
@@ -13336,7 +13959,13 @@ var CREATE_GUIDANCE = {
|
|
|
13336
13959
|
"blocker": {
|
|
13337
13960
|
"kind": "blind-parent",
|
|
13338
13961
|
"message": "vendor 500 (stage-11 apply-matrix, marker FULL100W-1791110339): the create consumed the vendor field ladder and then failed on the parent reference \u2014 the parent table is blind (0 rows) for this API user, so no valid parent id exists to satisfy it (W-A6). The exact final vendor response is preserved verbatim in vendorEvidence (campaign receipt artifact, as recorded on disk).",
|
|
13339
|
-
"remedy": "provision a parent record in the Autotask UI first \u2014 the projects table is blind (0 rows) for this API user (W-A6), so no valid parent id can be read back; then retry the create with the real parent id."
|
|
13962
|
+
"remedy": "provision a parent record in the Autotask UI first \u2014 the projects table is blind (0 rows) for this API user (W-A6), so no valid parent id can be read back; then retry the create with the real parent id.",
|
|
13963
|
+
"requires": {
|
|
13964
|
+
"anyOf": [
|
|
13965
|
+
"productID",
|
|
13966
|
+
"billingCodeID"
|
|
13967
|
+
]
|
|
13968
|
+
}
|
|
13340
13969
|
},
|
|
13341
13970
|
"vendorEvidence": [
|
|
13342
13971
|
'{"error":true,"code":"SERVER_ERROR","category":"server","retryable":true,"httpStatus":500,"operation":"project_charges.create","suggestedAction":"Retry with backoff; the server error is transient.","correlationId":"664ab2ea-408f-4834-a331-eb5dd55ac557","message":"A productID or a billingCodeID must '
|
|
@@ -13840,6 +14469,26 @@ var CREATE_GUIDANCE = {
|
|
|
13840
14469
|
},
|
|
13841
14470
|
"zone": "ww29"
|
|
13842
14471
|
},
|
|
14472
|
+
{
|
|
14473
|
+
"resource": "tax_regions",
|
|
14474
|
+
"createOp": "tax_regions.create",
|
|
14475
|
+
"parentScoped": false,
|
|
14476
|
+
"liveProvenPrefix": [],
|
|
14477
|
+
"unproven": true,
|
|
14478
|
+
"blocker": {
|
|
14479
|
+
"kind": "unknown",
|
|
14480
|
+
"message": "never live-probed: this entity reached the plan on 2026-10-26 (feat/guidance-contract-027) after the stage-11 apply matrix closed, so no create has been attempted against a tenant. The vendor documents the model body (definitions.TaxRegionModel) and answers OperationResultModel, but acceptance of the body is unverified; the spec defines no DELETE on the entity's paths.",
|
|
14481
|
+
"remedy": "attempt one create against a non-production tenant (dry-run first), then promote createGuidance to kind ok with its liveProvenPrefix; a refusal arrives as a vendor 500 whose errors[] text names the failing field."
|
|
14482
|
+
},
|
|
14483
|
+
"vendorEvidence": [
|
|
14484
|
+
"api-docs.json: POST /V1.0/TaxRegions consumes definitions.TaxRegionModel and answers OperationResultModel \u2014 the entity defines no DELETE path."
|
|
14485
|
+
],
|
|
14486
|
+
"deleteBoundary": {
|
|
14487
|
+
"available": false,
|
|
14488
|
+
"note": "the vendor defines no DELETE for tax_regions (spec-derived) \u2014 a record cannot be removed or corrected through the API; cleanup is UI-only."
|
|
14489
|
+
},
|
|
14490
|
+
"zone": "ww29"
|
|
14491
|
+
},
|
|
13843
14492
|
{
|
|
13844
14493
|
"resource": "ticket_additional_configuration_items",
|
|
13845
14494
|
"createOp": "ticket_additional_configuration_items.create",
|
|
@@ -13945,7 +14594,13 @@ var CREATE_GUIDANCE = {
|
|
|
13945
14594
|
"blocker": {
|
|
13946
14595
|
"kind": "blind-parent",
|
|
13947
14596
|
"message": "vendor 500 (stage-11 apply-matrix, marker FULL100W-1791110339): the create consumed the vendor field ladder and then failed on the parent reference \u2014 the parent table is blind (0 rows) for this API user, so no valid parent id exists to satisfy it (W-A6). The exact final vendor response is preserved verbatim in vendorEvidence (campaign receipt artifact, as recorded on disk).",
|
|
13948
|
-
"remedy": "provision a parent record in the Autotask UI first \u2014 the tickets table is blind (0 rows) for this API user (W-A6), so no valid parent id can be read back; then retry the create with the real parent id."
|
|
14597
|
+
"remedy": "provision a parent record in the Autotask UI first \u2014 the tickets table is blind (0 rows) for this API user (W-A6), so no valid parent id can be read back; then retry the create with the real parent id.",
|
|
14598
|
+
"requires": {
|
|
14599
|
+
"anyOf": [
|
|
14600
|
+
"productID",
|
|
14601
|
+
"billingCodeID"
|
|
14602
|
+
]
|
|
14603
|
+
}
|
|
13949
14604
|
},
|
|
13950
14605
|
"vendorEvidence": [
|
|
13951
14606
|
'{"error":true,"code":"SERVER_ERROR","category":"server","retryable":true,"httpStatus":500,"operation":"ticket_charges.create","suggestedAction":"Retry with backoff; the server error is transient.","correlationId":"b9b6939b-ccc5-4e9d-9ea2-e2f47d064f63","message":"A productID or a billingCodeID must b'
|
|
@@ -14168,7 +14823,30 @@ var CREATE_GUIDANCE = {
|
|
|
14168
14823
|
"available": true,
|
|
14169
14824
|
"note": null
|
|
14170
14825
|
},
|
|
14171
|
-
"zone": "ww29"
|
|
14826
|
+
"zone": "ww29",
|
|
14827
|
+
"derived": [
|
|
14828
|
+
{
|
|
14829
|
+
"field": "hoursWorked",
|
|
14830
|
+
"rule": "elapsed(startDateTime,endDateTime)"
|
|
14831
|
+
},
|
|
14832
|
+
{
|
|
14833
|
+
"field": "timeEntryType",
|
|
14834
|
+
"rule": "parent"
|
|
14835
|
+
},
|
|
14836
|
+
{
|
|
14837
|
+
"field": "contractID",
|
|
14838
|
+
"rule": "parent"
|
|
14839
|
+
},
|
|
14840
|
+
{
|
|
14841
|
+
"field": "internalBillingCodeID",
|
|
14842
|
+
"rule": "mirror(billingCodeID)"
|
|
14843
|
+
},
|
|
14844
|
+
{
|
|
14845
|
+
"field": "billingApprovalLevelMostRecent",
|
|
14846
|
+
"rule": "external",
|
|
14847
|
+
"writableRoute": "billing_item_approval_levels.create"
|
|
14848
|
+
}
|
|
14849
|
+
]
|
|
14172
14850
|
},
|
|
14173
14851
|
{
|
|
14174
14852
|
"resource": "time_entry_attachments",
|
|
@@ -14197,7 +14875,7 @@ var CREATE_GUIDANCE = {
|
|
|
14197
14875
|
}
|
|
14198
14876
|
],
|
|
14199
14877
|
"counts": {
|
|
14200
|
-
"total":
|
|
14878
|
+
"total": 97,
|
|
14201
14879
|
"byKind": {
|
|
14202
14880
|
"ok": 31,
|
|
14203
14881
|
"blind-reference": 16,
|
|
@@ -14207,7 +14885,7 @@ var CREATE_GUIDANCE = {
|
|
|
14207
14885
|
"resource-role-pair": 2,
|
|
14208
14886
|
"delete-absent": 8,
|
|
14209
14887
|
"non-mutable": 0,
|
|
14210
|
-
"unknown":
|
|
14888
|
+
"unknown": 17
|
|
14211
14889
|
}
|
|
14212
14890
|
}
|
|
14213
14891
|
};
|
|
@@ -14507,6 +15185,13 @@ var UNTRUSTED_FIELDS_BY_RESOURCE = {
|
|
|
14507
15185
|
"holidays": [
|
|
14508
15186
|
"holidayName"
|
|
14509
15187
|
],
|
|
15188
|
+
"invoice_templates": [
|
|
15189
|
+
"coveredByBlockRetainerContractLabel",
|
|
15190
|
+
"coveredByRecurringServiceFixedPricePerTicketContractLabel",
|
|
15191
|
+
"name",
|
|
15192
|
+
"nonBillableLaborLabel",
|
|
15193
|
+
"rateCostExpression"
|
|
15194
|
+
],
|
|
14510
15195
|
"invoices": [
|
|
14511
15196
|
"comments",
|
|
14512
15197
|
"taxRegionName"
|
|
@@ -14555,6 +15240,14 @@ var UNTRUSTED_FIELDS_BY_RESOURCE = {
|
|
|
14555
15240
|
"name",
|
|
14556
15241
|
"nickname"
|
|
14557
15242
|
],
|
|
15243
|
+
"organizational_level1s": [
|
|
15244
|
+
"description",
|
|
15245
|
+
"name"
|
|
15246
|
+
],
|
|
15247
|
+
"organizational_level2s": [
|
|
15248
|
+
"description",
|
|
15249
|
+
"name"
|
|
15250
|
+
],
|
|
14558
15251
|
"products": [
|
|
14559
15252
|
"UDF1",
|
|
14560
15253
|
"UDF10",
|
|
@@ -14692,6 +15385,34 @@ var UNTRUSTED_FIELDS_BY_RESOURCE = {
|
|
|
14692
15385
|
"description",
|
|
14693
15386
|
"name"
|
|
14694
15387
|
],
|
|
15388
|
+
"sales_orders": [
|
|
15389
|
+
"UDF1",
|
|
15390
|
+
"UDF10",
|
|
15391
|
+
"UDF11",
|
|
15392
|
+
"UDF12",
|
|
15393
|
+
"UDF13",
|
|
15394
|
+
"UDF14",
|
|
15395
|
+
"UDF15",
|
|
15396
|
+
"UDF16",
|
|
15397
|
+
"UDF17",
|
|
15398
|
+
"UDF18",
|
|
15399
|
+
"UDF19",
|
|
15400
|
+
"UDF2",
|
|
15401
|
+
"UDF20",
|
|
15402
|
+
"UDF3",
|
|
15403
|
+
"UDF4",
|
|
15404
|
+
"UDF5",
|
|
15405
|
+
"UDF6",
|
|
15406
|
+
"UDF7",
|
|
15407
|
+
"UDF8",
|
|
15408
|
+
"UDF9",
|
|
15409
|
+
"additionalBillToAddressInformation",
|
|
15410
|
+
"additionalShipToAddressInformation",
|
|
15411
|
+
"billToPostalCode",
|
|
15412
|
+
"shipToCity",
|
|
15413
|
+
"shipToState",
|
|
15414
|
+
"title"
|
|
15415
|
+
],
|
|
14695
15416
|
"service_calls": [
|
|
14696
15417
|
"description"
|
|
14697
15418
|
],
|
|
@@ -14766,6 +15487,9 @@ var UNTRUSTED_FIELDS_BY_RESOURCE = {
|
|
|
14766
15487
|
"tags": [
|
|
14767
15488
|
"label"
|
|
14768
15489
|
],
|
|
15490
|
+
"tax_regions": [
|
|
15491
|
+
"name"
|
|
15492
|
+
],
|
|
14769
15493
|
"ticket_attachments": [
|
|
14770
15494
|
"title"
|
|
14771
15495
|
],
|
|
@@ -16288,6 +17012,38 @@ async function expandResourceNames(client, ids, opts = {}) {
|
|
|
16288
17012
|
return { results, resolved, blind, failed };
|
|
16289
17013
|
}
|
|
16290
17014
|
|
|
17015
|
+
// src/operations/entityType.ts
|
|
17016
|
+
function buildEntityTypeMap() {
|
|
17017
|
+
const exact = {};
|
|
17018
|
+
for (const [resource, entry] of Object.entries(RELATIONSHIP_MAP)) {
|
|
17019
|
+
const apiEntity = entry.apiEntity;
|
|
17020
|
+
if (typeof apiEntity !== "string" || apiEntity === "") continue;
|
|
17021
|
+
if (exact[apiEntity] === void 0) exact[apiEntity] = resource;
|
|
17022
|
+
}
|
|
17023
|
+
const aliases = {};
|
|
17024
|
+
for (const [apiEntity, resource] of Object.entries(exact)) {
|
|
17025
|
+
if (!apiEntity.endsWith("s") || apiEntity.endsWith("ss")) continue;
|
|
17026
|
+
const singular = apiEntity.slice(0, -1);
|
|
17027
|
+
if (exact[singular] !== void 0 || aliases[singular] !== void 0) continue;
|
|
17028
|
+
aliases[singular] = resource;
|
|
17029
|
+
}
|
|
17030
|
+
return { ...exact, ...aliases };
|
|
17031
|
+
}
|
|
17032
|
+
var ENTITY_TYPE_TO_RESOURCE = buildEntityTypeMap();
|
|
17033
|
+
var ENUMERABLE_RESOURCES = new Set(
|
|
17034
|
+
CAPABILITIES.filter((rec) => rec.resource !== "operations" && (rec.operation === "query" || rec.operation === "get")).map(
|
|
17035
|
+
(rec) => rec.resource
|
|
17036
|
+
)
|
|
17037
|
+
);
|
|
17038
|
+
function resourceForEntityType(entityType) {
|
|
17039
|
+
if (typeof entityType !== "string" || entityType === "") return null;
|
|
17040
|
+
return ENTITY_TYPE_TO_RESOURCE[entityType] ?? null;
|
|
17041
|
+
}
|
|
17042
|
+
function isEnumerableResource(resource) {
|
|
17043
|
+
if (typeof resource !== "string" || resource === "") return false;
|
|
17044
|
+
return ENUMERABLE_RESOURCES.has(resource);
|
|
17045
|
+
}
|
|
17046
|
+
|
|
16291
17047
|
// src/operations/types.ts
|
|
16292
17048
|
var WORKFLOW_RESOURCES = [
|
|
16293
17049
|
"companies",
|
|
@@ -16301,24 +17057,36 @@ var WORKFLOW_RESOURCES = [
|
|
|
16301
17057
|
var MAX_FIELD_CATALOG_WIRE = 60;
|
|
16302
17058
|
var FIELD_CATALOG_HONESTY_NOTE = "Live field metadata reports the SHAPE of a field (existence, requiredness, type, maxLength, read-only, queryable, picklist-ness) as FLAGS and NAMES: picklist-ness as a flag (isPickList) and picklist field names (picklistFields). With the opt-in `labels: true`, picklist rows carry the vendor's exposed picklist VALUES (labels next to each value); without it the op serves no VALUES. It cannot resolve a picklist VALUE the vendor does not expose to this API user (the W-A4 wall \u2014 e.g. the attachments Type picklist): retrying the catalog will not surface a withheld value; that gap is vendor-side, not a client defect.";
|
|
16303
17059
|
var FIELD_CATALOG_OPT_KEYS = ["resources", "include", "fresh", "fields", "labels"];
|
|
16304
|
-
function projectFieldRow(raw, labels = false) {
|
|
17060
|
+
function projectFieldRow(raw, labels = false, udf = false) {
|
|
16305
17061
|
const r = typeof raw === "object" && raw !== null ? raw : {};
|
|
16306
17062
|
const name = typeof r.name === "string" ? r.name : "";
|
|
16307
17063
|
const type = typeof r.dataType === "string" ? r.dataType : typeof r.type === "string" ? r.type : "";
|
|
16308
17064
|
const values = labels && r.isPickList === true && Array.isArray(r.picklistValues) && r.picklistValues.length > 0 ? r.picklistValues : void 0;
|
|
17065
|
+
const referenceEntityType = typeof r.referenceEntityType === "string" ? r.referenceEntityType : "";
|
|
17066
|
+
const targetResource = resourceForEntityType(referenceEntityType);
|
|
16309
17067
|
return {
|
|
16310
17068
|
name,
|
|
16311
17069
|
...typeof r.label === "string" && r.label !== "" ? { label: r.label } : {},
|
|
16312
17070
|
type,
|
|
16313
17071
|
isRequired: r.isRequired === true,
|
|
16314
17072
|
isReadOnly: r.isReadOnly === true,
|
|
16315
|
-
|
|
17073
|
+
// Issue #219 N7: a UDF row never serves the vendor's isQueryable (it is
|
|
17074
|
+
// true for UDFs while a plain filter on a UDF name is refused); it serves
|
|
17075
|
+
// the marker the filter actually needs.
|
|
17076
|
+
...udf ? { filterable: "udf-marker" } : { isQueryable: r.isQueryable === true },
|
|
16316
17077
|
isPickList: r.isPickList === true,
|
|
17078
|
+
...isObjectOrArrayType(type) ? { writeShape: "replace-all" } : {},
|
|
16317
17079
|
maxLength: typeof r.length === "number" ? r.length : null,
|
|
16318
|
-
referenceEntityType
|
|
17080
|
+
referenceEntityType,
|
|
17081
|
+
targetResource,
|
|
17082
|
+
targetEnumerable: isEnumerableResource(targetResource),
|
|
16319
17083
|
...values !== void 0 ? { picklistValues: values } : {}
|
|
16320
17084
|
};
|
|
16321
17085
|
}
|
|
17086
|
+
function isObjectOrArrayType(type) {
|
|
17087
|
+
const t = type.trim().toLowerCase();
|
|
17088
|
+
return t === "object" || t === "array" || t === "collection" || t.endsWith("[]");
|
|
17089
|
+
}
|
|
16322
17090
|
function exposesPicklistValues(raw) {
|
|
16323
17091
|
const r = typeof raw === "object" && raw !== null ? raw : {};
|
|
16324
17092
|
return Array.isArray(r.picklistValues) && r.picklistValues.length > 0;
|
|
@@ -16348,6 +17116,27 @@ function capabilitySets() {
|
|
|
16348
17116
|
}
|
|
16349
17117
|
return { fieldOps, udfOps, resources };
|
|
16350
17118
|
}
|
|
17119
|
+
var derivedIndex = null;
|
|
17120
|
+
function derivedFieldsFor(resource) {
|
|
17121
|
+
if (derivedIndex === null) {
|
|
17122
|
+
derivedIndex = /* @__PURE__ */ new Map();
|
|
17123
|
+
for (const rec of CAPABILITIES) {
|
|
17124
|
+
const declared = rec.metadata?.derivedFields;
|
|
17125
|
+
if (!Array.isArray(declared) || derivedIndex.has(rec.resource)) continue;
|
|
17126
|
+
const rows = [];
|
|
17127
|
+
for (const row of declared) {
|
|
17128
|
+
if (typeof row?.field !== "string" || typeof row.rule !== "string") continue;
|
|
17129
|
+
rows.push({
|
|
17130
|
+
field: row.field,
|
|
17131
|
+
rule: row.rule,
|
|
17132
|
+
...typeof row.writableRoute === "string" ? { writableRoute: row.writableRoute } : {}
|
|
17133
|
+
});
|
|
17134
|
+
}
|
|
17135
|
+
derivedIndex.set(rec.resource, rows);
|
|
17136
|
+
}
|
|
17137
|
+
}
|
|
17138
|
+
return derivedIndex.get(resource) ?? [];
|
|
17139
|
+
}
|
|
16351
17140
|
function apiEntityFor(rec) {
|
|
16352
17141
|
const m = /^GET \/V1\.0\/([^/]+)\/entityInformation\/fields$/.exec(rec.endpoint ?? "");
|
|
16353
17142
|
if (m === null) {
|
|
@@ -16477,6 +17266,8 @@ async function sweepResource(ctx, resource, tally) {
|
|
|
16477
17266
|
resource,
|
|
16478
17267
|
apiEntity,
|
|
16479
17268
|
udfCapable: ctx.udfOps.has(resource),
|
|
17269
|
+
// Issue #219 N7: the UDF surface is declared with the mechanism, not a boolean.
|
|
17270
|
+
...ctx.udfOps.has(resource) ? { udfFilter: "udf-marker", udfWriteShape: "merge" } : {},
|
|
16480
17271
|
unmatchedFields: [],
|
|
16481
17272
|
required: [],
|
|
16482
17273
|
readOnly: [],
|
|
@@ -16489,7 +17280,7 @@ async function sweepResource(ctx, resource, tally) {
|
|
|
16489
17280
|
const fetches = kindFetches(holder, resource);
|
|
16490
17281
|
if (fresh) cache?.invalidate(resource);
|
|
16491
17282
|
const projectList = (kind, list) => {
|
|
16492
|
-
const projected = list.map((f) => projectFieldRow(f, labels));
|
|
17283
|
+
const projected = list.map((f) => projectFieldRow(f, labels, kind === "udf"));
|
|
16493
17284
|
if (kind === "fields") applyFieldsFilter(projected, fieldsFilter, row);
|
|
16494
17285
|
else row.udf = projected;
|
|
16495
17286
|
for (const f of list) if (exposesPicklistValues(f)) tally.anyPicklistValues = true;
|
|
@@ -16529,6 +17320,19 @@ async function sweepResource(ctx, resource, tally) {
|
|
|
16529
17320
|
}
|
|
16530
17321
|
}
|
|
16531
17322
|
row.cache = allCached ? { hit: true, age: ages.length > 0 ? Math.max(...ages) : 0 } : { hit: false, age: null };
|
|
17323
|
+
const declared = derivedFieldsFor(resource);
|
|
17324
|
+
if (declared.length > 0) {
|
|
17325
|
+
const byField = new Map(declared.map((d) => [d.field, d]));
|
|
17326
|
+
row.derivedFields = declared;
|
|
17327
|
+
for (const field of row.fields ?? []) {
|
|
17328
|
+
const derivation = byField.get(field.name);
|
|
17329
|
+
if (derivation === void 0) continue;
|
|
17330
|
+
field.derived = {
|
|
17331
|
+
rule: derivation.rule,
|
|
17332
|
+
...derivation.writableRoute !== void 0 ? { writableRoute: derivation.writableRoute } : {}
|
|
17333
|
+
};
|
|
17334
|
+
}
|
|
17335
|
+
}
|
|
16532
17336
|
return row;
|
|
16533
17337
|
}
|
|
16534
17338
|
async function fieldCatalog(client, opts) {
|
|
@@ -16752,6 +17556,7 @@ async function resolveCompositeNames(http, plan, opts = {}) {
|
|
|
16752
17556
|
var MODEL_FIELD_SETS = {
|
|
16753
17557
|
"appointments": ["id", "createDateTime", "creatorResourceID", "description", "endDateTime", "resourceID", "startDateTime", "title", "updateDateTime"],
|
|
16754
17558
|
"billing_codes": ["id", "afterHoursWorkType", "billingCodeType", "department", "description", "externalNumber", "generalLedgerAccount", "isActive", "isExcludedFromNewContracts", "markupRate", "name", "taxCategoryID", "unitCost", "unitPrice", "useType"],
|
|
17559
|
+
"billing_item_approval_levels": ["id", "approvalDateTime", "approvalLevel", "approvalResourceID", "timeEntryID"],
|
|
16755
17560
|
"billing_items": ["id", "accountManagerWhenApprovedID", "billingCodeID", "billingItemType", "companyID", "configurationItemID", "contractBlockID", "contractChargeID", "contractID", "contractServiceAdjustmentID", "contractServiceBundleAdjustmentID", "contractServiceBundleID", "contractServiceBundlePeriodID", "contractServiceID", "contractServicePeriodID", "description", "expenseItemID", "extendedPrice", "internalCurrencyExtendedPrice", "internalCurrencyRate", "internalCurrencyTaxDollars", "internalCurrencyTotalAmount", "invoiceID", "itemApproverID", "itemDate", "itemName", "lineItemFullDescription", "lineItemGroupDescription", "milestoneID", "nonBillable", "organizationalLevelAssociationID", "ourCost", "postedDate", "postedOnTime", "projectChargeID", "projectID", "purchaseOrderNumber", "quantity", "rate", "roleID", "serviceBundleID", "serviceID", "sortOrderID", "subType", "taskID", "taxDollars", "ticketChargeID", "ticketID", "timeEntryID", "totalAmount", "vendorID", "webServiceDate"],
|
|
16756
17561
|
"change_request_links": ["id", "changeRequestTicketID", "problemOrIncidentTicketID"],
|
|
16757
17562
|
"checklist_libraries": ["id", "description", "entityType", "isActive", "name"],
|
|
@@ -16807,11 +17612,15 @@ var MODEL_FIELD_SETS = {
|
|
|
16807
17612
|
"holiday_sets": ["id", "holidaySetDescription", "holidaySetName"],
|
|
16808
17613
|
"holidays": ["id", "holidayDate", "holidayName", "holidaySetID", "soapParentPropertyId"],
|
|
16809
17614
|
"inventory_products": ["id", "availableUnits", "backOrderQuantity", "bin", "createDateTime", "createdByResourceID", "inventoryLocationID", "onHandUnits", "pickedUnits", "productID", "quantityMaximum", "quantityMinimum", "referenceNumber", "reservedUnits", "unitsOnOrder"],
|
|
17615
|
+
"invoice_templates": ["id", "coveredByBlockRetainerContractLabel", "coveredByRecurringServiceFixedPricePerTicketContractLabel", "currencyNegativeFormat", "currencyPositiveFormat", "dateFormat", "displayFixedPriceContractLabor", "displayRecurringServiceContractLabor", "displaySeparateLineItemForEachTax", "displayTaxCategory", "displayTaxCategorySuperscripts", "displayZeroAmountRecurringServicesAndBundles", "groupBy", "itemizeItemsInEachGroup", "itemizeServicesAndBundles", "name", "nonBillableLaborLabel", "numberFormat", "pageLayout", "pageNumberFormat", "paymentTerms", "rateCostExpression", "showGridHeader", "showVerticalGridLines", "sortBy", "timeFormat"],
|
|
16810
17616
|
"invoices": ["id", "batchID", "comments", "companyID", "createDateTime", "creatorResourceID", "dueDate", "fromDate", "invoiceDateTime", "invoiceEditorTemplateID", "invoiceNumber", "invoiceTotal", "isVoided", "orderNumber", "paidDate", "paymentTerm", "taxGroup", "taxRegionName", "toDate", "totalTaxValue", "voidedByResourceID", "voidedDate", "webServiceDate"],
|
|
16811
17617
|
"notification_history": ["id", "companyID", "entityNumber", "entityTitle", "initiatingContactID", "initiatingResourceID", "isActive", "isDeleted", "isTemplateJob", "notificationHistoryTypeID", "notificationSentTime", "opportunityID", "projectID", "quoteID", "recipientDisplayName", "recipientEmailAddress", "taskID", "templateName", "ticketID", "timeEntryID"],
|
|
16812
17618
|
"opportunities": ["id", "advancedField1", "advancedField2", "advancedField3", "advancedField4", "advancedField5", "amount", "assessmentScore", "barriers", "closedDate", "companyID", "contactID", "cost", "createDate", "creatorResourceID", "description", "helpNeeded", "impersonatorCreatorResourceID", "lastActivity", "leadSource", "lossReason", "lossReasonDetail", "lostDate", "market", "monthlyCost", "monthlyRevenue", "nextStep", "onetimeCost", "onetimeRevenue", "opportunityCategoryID", "organizationalLevelAssociationID", "ownerResourceID", "primaryCompetitor", "probability", "productID", "projectedCloseDate", "promisedFulfillmentDate", "promotionName", "quarterlyCost", "quarterlyRevenue", "rating", "relationshipAssessmentScore", "revenueSpread", "revenueSpreadUnit", "salesOrderID", "salesProcessPercentComplete", "semiannualCost", "semiannualRevenue", "stage", "startDate", "status", "technicalAssessmentScore", "throughDate", "title", "totalAmountMonths", "useQuoteTotals", "winReason", "winReasonDetail", "yearlyCost", "yearlyRevenue", "userDefinedFields"],
|
|
16813
17619
|
"opportunity_attachments": ["id", "attachDate", "attachedByContactID", "attachedByResourceID", "attachmentType", "contentType", "creatorType", "fileSize", "fullPath", "impersonatorCreatorResourceID", "opportunityID", "parentAttachmentID", "parentID", "publish", "title", "data", "parentType", "soapParentPropertyId", "isTaskAttachment"],
|
|
16814
17620
|
"opportunity_categories": ["id", "displayColorRGB", "isActive", "isGlobalDefault", "name", "nickname"],
|
|
17621
|
+
"organizational_level1s": ["id", "description", "isActive", "name"],
|
|
17622
|
+
"organizational_level2s": ["id", "description", "isActive", "name"],
|
|
17623
|
+
"organizational_level_associations": ["id", "isActive", "organizationalLevel1ID", "organizationalLevel2ID"],
|
|
16815
17624
|
"phases": ["id", "createDate", "creatorResourceID", "description", "dueDate", "estimatedHours", "externalID", "isScheduled", "lastActivityDateTime", "parentPhaseID", "phaseNumber", "projectID", "startDate", "title", "soapParentPropertyId"],
|
|
16816
17625
|
"product_vendors": ["id", "isActive", "isDefault", "productID", "vendorCost", "vendorID", "vendorPartNumber", "soapParentPropertyId"],
|
|
16817
17626
|
"products": ["id", "billingType", "chargeBillingCodeID", "createdByResourceID", "createdTime", "defaultVendorID", "description", "doesNotRequireProcurement", "externalProductID", "impersonatorCreatorResourceID", "internalProductID", "isActive", "isEligibleForRma", "isSerialized", "link", "manufacturerName", "manufacturerProductName", "markupRate", "msrp", "name", "periodType", "priceCostMethod", "productBillingCodeID", "productCategory", "sku", "unitCost", "unitPrice", "vendorProductNumber", "defaultInstalledProductCategoryID", "userDefinedFields"],
|
|
@@ -16833,6 +17642,7 @@ var MODEL_FIELD_SETS = {
|
|
|
16833
17642
|
"resource_time_off_balances": ["id", "resourceID", "floatingHolidayAnnualAllowance", "floatingHolidayBalance", "floatingHolidayPlanned", "floatingHolidayUsed", "floatingHolidayWaitingApproval", "personalTimeAnnualAllowance", "personalTimeBalance", "personalTimePlanned", "personalTimeUsed", "personalTimeWaitingApproval", "sickTimeAnnualAllowance", "sickTimeBalance", "sickTimePlanned", "sickTimeUsed", "sickTimeWaitingApproval", "vacationTimeAnnualAllowance", "vacationTimeBalance", "vacationTimePlanned", "vacationTimeUsed", "vacationTimeWaitingApproval", "year", "soapParentPropertyId"],
|
|
16834
17643
|
"resources": ["id", "accountingReferenceID", "dateFormat", "defaultServiceDeskRoleID", "email", "email2", "email3", "emailTypeCode", "emailTypeCode2", "emailTypeCode3", "firstName", "gender", "greeting", "hireDate", "homePhone", "initials", "internalCost", "isActive", "lastName", "licenseType", "locationID", "middleName", "mobilePhone", "numberFormat", "officeExtension", "officePhone", "payrollIdentifier", "payrollType", "resourceType", "suffix", "surveyResourceRating", "timeFormat", "title", "travelAvailabilityPct", "userName", "userType"],
|
|
16835
17644
|
"roles": ["id", "description", "hourlyFactor", "hourlyRate", "isActive", "isExcludedFromNewContracts", "isSystemRole", "name", "quoteItemDefaultTaxCategoryId", "roleType"],
|
|
17645
|
+
"sales_orders": ["id", "additionalBillToAddressInformation", "additionalShipToAddressInformation", "billingAddress1", "billingAddress2", "billToCity", "billToCountryID", "billToPostalCode", "billToState", "companyID", "contactID", "impersonatorCreatorResourceID", "opportunityID", "organizationalLevelAssociationID", "ownerResourceID", "promisedFulfillmentDate", "salesOrderDate", "shipToAddress1", "shipToAddress2", "shipToCity", "shipToCountryID", "shipToPostalCode", "shipToState", "status", "title", "soapParentPropertyId", "userDefinedFields"],
|
|
16836
17646
|
"service_call_task_resources": ["id", "resourceID", "serviceCallTaskID", "soapParentPropertyId"],
|
|
16837
17647
|
"service_call_tasks": ["id", "serviceCallID", "taskID", "soapParentPropertyId"],
|
|
16838
17648
|
"service_call_ticket_resources": ["id", "resourceID", "serviceCallTicketID", "soapParentPropertyId"],
|
|
@@ -16850,6 +17660,7 @@ var MODEL_FIELD_SETS = {
|
|
|
16850
17660
|
"tags": ["id", "createDateTime", "isActive", "isExcludedFromAutomaticTagging", "isSystem", "label", "lastModifiedDateTime", "tagGroupID"],
|
|
16851
17661
|
"task_secondary_resources": ["id", "resourceID", "roleID", "taskID", "soapParentPropertyId"],
|
|
16852
17662
|
"tasks": ["id", "assignedResourceID", "assignedResourceRoleID", "billingCodeID", "canClientPortalUserCompleteTask", "companyLocationID", "completedByResourceID", "completedByType", "completedDateTime", "createDateTime", "creatorResourceID", "creatorType", "departmentID", "description", "endDateTime", "estimatedHours", "externalID", "hoursToBeScheduled", "isTaskBillable", "isVisibleInClientPortal", "lastActivityDateTime", "lastActivityPersonType", "lastActivityResourceID", "phaseID", "priority", "priorityLabel", "projectID", "purchaseOrderNumber", "remainingHours", "startDateTime", "status", "taskCategoryID", "taskNumber", "taskType", "title", "soapParentPropertyId", "userDefinedFields"],
|
|
17663
|
+
"tax_regions": ["id", "isActive", "name"],
|
|
16853
17664
|
"ticket_additional_configuration_items": ["id", "configurationItemID", "ticketID", "soapParentPropertyId"],
|
|
16854
17665
|
"ticket_additional_contacts": ["id", "contactID", "ticketID", "soapParentPropertyId"],
|
|
16855
17666
|
"ticket_attachments": ["id", "attachDate", "attachedByContactID", "attachedByResourceID", "attachmentType", "contentType", "creatorType", "fileSize", "fullPath", "impersonatorCreatorResourceID", "opportunityID", "parentAttachmentID", "parentID", "publish", "ticketID", "ticketNoteID", "timeEntryID", "title", "data", "parentType", "soapParentPropertyId", "isTaskAttachment"],
|
|
@@ -16871,6 +17682,7 @@ var MODEL_FIELD_SETS = {
|
|
|
16871
17682
|
};
|
|
16872
17683
|
var MODEL_DATE_FIELDS = {
|
|
16873
17684
|
"appointments": ["createDateTime", "endDateTime", "startDateTime", "updateDateTime"],
|
|
17685
|
+
"billing_item_approval_levels": ["approvalDateTime"],
|
|
16874
17686
|
"billing_items": ["itemDate", "postedDate", "postedOnTime", "webServiceDate"],
|
|
16875
17687
|
"companies": ["createDate", "lastActivityDate", "lastTrackedModifiedDateTime"],
|
|
16876
17688
|
"company_notes": ["completedDateTime", "createDateTime", "endDateTime", "lastModifiedDate", "startDateTime"],
|
|
@@ -16910,6 +17722,7 @@ var MODEL_DATE_FIELDS = {
|
|
|
16910
17722
|
"quote_templates": ["createDate", "lastActivityDate"],
|
|
16911
17723
|
"quotes": ["approvalStatusChangedDate", "createDate", "effectiveDate", "expirationDate", "extApprovalResponseDate", "lastActivityDate", "lastPublishedDateTime"],
|
|
16912
17724
|
"resources": ["hireDate"],
|
|
17725
|
+
"sales_orders": ["promisedFulfillmentDate", "salesOrderDate"],
|
|
16913
17726
|
"service_calls": ["canceledDateTime", "createDateTime", "endDateTime", "lastModifiedDateTime", "startDateTime"],
|
|
16914
17727
|
"services": ["createDate", "lastModifiedDate"],
|
|
16915
17728
|
"subscription_periods": ["periodDate", "postedDate"],
|
|
@@ -19357,6 +20170,8 @@ export {
|
|
|
19357
20170
|
MarkerUnsafeIdError,
|
|
19358
20171
|
RecoveryTruncatedError,
|
|
19359
20172
|
MoveRefusedError,
|
|
20173
|
+
READ_CACHE_MAX_ENTRIES,
|
|
20174
|
+
ReadCache,
|
|
19360
20175
|
ZONE_CATALOG,
|
|
19361
20176
|
ZONES,
|
|
19362
20177
|
DEFAULT_ZONE,
|
|
@@ -19402,6 +20217,7 @@ export {
|
|
|
19402
20217
|
buildTenantKey,
|
|
19403
20218
|
cooldownDurationMs,
|
|
19404
20219
|
resolveCredentials,
|
|
20220
|
+
buildReadCache,
|
|
19405
20221
|
resolveConfig,
|
|
19406
20222
|
IDEMPOTENT_METHODS,
|
|
19407
20223
|
isRecord2 as isRecord,
|
|
@@ -19469,6 +20285,9 @@ export {
|
|
|
19469
20285
|
validateQueryFieldNames,
|
|
19470
20286
|
EXPAND_RESOURCE_NAMES_MAX_IDS,
|
|
19471
20287
|
expandResourceNames,
|
|
20288
|
+
ENTITY_TYPE_TO_RESOURCE,
|
|
20289
|
+
resourceForEntityType,
|
|
20290
|
+
isEnumerableResource,
|
|
19472
20291
|
WORKFLOW_RESOURCES,
|
|
19473
20292
|
MAX_FIELD_CATALOG_WIRE,
|
|
19474
20293
|
FIELD_CATALOG_HONESTY_NOTE,
|