node-autotask 0.25.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 +61 -0
- package/MCP_TOOL_CATALOG.json +1063 -30
- package/MCP_TOOL_MANIFEST.md +82 -24
- package/N8N_MCP_MANIFEST.json +39 -8
- package/N8N_MCP_MANIFEST.md +9 -8
- package/README.md +11 -9
- package/capabilities.json +16956 -10596
- package/capabilities.schema.json +125 -0
- package/dist/capabilities.cjs +2 -2
- package/dist/capabilities.js +1 -1
- package/dist/{chunk-VUGZKP33.js → chunk-42ZUISDH.js} +997 -136
- package/dist/{chunk-WBMRACCV.cjs → chunk-5CC7LGNM.cjs} +16955 -10595
- package/dist/{chunk-Z5L7Q33V.cjs → chunk-5GGCSRT4.cjs} +947 -493
- package/dist/{chunk-EFR2XWRX.js → chunk-F7FVOXPQ.js} +16955 -10595
- package/dist/{chunk-XUB3S6AM.js → chunk-GURC52J7.js} +26 -2
- package/dist/{chunk-FKJ77K6Z.cjs → chunk-UHTZLUDE.cjs} +159 -135
- package/dist/{chunk-6PIJ6AZG.js → chunk-ZGTFVZL5.js} +478 -24
- package/dist/{chunk-2H7YI54B.cjs → chunk-ZJ4ONAQF.cjs} +1084 -223
- package/dist/{index-CZ94y401.d.ts → index-BIWy9m-a.d.ts} +414 -49
- package/dist/{index-C0OwQhon.d.cts → index-D4XYtn4s.d.cts} +414 -49
- package/dist/{index-BVtycq-6.d.cts → index-DQ9NgraW.d.cts} +322 -1
- package/dist/{index-BVtycq-6.d.ts → index-DQ9NgraW.d.ts} +322 -1
- package/dist/index.cjs +46 -24
- package/dist/index.d.cts +11 -5
- package/dist/index.d.ts +11 -5
- package/dist/index.js +28 -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 +21 -5
- package/dist/resources/index.d.cts +2 -2
- package/dist/resources/index.d.ts +2 -2
- package/dist/resources/index.js +20 -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 +3 -3
- /package/dist/{chunk-FLB2X6O5.cjs → chunk-IXF7AKOJ.cjs} +0 -0
- /package/dist/{chunk-DMMMWO6A.js → chunk-RMG55JTF.js} +0 -0
- /package/dist/{chunk-IDPB4N2Q.cjs → chunk-SDYRQFGL.cjs} +0 -0
- /package/dist/{chunk-UPQIUWOS.js → chunk-WLTLB2ND.js} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7; var _class8;
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunk5CC7LGNMcjs = require('./chunk-5CC7LGNM.cjs');
|
|
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 = class {
|
|
589
|
+
/** The configured TTL in ms (the fallback for resources without an override). */
|
|
590
|
+
|
|
591
|
+
/** The per-resource TTL overrides (issue #32; absent = every resource uses `ttlMs`). */
|
|
592
|
+
|
|
593
|
+
__init() {this.store = /* @__PURE__ */ new Map()}
|
|
594
|
+
__init2() {this.epochCounter = 0}
|
|
595
|
+
constructor(ttlMs, perResourceTtlMs) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);
|
|
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
|
+
}, _class);
|
|
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,
|
|
@@ -737,6 +843,7 @@ var DEFAULT_PER_RESOURCE_TTL_MS = {
|
|
|
737
843
|
"contract_ticket_purchases": 3e5,
|
|
738
844
|
"contracts": 3e5,
|
|
739
845
|
"countries": 36e5,
|
|
846
|
+
"currencies": 3e5,
|
|
740
847
|
"departments": 36e5,
|
|
741
848
|
"domain_registrars": 3e5,
|
|
742
849
|
"entity_information": 3e5,
|
|
@@ -746,12 +853,16 @@ var DEFAULT_PER_RESOURCE_TTL_MS = {
|
|
|
746
853
|
"holiday_sets": 3e5,
|
|
747
854
|
"holidays": 3e5,
|
|
748
855
|
"inventory_products": 3e5,
|
|
856
|
+
"invoice_templates": 3e5,
|
|
749
857
|
"invoices": 3e5,
|
|
750
858
|
"modules": 3e5,
|
|
751
859
|
"notification_history": 3e5,
|
|
752
860
|
"opportunities": 3e5,
|
|
753
861
|
"opportunity_attachments": 3e5,
|
|
754
862
|
"opportunity_categories": 3e5,
|
|
863
|
+
"organizational_level1s": 3e5,
|
|
864
|
+
"organizational_level2s": 3e5,
|
|
865
|
+
"organizational_level_associations": 3e5,
|
|
755
866
|
"phases": 36e5,
|
|
756
867
|
"product_vendors": 3e5,
|
|
757
868
|
"products": 3e5,
|
|
@@ -774,6 +885,7 @@ var DEFAULT_PER_RESOURCE_TTL_MS = {
|
|
|
774
885
|
"resource_time_off_balances": 3e5,
|
|
775
886
|
"resources": 3e5,
|
|
776
887
|
"roles": 36e5,
|
|
888
|
+
"sales_orders": 3e5,
|
|
777
889
|
"service_call_task_resources": 3e5,
|
|
778
890
|
"service_call_tasks": 3e5,
|
|
779
891
|
"service_call_ticket_resources": 3e5,
|
|
@@ -791,6 +903,7 @@ var DEFAULT_PER_RESOURCE_TTL_MS = {
|
|
|
791
903
|
"tags": 3e5,
|
|
792
904
|
"task_secondary_resources": 3e5,
|
|
793
905
|
"tasks": 3e5,
|
|
906
|
+
"tax_regions": 3e5,
|
|
794
907
|
"threshold_information": 3e5,
|
|
795
908
|
"ticket_additional_configuration_items": 3e5,
|
|
796
909
|
"ticket_additional_contacts": 3e5,
|
|
@@ -818,6 +931,7 @@ var DEFAULT_PER_RESOURCE_TTL_MS = {
|
|
|
818
931
|
var RESOURCE_KEY_BY_PATH = {
|
|
819
932
|
"/V1.0/Appointments": "appointments",
|
|
820
933
|
"/V1.0/BillingCodes": "billing_codes",
|
|
934
|
+
"/V1.0/BillingItemApprovalLevels": "billing_item_approval_levels",
|
|
821
935
|
"/V1.0/BillingItems": "billing_items",
|
|
822
936
|
"/V1.0/ChangeRequestLinks": "change_request_links",
|
|
823
937
|
"/V1.0/ChecklistLibraries": "checklist_libraries",
|
|
@@ -866,6 +980,7 @@ var RESOURCE_KEY_BY_PATH = {
|
|
|
866
980
|
"/V1.0/ContractTicketPurchases": "contract_ticket_purchases",
|
|
867
981
|
"/V1.0/Contracts": "contracts",
|
|
868
982
|
"/V1.0/Countries": "countries",
|
|
983
|
+
"/V1.0/Currencies": "currencies",
|
|
869
984
|
"/V1.0/Departments": "departments",
|
|
870
985
|
"/V1.0/DomainRegistrars": "domain_registrars",
|
|
871
986
|
"/V1.0/ExpenseItemAttachments": "expense_item_attachments",
|
|
@@ -874,11 +989,15 @@ var RESOURCE_KEY_BY_PATH = {
|
|
|
874
989
|
"/V1.0/HolidaySets": "holiday_sets",
|
|
875
990
|
"/V1.0/Holidays": "holidays",
|
|
876
991
|
"/V1.0/InventoryProducts": "inventory_products",
|
|
992
|
+
"/V1.0/InvoiceTemplates": "invoice_templates",
|
|
877
993
|
"/V1.0/Invoices": "invoices",
|
|
878
994
|
"/V1.0/NotificationHistory": "notification_history",
|
|
879
995
|
"/V1.0/Opportunities": "opportunities",
|
|
880
996
|
"/V1.0/OpportunityAttachments": "opportunity_attachments",
|
|
881
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",
|
|
882
1001
|
"/V1.0/Phases": "phases",
|
|
883
1002
|
"/V1.0/ProductVendors": "product_vendors",
|
|
884
1003
|
"/V1.0/Products": "products",
|
|
@@ -901,6 +1020,7 @@ var RESOURCE_KEY_BY_PATH = {
|
|
|
901
1020
|
"/V1.0/ResourceTimeOffBalances": "resource_time_off_balances",
|
|
902
1021
|
"/V1.0/Resources": "resources",
|
|
903
1022
|
"/V1.0/Roles": "roles",
|
|
1023
|
+
"/V1.0/SalesOrders": "sales_orders",
|
|
904
1024
|
"/V1.0/ServiceCallTaskResources": "service_call_task_resources",
|
|
905
1025
|
"/V1.0/ServiceCallTasks": "service_call_tasks",
|
|
906
1026
|
"/V1.0/ServiceCallTicketResources": "service_call_ticket_resources",
|
|
@@ -918,6 +1038,7 @@ var RESOURCE_KEY_BY_PATH = {
|
|
|
918
1038
|
"/V1.0/Tags": "tags",
|
|
919
1039
|
"/V1.0/TaskSecondaryResources": "task_secondary_resources",
|
|
920
1040
|
"/V1.0/Tasks": "tasks",
|
|
1041
|
+
"/V1.0/TaxRegions": "tax_regions",
|
|
921
1042
|
"/V1.0/TicketAdditionalConfigurationItems": "ticket_additional_configuration_items",
|
|
922
1043
|
"/V1.0/TicketAdditionalContacts": "ticket_additional_contacts",
|
|
923
1044
|
"/V1.0/TicketAttachments": "ticket_attachments",
|
|
@@ -982,14 +1103,14 @@ function credentialValueSummary(value) {
|
|
|
982
1103
|
// src/fieldCache.ts
|
|
983
1104
|
var FIELD_CACHE_MAX_ENTITIES = 256;
|
|
984
1105
|
var FIELD_CACHE_KINDS = ["info", "fields", "udf"];
|
|
985
|
-
var FieldCache = (
|
|
1106
|
+
var FieldCache = (_class2 = class _FieldCache {
|
|
986
1107
|
/** The configured TTL in ms. */
|
|
987
1108
|
|
|
988
1109
|
/** The entity bound (the cap applies to STORED entries; inflight never counts). */
|
|
989
1110
|
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
constructor(ttlMs, maxEntities = FIELD_CACHE_MAX_ENTITIES) {;
|
|
1111
|
+
__init3() {this.store = /* @__PURE__ */ new Map()}
|
|
1112
|
+
__init4() {this.inflightMap = /* @__PURE__ */ new Map()}
|
|
1113
|
+
constructor(ttlMs, maxEntities = FIELD_CACHE_MAX_ENTITIES) {;_class2.prototype.__init3.call(this);_class2.prototype.__init4.call(this);
|
|
993
1114
|
if (!Number.isInteger(ttlMs) || ttlMs <= 0) {
|
|
994
1115
|
throw new AutotaskConfigError(`fieldCache.ttlMs must be a positive integer (got ${ttlMs})`);
|
|
995
1116
|
}
|
|
@@ -1111,7 +1232,7 @@ var FieldCache = (_class = class _FieldCache {
|
|
|
1111
1232
|
this.store.clear();
|
|
1112
1233
|
this.inflightMap.clear();
|
|
1113
1234
|
}
|
|
1114
|
-
},
|
|
1235
|
+
}, _class2);
|
|
1115
1236
|
|
|
1116
1237
|
// src/circuit-breaker.ts
|
|
1117
1238
|
var DEFAULT_CIRCUIT_BREAKER_WINDOW_MS = 1e4;
|
|
@@ -1119,10 +1240,10 @@ var DEFAULT_CIRCUIT_BREAKER_FAILURE_THRESHOLD = 5;
|
|
|
1119
1240
|
var DEFAULT_CIRCUIT_BREAKER_OPEN_TIMEOUT_MS = 3e4;
|
|
1120
1241
|
var DEFAULT_CIRCUIT_BREAKER_SUCCESSES_TO_CLOSE = 2;
|
|
1121
1242
|
var DEFAULT_CIRCUIT_BREAKER_MAX_ENTRIES = 1024;
|
|
1122
|
-
var InMemoryCircuitBreakerStore = (
|
|
1243
|
+
var InMemoryCircuitBreakerStore = (_class3 = class {
|
|
1123
1244
|
|
|
1124
|
-
|
|
1125
|
-
constructor(maxEntries = DEFAULT_CIRCUIT_BREAKER_MAX_ENTRIES) {;
|
|
1245
|
+
__init5() {this.states = /* @__PURE__ */ new Map()}
|
|
1246
|
+
constructor(maxEntries = DEFAULT_CIRCUIT_BREAKER_MAX_ENTRIES) {;_class3.prototype.__init5.call(this);
|
|
1126
1247
|
if (!Number.isInteger(maxEntries) || maxEntries <= 0) {
|
|
1127
1248
|
throw new TypeError(`InMemoryCircuitBreakerStore maxEntries must be a positive integer (got ${String(maxEntries)})`);
|
|
1128
1249
|
}
|
|
@@ -1157,7 +1278,7 @@ var InMemoryCircuitBreakerStore = (_class2 = class {
|
|
|
1157
1278
|
clear() {
|
|
1158
1279
|
this.states.clear();
|
|
1159
1280
|
}
|
|
1160
|
-
},
|
|
1281
|
+
}, _class3);
|
|
1161
1282
|
var defaultStore;
|
|
1162
1283
|
function defaultCircuitBreakerStore() {
|
|
1163
1284
|
if (defaultStore === void 0) defaultStore = new InMemoryCircuitBreakerStore();
|
|
@@ -1187,10 +1308,10 @@ var DEFAULT_COOLDOWN_DEFAULT_MS = 6e4;
|
|
|
1187
1308
|
var DEFAULT_COOLDOWN_MAX_ENTRIES = 1024;
|
|
1188
1309
|
var THREAD_THRESHOLD_MAX_MS = 1e4;
|
|
1189
1310
|
var THREAD_THRESHOLD_DEFAULT_MS = 5e3;
|
|
1190
|
-
var InMemoryCooldownStore = (
|
|
1311
|
+
var InMemoryCooldownStore = (_class4 = class {
|
|
1191
1312
|
|
|
1192
|
-
|
|
1193
|
-
constructor(maxEntries = DEFAULT_COOLDOWN_MAX_ENTRIES) {;
|
|
1313
|
+
__init6() {this.deadlines = /* @__PURE__ */ new Map()}
|
|
1314
|
+
constructor(maxEntries = DEFAULT_COOLDOWN_MAX_ENTRIES) {;_class4.prototype.__init6.call(this);
|
|
1194
1315
|
if (!Number.isInteger(maxEntries) || maxEntries <= 0) {
|
|
1195
1316
|
throw new TypeError(`InMemoryCooldownStore maxEntries must be a positive integer (got ${String(maxEntries)})`);
|
|
1196
1317
|
}
|
|
@@ -1224,7 +1345,7 @@ var InMemoryCooldownStore = (_class3 = class {
|
|
|
1224
1345
|
clear() {
|
|
1225
1346
|
this.deadlines.clear();
|
|
1226
1347
|
}
|
|
1227
|
-
},
|
|
1348
|
+
}, _class4);
|
|
1228
1349
|
var defaultStore2;
|
|
1229
1350
|
function defaultCooldownStore() {
|
|
1230
1351
|
if (defaultStore2 === void 0) defaultStore2 = new InMemoryCooldownStore();
|
|
@@ -1245,111 +1366,6 @@ function cooldownDurationMs(retryAfterSecs, opts) {
|
|
|
1245
1366
|
return Math.min(rawMs, opts.maxMs);
|
|
1246
1367
|
}
|
|
1247
1368
|
|
|
1248
|
-
// src/cache.ts
|
|
1249
|
-
var READ_CACHE_MAX_ENTRIES = 4096;
|
|
1250
|
-
var ReadCache = (_class4 = class {
|
|
1251
|
-
/** The configured TTL in ms (the fallback for resources without an override). */
|
|
1252
|
-
|
|
1253
|
-
/** The per-resource TTL overrides (issue #32; absent = every resource uses `ttlMs`). */
|
|
1254
|
-
|
|
1255
|
-
__init5() {this.store = /* @__PURE__ */ new Map()}
|
|
1256
|
-
__init6() {this.epochCounter = 0}
|
|
1257
|
-
constructor(ttlMs, perResourceTtlMs) {;_class4.prototype.__init5.call(this);_class4.prototype.__init6.call(this);
|
|
1258
|
-
if (!Number.isInteger(ttlMs) || ttlMs <= 0) {
|
|
1259
|
-
throw new AutotaskConfigError(`cache.ttlMs must be a positive integer (got ${ttlMs})`);
|
|
1260
|
-
}
|
|
1261
|
-
if (perResourceTtlMs !== void 0) {
|
|
1262
|
-
if (perResourceTtlMs === null || typeof perResourceTtlMs !== "object" || Array.isArray(perResourceTtlMs)) {
|
|
1263
|
-
throw new AutotaskConfigError(
|
|
1264
|
-
`cache.perResourceTtlMs must be an object of resource key -> ms (got ${String(perResourceTtlMs)})`
|
|
1265
|
-
);
|
|
1266
|
-
}
|
|
1267
|
-
for (const [key, value] of Object.entries(perResourceTtlMs)) {
|
|
1268
|
-
if (key === "") {
|
|
1269
|
-
throw new AutotaskConfigError("cache.perResourceTtlMs keys must be non-empty resource keys");
|
|
1270
|
-
}
|
|
1271
|
-
if (!Number.isInteger(value) || value <= 0) {
|
|
1272
|
-
throw new AutotaskConfigError(
|
|
1273
|
-
`cache.perResourceTtlMs.${key} must be a positive integer (got ${String(value)})`
|
|
1274
|
-
);
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
}
|
|
1278
|
-
this.ttlMs = ttlMs;
|
|
1279
|
-
this.perResourceTtlMs = perResourceTtlMs;
|
|
1280
|
-
}
|
|
1281
|
-
/**
|
|
1282
|
-
* The TTL (ms) for a resource plan key: the `perResourceTtlMs` override
|
|
1283
|
-
* when the map is present and names the resource, else the base
|
|
1284
|
-
* `ttlMs` (absent map, absent key, and `undefined` all fall back).
|
|
1285
|
-
*/
|
|
1286
|
-
ttlFor(resource) {
|
|
1287
|
-
if (resource !== void 0 && this.perResourceTtlMs !== void 0) {
|
|
1288
|
-
const override = this.perResourceTtlMs[resource];
|
|
1289
|
-
if (override !== void 0) return override;
|
|
1290
|
-
}
|
|
1291
|
-
return this.ttlMs;
|
|
1292
|
-
}
|
|
1293
|
-
/**
|
|
1294
|
-
* Read-through lookup: the live entry's value, or `undefined` (absent OR
|
|
1295
|
-
* expired — an expired entry is purged lazily on this read).
|
|
1296
|
-
*/
|
|
1297
|
-
get(key) {
|
|
1298
|
-
const entry = this.store.get(key);
|
|
1299
|
-
if (entry === void 0) return void 0;
|
|
1300
|
-
if (entry.expiresAt <= Date.now()) {
|
|
1301
|
-
this.store.delete(key);
|
|
1302
|
-
return void 0;
|
|
1303
|
-
}
|
|
1304
|
-
return structuredClone(entry.value);
|
|
1305
|
-
}
|
|
1306
|
-
/** Store a successful read payload under `key`, live for `ttlFor(resource)`:
|
|
1307
|
-
* the per-resource override (issue #32) when named, else `ttlMs`.
|
|
1308
|
-
* `epoch` is the invalidation epoch the caller captured BEFORE its wire
|
|
1309
|
-
* read: a read that straddled a `clear()` (a write) is dropped, never
|
|
1310
|
-
* re-stored with its pre-write body. */
|
|
1311
|
-
set(key, value, resource, epoch = this.epochCounter) {
|
|
1312
|
-
if (epoch !== this.epochCounter) return;
|
|
1313
|
-
if (this.store.size >= READ_CACHE_MAX_ENTRIES && this.purgeExpired() === 0) {
|
|
1314
|
-
const oldest = this.store.keys().next();
|
|
1315
|
-
if (!oldest.done) this.store.delete(oldest.value);
|
|
1316
|
-
}
|
|
1317
|
-
this.store.delete(key);
|
|
1318
|
-
this.store.set(key, { value: structuredClone(value), expiresAt: Date.now() + this.ttlFor(resource) });
|
|
1319
|
-
}
|
|
1320
|
-
/** Drop every expired entry (returns the number removed). */
|
|
1321
|
-
purgeExpired() {
|
|
1322
|
-
const now = Date.now();
|
|
1323
|
-
let removed = 0;
|
|
1324
|
-
for (const [key, entry] of this.store) {
|
|
1325
|
-
if (entry.expiresAt <= now) {
|
|
1326
|
-
this.store.delete(key);
|
|
1327
|
-
removed += 1;
|
|
1328
|
-
}
|
|
1329
|
-
}
|
|
1330
|
-
return removed;
|
|
1331
|
-
}
|
|
1332
|
-
/** Current entry count (live + not-yet-purged expired). */
|
|
1333
|
-
get size() {
|
|
1334
|
-
return this.store.size;
|
|
1335
|
-
}
|
|
1336
|
-
/** Drop one key (issue #36: a later positive outcome clears a stale 'absent' marker). */
|
|
1337
|
-
delete(key) {
|
|
1338
|
-
return this.store.delete(key);
|
|
1339
|
-
}
|
|
1340
|
-
/** The invalidation epoch: bumped by `clear()`; capture it before a wire
|
|
1341
|
-
* read and pass it to `set` so a read in flight across a write cannot
|
|
1342
|
-
* re-store its stale answer. */
|
|
1343
|
-
get epoch() {
|
|
1344
|
-
return this.epochCounter;
|
|
1345
|
-
}
|
|
1346
|
-
/** Drop everything (e.g. a caller that knows the tenant was reset). */
|
|
1347
|
-
clear() {
|
|
1348
|
-
this.epochCounter += 1;
|
|
1349
|
-
this.store.clear();
|
|
1350
|
-
}
|
|
1351
|
-
}, _class4);
|
|
1352
|
-
|
|
1353
1369
|
// src/resourceNameCache.ts
|
|
1354
1370
|
var RESOURCE_NAME_CACHE_MAX_ENTRIES = 1024;
|
|
1355
1371
|
var RESOURCE_NAME_CACHE_BLIND_TTL_MS = 6e4;
|
|
@@ -1833,22 +1849,41 @@ function resolveResolution(config, agent) {
|
|
|
1833
1849
|
}
|
|
1834
1850
|
function resolveCaches(config) {
|
|
1835
1851
|
const cacheBlock = config.cache === false || config.cache === void 0 ? void 0 : config.cache;
|
|
1852
|
+
resolveReadCacheStore(cacheBlock);
|
|
1836
1853
|
const fieldCacheBlock = config.fieldCache === false || config.fieldCache === void 0 ? void 0 : config.fieldCache;
|
|
1837
1854
|
const resourceNameCacheBlock = config.resourceNameCache === false || config.resourceNameCache === void 0 ? void 0 : config.resourceNameCache;
|
|
1838
|
-
const readCache = config.cache === false ? void 0 :
|
|
1839
|
-
_nullishCoalesce(_optionalChain([cacheBlock, 'optionalAccess', _41 => _41.ttlMs]), () => ( DEFAULT_READ_CACHE_TTL_MS)),
|
|
1840
|
-
{ ...DEFAULT_PER_RESOURCE_TTL_MS, ..._optionalChain([cacheBlock, 'optionalAccess', _42 => _42.perResourceTtlMs]) }
|
|
1841
|
-
);
|
|
1855
|
+
const readCache = config.cache === false ? void 0 : _nullishCoalesce(_optionalChain([cacheBlock, 'optionalAccess', _41 => _41.store]), () => ( buildReadCache(config)));
|
|
1842
1856
|
const fieldCache = config.fieldCache === false ? void 0 : new FieldCache(
|
|
1843
|
-
_nullishCoalesce(_optionalChain([fieldCacheBlock, 'optionalAccess',
|
|
1844
|
-
_nullishCoalesce(_optionalChain([fieldCacheBlock, 'optionalAccess',
|
|
1857
|
+
_nullishCoalesce(_optionalChain([fieldCacheBlock, 'optionalAccess', _42 => _42.ttlMs]), () => ( DEFAULT_FIELD_CACHE_TTL_MS)),
|
|
1858
|
+
_nullishCoalesce(_optionalChain([fieldCacheBlock, 'optionalAccess', _43 => _43.maxEntities]), () => ( FIELD_CACHE_MAX_ENTITIES))
|
|
1845
1859
|
);
|
|
1846
1860
|
const resourceNameCache = config.resourceNameCache === false ? void 0 : new ResourceNameCache(
|
|
1847
|
-
_nullishCoalesce(_optionalChain([resourceNameCacheBlock, 'optionalAccess',
|
|
1848
|
-
_nullishCoalesce(_optionalChain([resourceNameCacheBlock, 'optionalAccess',
|
|
1861
|
+
_nullishCoalesce(_optionalChain([resourceNameCacheBlock, 'optionalAccess', _44 => _44.ttlMs]), () => ( DEFAULT_RESOURCE_NAME_CACHE_TTL_MS)),
|
|
1862
|
+
_nullishCoalesce(_optionalChain([resourceNameCacheBlock, 'optionalAccess', _45 => _45.maxEntries]), () => ( RESOURCE_NAME_CACHE_MAX_ENTRIES))
|
|
1849
1863
|
);
|
|
1850
1864
|
return { readCache, fieldCache, resourceNameCache };
|
|
1851
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
|
+
_nullishCoalesce(_optionalChain([cacheBlock, 'optionalAccess', _46 => _46.ttlMs]), () => ( DEFAULT_READ_CACHE_TTL_MS)),
|
|
1884
|
+
{ ...DEFAULT_PER_RESOURCE_TTL_MS, ..._optionalChain([cacheBlock, 'optionalAccess', _47 => _47.perResourceTtlMs]) }
|
|
1885
|
+
);
|
|
1886
|
+
}
|
|
1852
1887
|
function resolveConfig(config) {
|
|
1853
1888
|
if (config === null || typeof config !== "object") {
|
|
1854
1889
|
throw new AutotaskConfigError("AutotaskConfig is required");
|
|
@@ -1864,12 +1899,12 @@ function resolveConfig(config) {
|
|
|
1864
1899
|
const resolution = resolveResolution(config, agent);
|
|
1865
1900
|
const redactPersonalData = _nullishCoalesce(config.redactPersonalData, () => ( true));
|
|
1866
1901
|
const caches = resolveCaches(config);
|
|
1867
|
-
const update = { putFallback: _optionalChain([config, 'access',
|
|
1902
|
+
const update = { putFallback: _optionalChain([config, 'access', _48 => _48.update, 'optionalAccess', _49 => _49.putFallback]) === true };
|
|
1868
1903
|
const reResolveZoneOn401 = config.reResolveZoneOn401 === true;
|
|
1869
1904
|
const logger = _nullishCoalesce(config.logger, () => ( NoopLogger));
|
|
1870
1905
|
if (credentials.baseUrl.startsWith("http:")) {
|
|
1871
1906
|
const host = new URL(credentials.baseUrl).host;
|
|
1872
|
-
_optionalChain([logger, 'access',
|
|
1907
|
+
_optionalChain([logger, 'access', _50 => _50.warn, 'optionalCall', _51 => _51(
|
|
1873
1908
|
`[autotask] cleartext credentials to ${host} \u2014 https recommended (baseUrl uses http:; all catalog zones are https)`
|
|
1874
1909
|
)]);
|
|
1875
1910
|
}
|
|
@@ -1950,7 +1985,7 @@ function parseIdentifier(value, label = "id") {
|
|
|
1950
1985
|
return parsed;
|
|
1951
1986
|
}
|
|
1952
1987
|
function flattenUdfs(record, options) {
|
|
1953
|
-
const prefix = _nullishCoalesce(_optionalChain([options, 'optionalAccess',
|
|
1988
|
+
const prefix = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _52 => _52.prefix]), () => ( "udf_"));
|
|
1954
1989
|
const out = { ...record };
|
|
1955
1990
|
const udfs = record.userDefinedFields;
|
|
1956
1991
|
if (!Array.isArray(udfs)) return out;
|
|
@@ -2353,6 +2388,52 @@ var RELATIONSHIP_MAP = {
|
|
|
2353
2388
|
"deleteBoundary": null,
|
|
2354
2389
|
"markerField": null
|
|
2355
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
|
+
},
|
|
2356
2437
|
"billing_items": {
|
|
2357
2438
|
"resource": "billing_items",
|
|
2358
2439
|
"apiEntity": "BillingItems",
|
|
@@ -5076,8 +5157,8 @@ var RELATIONSHIP_MAP = {
|
|
|
5076
5157
|
"unproven": false,
|
|
5077
5158
|
"blocker": {
|
|
5078
5159
|
"kind": "ok",
|
|
5079
|
-
"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)
|
|
5080
|
-
"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)"
|
|
5081
5162
|
},
|
|
5082
5163
|
"vendorEvidence": [
|
|
5083
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',
|
|
@@ -5087,7 +5168,75 @@ var RELATIONSHIP_MAP = {
|
|
|
5087
5168
|
"available": false,
|
|
5088
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."
|
|
5089
5170
|
},
|
|
5090
|
-
"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
|
+
]
|
|
5091
5240
|
}
|
|
5092
5241
|
},
|
|
5093
5242
|
"deleteBoundary": {
|
|
@@ -5117,6 +5266,27 @@ var RELATIONSHIP_MAP = {
|
|
|
5117
5266
|
"deleteBoundary": null,
|
|
5118
5267
|
"markerField": null
|
|
5119
5268
|
},
|
|
5269
|
+
"currencies": {
|
|
5270
|
+
"resource": "currencies",
|
|
5271
|
+
"apiEntity": "Currency",
|
|
5272
|
+
"kind": "entity",
|
|
5273
|
+
"path": "Currencies",
|
|
5274
|
+
"parentScoped": false,
|
|
5275
|
+
"tier": "advanced",
|
|
5276
|
+
"workflowResource": false,
|
|
5277
|
+
"group": "B",
|
|
5278
|
+
"parent": null,
|
|
5279
|
+
"children": [],
|
|
5280
|
+
"naturalKeys": {
|
|
5281
|
+
"hasSearch": true,
|
|
5282
|
+
"searchCovers": "name only (contains)",
|
|
5283
|
+
"findBy": []
|
|
5284
|
+
},
|
|
5285
|
+
"blindSurfaces": null,
|
|
5286
|
+
"zoneFacts": null,
|
|
5287
|
+
"deleteBoundary": null,
|
|
5288
|
+
"markerField": null
|
|
5289
|
+
},
|
|
5120
5290
|
"departments": {
|
|
5121
5291
|
"resource": "departments",
|
|
5122
5292
|
"apiEntity": "Department",
|
|
@@ -5504,6 +5674,27 @@ var RELATIONSHIP_MAP = {
|
|
|
5504
5674
|
"deleteBoundary": null,
|
|
5505
5675
|
"markerField": null
|
|
5506
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
|
+
},
|
|
5507
5698
|
"invoices": {
|
|
5508
5699
|
"resource": "invoices",
|
|
5509
5700
|
"apiEntity": "Invoice",
|
|
@@ -5694,6 +5885,138 @@ var RELATIONSHIP_MAP = {
|
|
|
5694
5885
|
"deleteBoundary": null,
|
|
5695
5886
|
"markerField": null
|
|
5696
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
|
+
},
|
|
5697
6020
|
"product_vendors": {
|
|
5698
6021
|
"resource": "product_vendors",
|
|
5699
6022
|
"apiEntity": "ProductVendors",
|
|
@@ -5846,7 +6169,13 @@ var RELATIONSHIP_MAP = {
|
|
|
5846
6169
|
"blocker": {
|
|
5847
6170
|
"kind": "blind-parent",
|
|
5848
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).",
|
|
5849
|
-
"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
|
+
}
|
|
5850
6179
|
},
|
|
5851
6180
|
"vendorEvidence": [
|
|
5852
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 '
|
|
@@ -6919,6 +7248,27 @@ var RELATIONSHIP_MAP = {
|
|
|
6919
7248
|
},
|
|
6920
7249
|
"markerField": "name"
|
|
6921
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
|
+
},
|
|
6922
7272
|
"service_call_task_resources": {
|
|
6923
7273
|
"resource": "service_call_task_resources",
|
|
6924
7274
|
"apiEntity": "ServiceCallTaskResource",
|
|
@@ -7577,26 +7927,70 @@ var RELATIONSHIP_MAP = {
|
|
|
7577
7927
|
"blindSurfaces": null,
|
|
7578
7928
|
"zoneFacts": {
|
|
7579
7929
|
"createGuidance": {
|
|
7580
|
-
"createOp": "task_secondary_resources.create",
|
|
7581
|
-
"parentScoped": true,
|
|
7930
|
+
"createOp": "task_secondary_resources.create",
|
|
7931
|
+
"parentScoped": true,
|
|
7932
|
+
"liveProvenPrefix": [],
|
|
7933
|
+
"unproven": true,
|
|
7934
|
+
"blocker": {
|
|
7935
|
+
"kind": "unknown",
|
|
7936
|
+
"message": "vendor 500: reference rejection on r (exact vendor text preserved verbatim in vendorEvidence \u2014 campaign receipt artifact, as recorded on disk)",
|
|
7937
|
+
"remedy": "the wall is opaque in the campaign record \u2014 inspect vendorEvidence for the exact vendor text, re-run the create with a live probe (dry-run first), and adjudicate against the vendored spec before retrying."
|
|
7938
|
+
},
|
|
7939
|
+
"vendorEvidence": [
|
|
7940
|
+
'{"error":true,"code":"SERVER_ERROR","category":"server","retryable":true,"httpStatus":500,"operation":"task_secondary_resources.create","suggestedAction":"Retry with backoff; the server error is transient.","correlationId":"d2783d1d-b23a-4c7d-9459-0089be7f9b0b","message":"Reference value on field: r'
|
|
7941
|
+
],
|
|
7942
|
+
"deleteBoundary": {
|
|
7943
|
+
"available": true,
|
|
7944
|
+
"note": null
|
|
7945
|
+
},
|
|
7946
|
+
"zone": "ww29"
|
|
7947
|
+
}
|
|
7948
|
+
},
|
|
7949
|
+
"deleteBoundary": null,
|
|
7950
|
+
"markerField": null
|
|
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,
|
|
7582
7973
|
"liveProvenPrefix": [],
|
|
7583
7974
|
"unproven": true,
|
|
7584
7975
|
"blocker": {
|
|
7585
7976
|
"kind": "unknown",
|
|
7586
|
-
"message": "
|
|
7587
|
-
"remedy": "
|
|
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."
|
|
7588
7979
|
},
|
|
7589
7980
|
"vendorEvidence": [
|
|
7590
|
-
|
|
7981
|
+
"api-docs.json: POST /V1.0/TaxRegions consumes definitions.TaxRegionModel and answers OperationResultModel \u2014 the entity defines no DELETE path."
|
|
7591
7982
|
],
|
|
7592
7983
|
"deleteBoundary": {
|
|
7593
|
-
"available":
|
|
7594
|
-
"note":
|
|
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."
|
|
7595
7986
|
},
|
|
7596
7987
|
"zone": "ww29"
|
|
7597
7988
|
}
|
|
7598
7989
|
},
|
|
7599
|
-
"deleteBoundary":
|
|
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
|
+
},
|
|
7600
7994
|
"markerField": null
|
|
7601
7995
|
},
|
|
7602
7996
|
"ticket_additional_configuration_items": {
|
|
@@ -7888,7 +8282,13 @@ var RELATIONSHIP_MAP = {
|
|
|
7888
8282
|
"blocker": {
|
|
7889
8283
|
"kind": "blind-parent",
|
|
7890
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).",
|
|
7891
|
-
"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
|
+
}
|
|
7892
8292
|
},
|
|
7893
8293
|
"vendorEvidence": [
|
|
7894
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'
|
|
@@ -8954,6 +9354,7 @@ var BLIND_SURFACE_STAMPS = {
|
|
|
8954
9354
|
}
|
|
8955
9355
|
};
|
|
8956
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.",
|
|
8957
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.",
|
|
8958
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.",
|
|
8959
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.",
|
|
@@ -8977,6 +9378,9 @@ var DELETE_BOUNDARY_NOTES = {
|
|
|
8977
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.",
|
|
8978
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.",
|
|
8979
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.",
|
|
8980
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.",
|
|
8981
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.",
|
|
8982
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.",
|
|
@@ -8991,6 +9395,7 @@ var DELETE_BOUNDARY_NOTES = {
|
|
|
8991
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.",
|
|
8992
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.",
|
|
8993
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.",
|
|
8994
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.",
|
|
8995
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.",
|
|
8996
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."
|
|
@@ -10492,6 +10897,18 @@ var BLIND_SURFACE_INVENTORY = {
|
|
|
10492
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.",
|
|
10493
10898
|
"proof": "live-verified"
|
|
10494
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
|
+
},
|
|
10495
10912
|
{
|
|
10496
10913
|
"resource": "billing_items",
|
|
10497
10914
|
"ops": [
|
|
@@ -11044,6 +11461,18 @@ var BLIND_SURFACE_INVENTORY = {
|
|
|
11044
11461
|
"note": "ww29 discovery sweep (marker FULL100-SEED-1791096521, 2026-10-04): the unfiltered limit-2 read returned 0 rows \u2014 INCONCLUSIVE (tenant-empty-for-user vs blind for this API user; a 0/empty result here proves nothing). countries.get is the authority for a specific record.",
|
|
11045
11462
|
"proof": "discovery-sweep"
|
|
11046
11463
|
},
|
|
11464
|
+
{
|
|
11465
|
+
"resource": "currencies",
|
|
11466
|
+
"ops": [
|
|
11467
|
+
"count",
|
|
11468
|
+
"query"
|
|
11469
|
+
],
|
|
11470
|
+
"kind": "unknown",
|
|
11471
|
+
"unfilteredRows": null,
|
|
11472
|
+
"authority": "currencies.get",
|
|
11473
|
+
"note": "Not swept: currencies was added after the ww29 discovery sweep, so no unfiltered read has been made for any tenant. Whether this API user sees currency rows through count/query is unknown; currencies.get is the authority for a specific record.",
|
|
11474
|
+
"proof": "spec-derived"
|
|
11475
|
+
},
|
|
11047
11476
|
{
|
|
11048
11477
|
"resource": "departments",
|
|
11049
11478
|
"ops": [
|
|
@@ -11140,6 +11569,18 @@ var BLIND_SURFACE_INVENTORY = {
|
|
|
11140
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).",
|
|
11141
11570
|
"proof": "discovery-sweep"
|
|
11142
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
|
+
},
|
|
11143
11584
|
{
|
|
11144
11585
|
"resource": "invoices",
|
|
11145
11586
|
"ops": [
|
|
@@ -11200,6 +11641,42 @@ var BLIND_SURFACE_INVENTORY = {
|
|
|
11200
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).",
|
|
11201
11642
|
"proof": "discovery-sweep"
|
|
11202
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
|
+
},
|
|
11203
11680
|
{
|
|
11204
11681
|
"resource": "phases",
|
|
11205
11682
|
"ops": [
|
|
@@ -11440,6 +11917,18 @@ var BLIND_SURFACE_INVENTORY = {
|
|
|
11440
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).",
|
|
11441
11918
|
"proof": "discovery-sweep"
|
|
11442
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
|
+
},
|
|
11443
11932
|
{
|
|
11444
11933
|
"resource": "service_call_task_resources",
|
|
11445
11934
|
"ops": [
|
|
@@ -11644,6 +12133,18 @@ var BLIND_SURFACE_INVENTORY = {
|
|
|
11644
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).",
|
|
11645
12134
|
"proof": "discovery-sweep"
|
|
11646
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
|
+
},
|
|
11647
12148
|
{
|
|
11648
12149
|
"resource": "ticket_additional_configuration_items",
|
|
11649
12150
|
"ops": [
|
|
@@ -11862,7 +12363,7 @@ var BLIND_SURFACE_INVENTORY = {
|
|
|
11862
12363
|
}
|
|
11863
12364
|
],
|
|
11864
12365
|
"counts": {
|
|
11865
|
-
"total":
|
|
12366
|
+
"total": 124,
|
|
11866
12367
|
"dataFull": 46,
|
|
11867
12368
|
"blind": 69,
|
|
11868
12369
|
"pinned": 6
|
|
@@ -11932,6 +12433,7 @@ var REACHABILITY_PROBE_DEFAULTS = {
|
|
|
11932
12433
|
"defaultTargets": [
|
|
11933
12434
|
"appointments",
|
|
11934
12435
|
"billing_codes",
|
|
12436
|
+
"billing_item_approval_levels",
|
|
11935
12437
|
"billing_items",
|
|
11936
12438
|
"change_request_links",
|
|
11937
12439
|
"classification_icons",
|
|
@@ -11964,10 +12466,15 @@ var REACHABILITY_PROBE_DEFAULTS = {
|
|
|
11964
12466
|
"contract_ticket_purchases",
|
|
11965
12467
|
"contracts",
|
|
11966
12468
|
"countries",
|
|
12469
|
+
"currencies",
|
|
11967
12470
|
"expense_items",
|
|
11968
12471
|
"expense_reports",
|
|
12472
|
+
"invoice_templates",
|
|
11969
12473
|
"invoices",
|
|
11970
12474
|
"notification_history",
|
|
12475
|
+
"organizational_level1s",
|
|
12476
|
+
"organizational_level2s",
|
|
12477
|
+
"organizational_level_associations",
|
|
11971
12478
|
"product_vendors",
|
|
11972
12479
|
"products",
|
|
11973
12480
|
"project_charges",
|
|
@@ -11982,6 +12489,7 @@ var REACHABILITY_PROBE_DEFAULTS = {
|
|
|
11982
12489
|
"resource_roles",
|
|
11983
12490
|
"resource_skills",
|
|
11984
12491
|
"resources",
|
|
12492
|
+
"sales_orders",
|
|
11985
12493
|
"service_call_task_resources",
|
|
11986
12494
|
"service_call_tasks",
|
|
11987
12495
|
"service_call_ticket_resources",
|
|
@@ -11991,6 +12499,7 @@ var REACHABILITY_PROBE_DEFAULTS = {
|
|
|
11991
12499
|
"skills",
|
|
11992
12500
|
"subscription_periods",
|
|
11993
12501
|
"subscriptions",
|
|
12502
|
+
"tax_regions",
|
|
11994
12503
|
"ticket_change_request_approvals",
|
|
11995
12504
|
"ticket_charges",
|
|
11996
12505
|
"ticket_history",
|
|
@@ -12031,6 +12540,28 @@ var CREATE_GUIDANCE = {
|
|
|
12031
12540
|
},
|
|
12032
12541
|
"zone": "ww29"
|
|
12033
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
|
+
},
|
|
12034
12565
|
{
|
|
12035
12566
|
"resource": "change_request_links",
|
|
12036
12567
|
"createOp": "change_request_links.create",
|
|
@@ -12962,8 +13493,8 @@ var CREATE_GUIDANCE = {
|
|
|
12962
13493
|
"unproven": false,
|
|
12963
13494
|
"blocker": {
|
|
12964
13495
|
"kind": "ok",
|
|
12965
|
-
"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)
|
|
12966
|
-
"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)"
|
|
12967
13498
|
},
|
|
12968
13499
|
"vendorEvidence": [
|
|
12969
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',
|
|
@@ -12973,7 +13504,75 @@ var CREATE_GUIDANCE = {
|
|
|
12973
13504
|
"available": false,
|
|
12974
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."
|
|
12975
13506
|
},
|
|
12976
|
-
"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
|
+
]
|
|
12977
13576
|
},
|
|
12978
13577
|
{
|
|
12979
13578
|
"resource": "departments",
|
|
@@ -13219,6 +13818,66 @@ var CREATE_GUIDANCE = {
|
|
|
13219
13818
|
},
|
|
13220
13819
|
"zone": "ww29"
|
|
13221
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
|
+
},
|
|
13222
13881
|
{
|
|
13223
13882
|
"resource": "phases",
|
|
13224
13883
|
"createOp": "phases.create",
|
|
@@ -13300,7 +13959,13 @@ var CREATE_GUIDANCE = {
|
|
|
13300
13959
|
"blocker": {
|
|
13301
13960
|
"kind": "blind-parent",
|
|
13302
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).",
|
|
13303
|
-
"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
|
+
}
|
|
13304
13969
|
},
|
|
13305
13970
|
"vendorEvidence": [
|
|
13306
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 '
|
|
@@ -13804,6 +14469,26 @@ var CREATE_GUIDANCE = {
|
|
|
13804
14469
|
},
|
|
13805
14470
|
"zone": "ww29"
|
|
13806
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
|
+
},
|
|
13807
14492
|
{
|
|
13808
14493
|
"resource": "ticket_additional_configuration_items",
|
|
13809
14494
|
"createOp": "ticket_additional_configuration_items.create",
|
|
@@ -13909,7 +14594,13 @@ var CREATE_GUIDANCE = {
|
|
|
13909
14594
|
"blocker": {
|
|
13910
14595
|
"kind": "blind-parent",
|
|
13911
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).",
|
|
13912
|
-
"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
|
+
}
|
|
13913
14604
|
},
|
|
13914
14605
|
"vendorEvidence": [
|
|
13915
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'
|
|
@@ -14132,7 +14823,30 @@ var CREATE_GUIDANCE = {
|
|
|
14132
14823
|
"available": true,
|
|
14133
14824
|
"note": null
|
|
14134
14825
|
},
|
|
14135
|
-
"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
|
+
]
|
|
14136
14850
|
},
|
|
14137
14851
|
{
|
|
14138
14852
|
"resource": "time_entry_attachments",
|
|
@@ -14161,7 +14875,7 @@ var CREATE_GUIDANCE = {
|
|
|
14161
14875
|
}
|
|
14162
14876
|
],
|
|
14163
14877
|
"counts": {
|
|
14164
|
-
"total":
|
|
14878
|
+
"total": 97,
|
|
14165
14879
|
"byKind": {
|
|
14166
14880
|
"ok": 31,
|
|
14167
14881
|
"blind-reference": 16,
|
|
@@ -14171,7 +14885,7 @@ var CREATE_GUIDANCE = {
|
|
|
14171
14885
|
"resource-role-pair": 2,
|
|
14172
14886
|
"delete-absent": 8,
|
|
14173
14887
|
"non-mutable": 0,
|
|
14174
|
-
"unknown":
|
|
14888
|
+
"unknown": 17
|
|
14175
14889
|
}
|
|
14176
14890
|
}
|
|
14177
14891
|
};
|
|
@@ -14400,6 +15114,10 @@ var UNTRUSTED_FIELDS_BY_RESOURCE = {
|
|
|
14400
15114
|
"displayName",
|
|
14401
15115
|
"name"
|
|
14402
15116
|
],
|
|
15117
|
+
"currencies": [
|
|
15118
|
+
"description",
|
|
15119
|
+
"name"
|
|
15120
|
+
],
|
|
14403
15121
|
"departments": [
|
|
14404
15122
|
"description",
|
|
14405
15123
|
"name"
|
|
@@ -14467,6 +15185,13 @@ var UNTRUSTED_FIELDS_BY_RESOURCE = {
|
|
|
14467
15185
|
"holidays": [
|
|
14468
15186
|
"holidayName"
|
|
14469
15187
|
],
|
|
15188
|
+
"invoice_templates": [
|
|
15189
|
+
"coveredByBlockRetainerContractLabel",
|
|
15190
|
+
"coveredByRecurringServiceFixedPricePerTicketContractLabel",
|
|
15191
|
+
"name",
|
|
15192
|
+
"nonBillableLaborLabel",
|
|
15193
|
+
"rateCostExpression"
|
|
15194
|
+
],
|
|
14470
15195
|
"invoices": [
|
|
14471
15196
|
"comments",
|
|
14472
15197
|
"taxRegionName"
|
|
@@ -14515,6 +15240,14 @@ var UNTRUSTED_FIELDS_BY_RESOURCE = {
|
|
|
14515
15240
|
"name",
|
|
14516
15241
|
"nickname"
|
|
14517
15242
|
],
|
|
15243
|
+
"organizational_level1s": [
|
|
15244
|
+
"description",
|
|
15245
|
+
"name"
|
|
15246
|
+
],
|
|
15247
|
+
"organizational_level2s": [
|
|
15248
|
+
"description",
|
|
15249
|
+
"name"
|
|
15250
|
+
],
|
|
14518
15251
|
"products": [
|
|
14519
15252
|
"UDF1",
|
|
14520
15253
|
"UDF10",
|
|
@@ -14652,6 +15385,34 @@ var UNTRUSTED_FIELDS_BY_RESOURCE = {
|
|
|
14652
15385
|
"description",
|
|
14653
15386
|
"name"
|
|
14654
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
|
+
],
|
|
14655
15416
|
"service_calls": [
|
|
14656
15417
|
"description"
|
|
14657
15418
|
],
|
|
@@ -14726,6 +15487,9 @@ var UNTRUSTED_FIELDS_BY_RESOURCE = {
|
|
|
14726
15487
|
"tags": [
|
|
14727
15488
|
"label"
|
|
14728
15489
|
],
|
|
15490
|
+
"tax_regions": [
|
|
15491
|
+
"name"
|
|
15492
|
+
],
|
|
14729
15493
|
"ticket_attachments": [
|
|
14730
15494
|
"title"
|
|
14731
15495
|
],
|
|
@@ -14841,7 +15605,7 @@ function attachEmptyReasonDetails(err) {
|
|
|
14841
15605
|
const resource = err.operation.slice(0, dot);
|
|
14842
15606
|
const op = err.operation.slice(dot + 1);
|
|
14843
15607
|
const surface = err.operation;
|
|
14844
|
-
const stamp = _optionalChain([EMPTY_REASON_STAMPS, 'access',
|
|
15608
|
+
const stamp = _optionalChain([EMPTY_REASON_STAMPS, 'access', _53 => _53[resource], 'optionalAccess', _54 => _54[op]]);
|
|
14845
15609
|
const pointer = POINTER_NOTES[surface];
|
|
14846
15610
|
const isGetMiss = err instanceof NotFoundError && op === "get";
|
|
14847
15611
|
if (stamp === void 0 && pointer === void 0 && !isGetMiss) return;
|
|
@@ -15036,7 +15800,7 @@ async function readBodyText(res, max, what, ctx) {
|
|
|
15036
15800
|
});
|
|
15037
15801
|
const declared = Number(res.headers.get("Content-Length"));
|
|
15038
15802
|
if (Number.isFinite(declared) && declared > max) {
|
|
15039
|
-
await _optionalChain([res, 'access',
|
|
15803
|
+
await _optionalChain([res, 'access', _55 => _55.body, 'optionalAccess', _56 => _56.cancel, 'call', _57 => _57(), 'access', _58 => _58.catch, 'call', _59 => _59(() => void 0)]);
|
|
15040
15804
|
throw tooLarge();
|
|
15041
15805
|
}
|
|
15042
15806
|
if (res.body === null) return "";
|
|
@@ -15057,7 +15821,7 @@ async function readBodyText(res, max, what, ctx) {
|
|
|
15057
15821
|
return text + decoder.decode();
|
|
15058
15822
|
}
|
|
15059
15823
|
function isJsonMediaType(header) {
|
|
15060
|
-
const mediaType = _nullishCoalesce(_optionalChain([header, 'access',
|
|
15824
|
+
const mediaType = _nullishCoalesce(_optionalChain([header, 'access', _60 => _60.split, 'call', _61 => _61(";"), 'access', _62 => _62[0], 'optionalAccess', _63 => _63.trim, 'call', _64 => _64(), 'access', _65 => _65.toLowerCase, 'call', _66 => _66()]), () => ( ""));
|
|
15061
15825
|
return mediaType.startsWith("application/json") || mediaType.endsWith("+json");
|
|
15062
15826
|
}
|
|
15063
15827
|
function bodySnippet(text, redactPersonalData) {
|
|
@@ -15137,7 +15901,7 @@ function recordSuccess(breaker, key, probe, logger) {
|
|
|
15137
15901
|
};
|
|
15138
15902
|
if (next.successes >= breaker.successesToClose) {
|
|
15139
15903
|
breaker.store.delete(key);
|
|
15140
|
-
_optionalChain([logger, 'access',
|
|
15904
|
+
_optionalChain([logger, 'access', _67 => _67.warn, 'optionalCall', _68 => _68(
|
|
15141
15905
|
`[autotask] circuit breaker CLOSED for ${key} (${next.successes} probe successes)`,
|
|
15142
15906
|
void 0
|
|
15143
15907
|
)]);
|
|
@@ -15152,7 +15916,7 @@ function recordFailure(breaker, key, probe, logger, correlationId) {
|
|
|
15152
15916
|
const failures = [...st.failures.filter((t) => t > now - breaker.failureWindowMs), now];
|
|
15153
15917
|
if (failures.length >= breaker.failureThreshold) {
|
|
15154
15918
|
breaker.store.set(key, { failures, openedAt: now, successes: 0, probes: 0 });
|
|
15155
|
-
_optionalChain([logger, 'access',
|
|
15919
|
+
_optionalChain([logger, 'access', _69 => _69.warn, 'optionalCall', _70 => _70(
|
|
15156
15920
|
`[autotask] circuit breaker OPEN for ${key} (${failures.length} counted failures in ${Math.round(breaker.failureWindowMs / 1e3)}s) \u2014 refusing locally for ${Math.round(breaker.openTimeoutMs / 1e3)}s`,
|
|
15157
15921
|
correlationId
|
|
15158
15922
|
)]);
|
|
@@ -15307,7 +16071,7 @@ async function discoverZoneBase(userName, maxResponseBytes, signal, ctx) {
|
|
|
15307
16071
|
return void 0;
|
|
15308
16072
|
}
|
|
15309
16073
|
if (res.status < 200 || res.status >= 300) {
|
|
15310
|
-
await _optionalChain([res, 'access',
|
|
16074
|
+
await _optionalChain([res, 'access', _71 => _71.body, 'optionalAccess', _72 => _72.cancel, 'call', _73 => _73(), 'access', _74 => _74.catch, 'call', _75 => _75(() => void 0)]);
|
|
15311
16075
|
return void 0;
|
|
15312
16076
|
}
|
|
15313
16077
|
let text;
|
|
@@ -15442,7 +16206,7 @@ var HttpClient = class {
|
|
|
15442
16206
|
this.maintenanceMaxWaitMs = config.maintenanceMaxWaitMs;
|
|
15443
16207
|
this.maintenancePollMs = config.maintenancePollMs;
|
|
15444
16208
|
this.maxResponseBytes = config.maxResponseBytes;
|
|
15445
|
-
this.hourly = _optionalChain([config, 'access',
|
|
16209
|
+
this.hourly = _optionalChain([config, 'access', _76 => _76.rateLimit, 'optionalAccess', _77 => _77.perHour]) === void 0 ? void 0 : new HourlyBudget(config.rateLimit.perHour, config.profile);
|
|
15446
16210
|
this.tenantKey = buildTenantKey(config.userName, config.baseUrl);
|
|
15447
16211
|
this.cooldownStore = config.cooldown.enabled ? _nullishCoalesce(config.cooldown.store, () => ( defaultCooldownStore())) : void 0;
|
|
15448
16212
|
this.cooldownMaxMs = config.cooldown.maxMs;
|
|
@@ -15472,7 +16236,7 @@ var HttpClient = class {
|
|
|
15472
16236
|
* `thresholdInformation.get()`.
|
|
15473
16237
|
*/
|
|
15474
16238
|
hourlyBudget() {
|
|
15475
|
-
return _optionalChain([this, 'access',
|
|
16239
|
+
return _optionalChain([this, 'access', _78 => _78.hourly, 'optionalAccess', _79 => _79.snapshot, 'call', _80 => _80()]);
|
|
15476
16240
|
}
|
|
15477
16241
|
/**
|
|
15478
16242
|
* One audit event per settled request (section 19.3): the correlation id,
|
|
@@ -15502,7 +16266,7 @@ var HttpClient = class {
|
|
|
15502
16266
|
this.liveBaseUrl = to;
|
|
15503
16267
|
this.tenantKey = buildTenantKey(this.auth.userName, to);
|
|
15504
16268
|
this.breakerKey = buildBreakerKey(to);
|
|
15505
|
-
_optionalChain([this, 'access',
|
|
16269
|
+
_optionalChain([this, 'access', _81 => _81.logger, 'access', _82 => _82.warn, 'optionalCall', _83 => _83(
|
|
15506
16270
|
`[autotask] zone re-point ${from} -> ${to} (a 401 on the stale zone base; the vendor's unauthenticated zone discovery named the tenant's current zone) \u2014 retrying the request once against the new base`,
|
|
15507
16271
|
void 0
|
|
15508
16272
|
)]);
|
|
@@ -15531,7 +16295,7 @@ var HttpClient = class {
|
|
|
15531
16295
|
/** The caller's signal wins over the deadline when both fired. */
|
|
15532
16296
|
interrupted(s) {
|
|
15533
16297
|
const { method, opts, ctx } = s;
|
|
15534
|
-
return _optionalChain([s, 'access',
|
|
16298
|
+
return _optionalChain([s, 'access', _84 => _84.callerSignal, 'optionalAccess', _85 => _85.aborted]) ? new AutotaskAbortError(`Request aborted: ${method} ${opts.path}`, { ...ctx, suggestedAction: "The caller aborted; re-issue the call if still needed." }) : new AutotaskTimeoutError(`Request timed out after ${s.timeoutMs}ms: ${method} ${opts.path}`, ctx);
|
|
15535
16299
|
}
|
|
15536
16300
|
/** A retry only runs when its wait fits inside what is left of the call budget. */
|
|
15537
16301
|
canWait(s, delay) {
|
|
@@ -15552,7 +16316,7 @@ var HttpClient = class {
|
|
|
15552
16316
|
/** If the retry's wait fits the budget: log, count the attempt, pause, and report true (loop again). */
|
|
15553
16317
|
async retryAfterDelay(s, delay, what) {
|
|
15554
16318
|
if (!this.canWait(s, delay)) return false;
|
|
15555
|
-
_optionalChain([this, 'access',
|
|
16319
|
+
_optionalChain([this, 'access', _86 => _86.logger, 'access', _87 => _87.warn, 'optionalCall', _88 => _88(
|
|
15556
16320
|
`[autotask] ${what}; retrying in ${delay}ms (attempt ${s.attempt + 1}/${s.maxRetries})`,
|
|
15557
16321
|
s.correlationId
|
|
15558
16322
|
)]);
|
|
@@ -15576,7 +16340,7 @@ var HttpClient = class {
|
|
|
15576
16340
|
const wait = Math.min(s.maintenancePollMs, remaining);
|
|
15577
16341
|
if (wait >= remaining) s.maintenanceBudgetSpent = true;
|
|
15578
16342
|
s.maintenanceWaits += 1;
|
|
15579
|
-
_optionalChain([this, 'access',
|
|
16343
|
+
_optionalChain([this, 'access', _89 => _89.logger, 'access', _90 => _90.warn, 'optionalCall', _91 => _91(
|
|
15580
16344
|
`[autotask] maintenance window on ${s.method} ${s.opts.path}${statusLabel}; waiting ${Math.round(wait / 1e3)}s (retry ${s.maintenanceWaits}, up to ${Math.round(s.maintenanceMaxWaitMs / 6e4)} min)`,
|
|
15581
16345
|
s.correlationId
|
|
15582
16346
|
)]);
|
|
@@ -15626,7 +16390,7 @@ var HttpClient = class {
|
|
|
15626
16390
|
if (this.cooldownStore === void 0 || s.opts.bypassCooldown) return;
|
|
15627
16391
|
const err = cooldownRefusal(this.cooldownStore, this.tenantKey, s.ctx);
|
|
15628
16392
|
if (err === void 0) return;
|
|
15629
|
-
if (_optionalChain([s, 'access',
|
|
16393
|
+
if (_optionalChain([s, 'access', _92 => _92.callerSignal, 'optionalAccess', _93 => _93.aborted])) throw this.interrupted(s);
|
|
15630
16394
|
this.auditNotSent(s, "RATE_LIMITED_COOLDOWN");
|
|
15631
16395
|
throw err;
|
|
15632
16396
|
}
|
|
@@ -15640,7 +16404,7 @@ var HttpClient = class {
|
|
|
15640
16404
|
*/
|
|
15641
16405
|
gateBreaker(s) {
|
|
15642
16406
|
if (this.breaker === void 0 || s.opts.bypassCircuitBreaker) return;
|
|
15643
|
-
if (_optionalChain([s, 'access',
|
|
16407
|
+
if (_optionalChain([s, 'access', _94 => _94.callerSignal, 'optionalAccess', _95 => _95.aborted])) throw this.interrupted(s);
|
|
15644
16408
|
const verdict = evaluateBreakerGate(this.breaker, this.breakerKey, s.ctx);
|
|
15645
16409
|
if (verdict.refusal !== void 0) {
|
|
15646
16410
|
this.auditNotSent(s, "CIRCUIT_BREAKER_OPEN");
|
|
@@ -15660,7 +16424,7 @@ var HttpClient = class {
|
|
|
15660
16424
|
async sendOnce(s) {
|
|
15661
16425
|
const { method, opts, ctx } = s;
|
|
15662
16426
|
try {
|
|
15663
|
-
await _optionalChain([this, 'access',
|
|
16427
|
+
await _optionalChain([this, 'access', _96 => _96.hourly, 'optionalAccess', _97 => _97.take, 'call', _98 => _98(s.deadlineAt, s.signal, ctx)]);
|
|
15664
16428
|
} catch (err) {
|
|
15665
16429
|
if (s.signal.aborted) throw this.interrupted(s);
|
|
15666
16430
|
throw err;
|
|
@@ -15686,7 +16450,7 @@ var HttpClient = class {
|
|
|
15686
16450
|
try {
|
|
15687
16451
|
status = res.status;
|
|
15688
16452
|
if (status >= 300 && status < 400) {
|
|
15689
|
-
await _optionalChain([res, 'access',
|
|
16453
|
+
await _optionalChain([res, 'access', _99 => _99.body, 'optionalAccess', _100 => _100.cancel, 'call', _101 => _101(), 'access', _102 => _102.catch, 'call', _103 => _103(() => void 0)]);
|
|
15690
16454
|
throw new ResponseRejectedError(
|
|
15691
16455
|
`Refused to follow a ${status} redirect for ${method} ${opts.path}`,
|
|
15692
16456
|
{ ...ctx, code: "REDIRECT_BLOCKED", httpStatus: status, suggestedAction: "Check the configured zone/baseUrl; the API does not redirect." }
|
|
@@ -15768,11 +16532,11 @@ var HttpClient = class {
|
|
|
15768
16532
|
const delay = retryAfter !== void 0 ? retryAfter * 1e3 : backoffDelay(s.attempt);
|
|
15769
16533
|
if (await this.retryAfterDelay(s, delay, `non-JSON 2xx on ${method} ${opts.path}`)) return RETRY;
|
|
15770
16534
|
}
|
|
15771
|
-
const pageSnippet = typeof _optionalChain([err, 'access',
|
|
16535
|
+
const pageSnippet = typeof _optionalChain([err, 'access', _104 => _104.details, 'optionalAccess', _105 => _105.bodySnippet]) === "string" ? err.details.bodySnippet : "";
|
|
15772
16536
|
this.stampMaintenance(s, err);
|
|
15773
16537
|
if (err.code === "UNEXPECTED_CONTENT_TYPE" && !looksLikeMaintenanceText(text) && isHtmlLike(res.headers.get("Content-Type"), text)) {
|
|
15774
16538
|
err.details = { ..._nullishCoalesce(err.details, () => ( {})), maintenancePatternMiss: true };
|
|
15775
|
-
_optionalChain([this, 'access',
|
|
16539
|
+
_optionalChain([this, 'access', _106 => _106.logger, 'access', _107 => _107.debug, 'optionalCall', _108 => _108(
|
|
15776
16540
|
`[autotask] non-JSON body did not match the maintenance vocabulary on ${method} ${opts.path}: ${pageSnippet}`,
|
|
15777
16541
|
s.correlationId
|
|
15778
16542
|
)]);
|
|
@@ -15815,7 +16579,7 @@ var HttpClient = class {
|
|
|
15815
16579
|
const target = await discoverZoneBase(this.userName, this.maxResponseBytes, s.signal, s.ctx);
|
|
15816
16580
|
const targetViolation = target === void 0 || this.hostPolicy === void 0 ? null : decideHostPolicy(target, this.hostPolicy);
|
|
15817
16581
|
if (targetViolation !== null) {
|
|
15818
|
-
_optionalChain([this, 'access',
|
|
16582
|
+
_optionalChain([this, 'access', _109 => _109.logger, 'access', _110 => _110.warn, 'optionalCall', _111 => _111(
|
|
15819
16583
|
`[autotask] zone re-point refused by hostPolicy (${targetViolation.bound}): ${targetViolation.origin} \u2014 the original 401 propagates, zero wire to the refused host`,
|
|
15820
16584
|
void 0
|
|
15821
16585
|
)]);
|
|
@@ -15844,7 +16608,7 @@ var HttpClient = class {
|
|
|
15844
16608
|
err.suggestedAction = `A maintenance-shaped page answered ${method} ${opts.path} (HTTP ${status}); it was NOT waited out or re-sent \u2014 a non-2xx edge page can arrive after the request was forwarded, so verify the record before re-issuing (only a GET or an explicitly idempotent-flagged call waits this window out).`;
|
|
15845
16609
|
} else if (!nonJsonIsMaintenance && nonJsonIsHtmlCandidate) {
|
|
15846
16610
|
err.details = { ..._nullishCoalesce(err.details, () => ( {})), maintenancePatternMiss: true };
|
|
15847
|
-
_optionalChain([this, 'access',
|
|
16611
|
+
_optionalChain([this, 'access', _112 => _112.logger, 'access', _113 => _113.debug, 'optionalCall', _114 => _114(
|
|
15848
16612
|
`[autotask] non-JSON body did not match the maintenance vocabulary on ${method} ${opts.path}: ${nonJsonSnippet}`,
|
|
15849
16613
|
s.correlationId
|
|
15850
16614
|
)]);
|
|
@@ -15866,7 +16630,7 @@ var HttpClient = class {
|
|
|
15866
16630
|
threadThreshold
|
|
15867
16631
|
});
|
|
15868
16632
|
this.cooldownStore.set(this.tenantKey, Date.now() + durationMs);
|
|
15869
|
-
_optionalChain([this, 'access',
|
|
16633
|
+
_optionalChain([this, 'access', _115 => _115.logger, 'access', _116 => _116.warn, 'optionalCall', _117 => _117(
|
|
15870
16634
|
`[autotask] 429 on ${method} ${opts.path} surfaces after ${s.attempt + 1} attempt(s); tenant cooldown armed for ${Math.round(durationMs / 1e3)}s`,
|
|
15871
16635
|
s.correlationId
|
|
15872
16636
|
)]);
|
|
@@ -15912,7 +16676,7 @@ var HttpClient = class {
|
|
|
15912
16676
|
if (this.fieldCache !== void 0 && err instanceof AutotaskError) {
|
|
15913
16677
|
const op = typeof opts.operation === "string" ? opts.operation : void 0;
|
|
15914
16678
|
const verb = op !== void 0 ? op.slice(op.lastIndexOf(".") + 1) : "";
|
|
15915
|
-
const drift = _optionalChain([err, 'access',
|
|
16679
|
+
const drift = _optionalChain([err, 'access', _118 => _118.details, 'optionalAccess', _119 => _119.deterministic]) === true || err.code === "INVALID_RESPONSE" && META_TRIO_VERBS.has(verb);
|
|
15916
16680
|
if (drift && op !== void 0) {
|
|
15917
16681
|
const dot = op.indexOf(".");
|
|
15918
16682
|
if (dot > 0) this.fieldCache.invalidate(op.slice(0, dot));
|
|
@@ -15922,7 +16686,7 @@ var HttpClient = class {
|
|
|
15922
16686
|
/** A real write (even a failed one — it may have partly applied) voids cached reads. */
|
|
15923
16687
|
invalidateAfterWrite(opts) {
|
|
15924
16688
|
if (opts.method === "GET" || opts.idempotent === true) return;
|
|
15925
|
-
_optionalChain([this, 'access',
|
|
16689
|
+
_optionalChain([this, 'access', _120 => _120.readCache, 'optionalAccess', _121 => _121.clear, 'call', _122 => _122()]);
|
|
15926
16690
|
this.latestCountCache.clear();
|
|
15927
16691
|
const nameOp = typeof opts.operation === "string" ? opts.operation : void 0;
|
|
15928
16692
|
const nameDot = nameOp !== void 0 ? nameOp.indexOf(".") : -1;
|
|
@@ -16003,7 +16767,7 @@ var HttpClient = class {
|
|
|
16003
16767
|
try {
|
|
16004
16768
|
this.gateCooldown(s);
|
|
16005
16769
|
this.gateBreaker(s);
|
|
16006
|
-
_optionalChain([this, 'access',
|
|
16770
|
+
_optionalChain([this, 'access', _123 => _123.logger, 'access', _124 => _124.debug, 'optionalCall', _125 => _125(`[autotask] ${method} ${opts.path}`, correlationId)]);
|
|
16007
16771
|
try {
|
|
16008
16772
|
for (; ; ) {
|
|
16009
16773
|
const sent = await this.sendOnce(s);
|
|
@@ -16213,7 +16977,7 @@ async function expandResourceNames(client, ids, opts = {}) {
|
|
|
16213
16977
|
continue;
|
|
16214
16978
|
}
|
|
16215
16979
|
}
|
|
16216
|
-
const epoch = _nullishCoalesce(_optionalChain([cache, 'optionalAccess',
|
|
16980
|
+
const epoch = _nullishCoalesce(_optionalChain([cache, 'optionalAccess', _126 => _126.epoch]), () => ( 0));
|
|
16217
16981
|
const work = (async () => {
|
|
16218
16982
|
try {
|
|
16219
16983
|
const record = await holder.get(id, { fresh });
|
|
@@ -16248,6 +17012,38 @@ async function expandResourceNames(client, ids, opts = {}) {
|
|
|
16248
17012
|
return { results, resolved, blind, failed };
|
|
16249
17013
|
}
|
|
16250
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
|
+
_chunk5CC7LGNMcjs.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 _nullishCoalesce(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
|
+
|
|
16251
17047
|
// src/operations/types.ts
|
|
16252
17048
|
var WORKFLOW_RESOURCES = [
|
|
16253
17049
|
"companies",
|
|
@@ -16261,24 +17057,36 @@ var WORKFLOW_RESOURCES = [
|
|
|
16261
17057
|
var MAX_FIELD_CATALOG_WIRE = 60;
|
|
16262
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.";
|
|
16263
17059
|
var FIELD_CATALOG_OPT_KEYS = ["resources", "include", "fresh", "fields", "labels"];
|
|
16264
|
-
function projectFieldRow(raw, labels = false) {
|
|
17060
|
+
function projectFieldRow(raw, labels = false, udf = false) {
|
|
16265
17061
|
const r = typeof raw === "object" && raw !== null ? raw : {};
|
|
16266
17062
|
const name = typeof r.name === "string" ? r.name : "";
|
|
16267
17063
|
const type = typeof r.dataType === "string" ? r.dataType : typeof r.type === "string" ? r.type : "";
|
|
16268
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);
|
|
16269
17067
|
return {
|
|
16270
17068
|
name,
|
|
16271
17069
|
...typeof r.label === "string" && r.label !== "" ? { label: r.label } : {},
|
|
16272
17070
|
type,
|
|
16273
17071
|
isRequired: r.isRequired === true,
|
|
16274
17072
|
isReadOnly: r.isReadOnly === true,
|
|
16275
|
-
|
|
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 },
|
|
16276
17077
|
isPickList: r.isPickList === true,
|
|
17078
|
+
...isObjectOrArrayType(type) ? { writeShape: "replace-all" } : {},
|
|
16277
17079
|
maxLength: typeof r.length === "number" ? r.length : null,
|
|
16278
|
-
referenceEntityType
|
|
17080
|
+
referenceEntityType,
|
|
17081
|
+
targetResource,
|
|
17082
|
+
targetEnumerable: isEnumerableResource(targetResource),
|
|
16279
17083
|
...values !== void 0 ? { picklistValues: values } : {}
|
|
16280
17084
|
};
|
|
16281
17085
|
}
|
|
17086
|
+
function isObjectOrArrayType(type) {
|
|
17087
|
+
const t = type.trim().toLowerCase();
|
|
17088
|
+
return t === "object" || t === "array" || t === "collection" || t.endsWith("[]");
|
|
17089
|
+
}
|
|
16282
17090
|
function exposesPicklistValues(raw) {
|
|
16283
17091
|
const r = typeof raw === "object" && raw !== null ? raw : {};
|
|
16284
17092
|
return Array.isArray(r.picklistValues) && r.picklistValues.length > 0;
|
|
@@ -16300,7 +17108,7 @@ function capabilitySets() {
|
|
|
16300
17108
|
const fieldOps = /* @__PURE__ */ new Map();
|
|
16301
17109
|
const udfOps = /* @__PURE__ */ new Map();
|
|
16302
17110
|
const resources = /* @__PURE__ */ new Set();
|
|
16303
|
-
for (const rec of
|
|
17111
|
+
for (const rec of _chunk5CC7LGNMcjs.CAPABILITIES) {
|
|
16304
17112
|
if (rec.resource === "operations") continue;
|
|
16305
17113
|
resources.add(rec.resource);
|
|
16306
17114
|
if (rec.operation === "getFieldInfo") fieldOps.set(rec.resource, rec);
|
|
@@ -16308,6 +17116,27 @@ function capabilitySets() {
|
|
|
16308
17116
|
}
|
|
16309
17117
|
return { fieldOps, udfOps, resources };
|
|
16310
17118
|
}
|
|
17119
|
+
var derivedIndex = null;
|
|
17120
|
+
function derivedFieldsFor(resource) {
|
|
17121
|
+
if (derivedIndex === null) {
|
|
17122
|
+
derivedIndex = /* @__PURE__ */ new Map();
|
|
17123
|
+
for (const rec of _chunk5CC7LGNMcjs.CAPABILITIES) {
|
|
17124
|
+
const declared = _optionalChain([rec, 'access', _127 => _127.metadata, 'optionalAccess', _128 => _128.derivedFields]);
|
|
17125
|
+
if (!Array.isArray(declared) || derivedIndex.has(rec.resource)) continue;
|
|
17126
|
+
const rows = [];
|
|
17127
|
+
for (const row of declared) {
|
|
17128
|
+
if (typeof _optionalChain([row, 'optionalAccess', _129 => _129.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 _nullishCoalesce(derivedIndex.get(resource), () => ( []));
|
|
17139
|
+
}
|
|
16311
17140
|
function apiEntityFor(rec) {
|
|
16312
17141
|
const m = /^GET \/V1\.0\/([^/]+)\/entityInformation\/fields$/.exec(_nullishCoalesce(rec.endpoint, () => ( "")));
|
|
16313
17142
|
if (m === null) {
|
|
@@ -16334,7 +17163,7 @@ function validateCatalogOptsShape(opts) {
|
|
|
16334
17163
|
}
|
|
16335
17164
|
}
|
|
16336
17165
|
function resolveInclude(opts) {
|
|
16337
|
-
const includeRaw = _nullishCoalesce(_optionalChain([opts, 'optionalAccess',
|
|
17166
|
+
const includeRaw = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _130 => _130.include]), () => ( ["fields"]));
|
|
16338
17167
|
if (!Array.isArray(includeRaw) || includeRaw.length === 0) {
|
|
16339
17168
|
throw new AutotaskConfigError("fieldCatalog: opts.include must be a non-empty array of (info|fields|udf)");
|
|
16340
17169
|
}
|
|
@@ -16351,7 +17180,7 @@ function resolveInclude(opts) {
|
|
|
16351
17180
|
return include;
|
|
16352
17181
|
}
|
|
16353
17182
|
function resolveTargets(opts, fieldOps, allResources) {
|
|
16354
|
-
const resourcesRaw = _nullishCoalesce(_optionalChain([opts, 'optionalAccess',
|
|
17183
|
+
const resourcesRaw = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _131 => _131.resources]), () => ( WORKFLOW_RESOURCES));
|
|
16355
17184
|
if (!Array.isArray(resourcesRaw) || resourcesRaw.length === 0) {
|
|
16356
17185
|
throw new AutotaskConfigError("fieldCatalog: opts.resources must be a non-empty array of plan resource keys");
|
|
16357
17186
|
}
|
|
@@ -16385,7 +17214,7 @@ function resolveTargets(opts, fieldOps, allResources) {
|
|
|
16385
17214
|
return targets;
|
|
16386
17215
|
}
|
|
16387
17216
|
function resolveFieldsFilter(opts) {
|
|
16388
|
-
const fieldsRaw = _optionalChain([opts, 'optionalAccess',
|
|
17217
|
+
const fieldsRaw = _optionalChain([opts, 'optionalAccess', _132 => _132.fields]);
|
|
16389
17218
|
if (fieldsRaw === void 0) return void 0;
|
|
16390
17219
|
if (!Array.isArray(fieldsRaw) || fieldsRaw.length === 0) {
|
|
16391
17220
|
throw new AutotaskConfigError("fieldCatalog: opts.fields must be a non-empty array of vendor field name strings");
|
|
@@ -16408,7 +17237,7 @@ function resolveLabels(opts) {
|
|
|
16408
17237
|
`fieldCatalog: opts.labels must be a boolean (got ${typeof opts.labels})`
|
|
16409
17238
|
);
|
|
16410
17239
|
}
|
|
16411
|
-
return _optionalChain([opts, 'optionalAccess',
|
|
17240
|
+
return _optionalChain([opts, 'optionalAccess', _133 => _133.labels]) === true;
|
|
16412
17241
|
}
|
|
16413
17242
|
function assertWithinWireCap(targetCount, kindCount) {
|
|
16414
17243
|
const cost = targetCount * kindCount;
|
|
@@ -16421,9 +17250,9 @@ function assertWithinWireCap(targetCount, kindCount) {
|
|
|
16421
17250
|
}
|
|
16422
17251
|
function kindFetches(holder, resource) {
|
|
16423
17252
|
return {
|
|
16424
|
-
info: () => _nullishCoalesce(_optionalChain([holder, 'optionalAccess',
|
|
16425
|
-
fields: () => _nullishCoalesce(_optionalChain([holder, 'optionalAccess',
|
|
16426
|
-
udf: () => _nullishCoalesce(_optionalChain([holder, 'optionalAccess',
|
|
17253
|
+
info: () => _nullishCoalesce(_optionalChain([holder, 'optionalAccess', _134 => _134.getEntityInfo, 'optionalCall', _135 => _135()]), () => ( Promise.reject(new AutotaskError(`fieldCatalog: the client exposes no getEntityInfo read for "${resource}"`, { code: "INVALID_RESPONSE", category: "server" })))),
|
|
17254
|
+
fields: () => _nullishCoalesce(_optionalChain([holder, 'optionalAccess', _136 => _136.getFieldInfo, 'optionalCall', _137 => _137()]), () => ( Promise.reject(new AutotaskError(`fieldCatalog: the client exposes no getFieldInfo read for "${resource}"`, { code: "INVALID_RESPONSE", category: "server" })))),
|
|
17255
|
+
udf: () => _nullishCoalesce(_optionalChain([holder, 'optionalAccess', _138 => _138.getUdfInfo, 'optionalCall', _139 => _139()]), () => ( Promise.reject(new AutotaskError(`fieldCatalog: the client exposes no getUdfInfo read for "${resource}"`, { code: "INVALID_RESPONSE", category: "server" }))))
|
|
16427
17256
|
};
|
|
16428
17257
|
}
|
|
16429
17258
|
async function sweepResource(ctx, resource, tally) {
|
|
@@ -16437,6 +17266,8 @@ async function sweepResource(ctx, resource, tally) {
|
|
|
16437
17266
|
resource,
|
|
16438
17267
|
apiEntity,
|
|
16439
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" } : {},
|
|
16440
17271
|
unmatchedFields: [],
|
|
16441
17272
|
required: [],
|
|
16442
17273
|
readOnly: [],
|
|
@@ -16447,9 +17278,9 @@ async function sweepResource(ctx, resource, tally) {
|
|
|
16447
17278
|
error: null
|
|
16448
17279
|
};
|
|
16449
17280
|
const fetches = kindFetches(holder, resource);
|
|
16450
|
-
if (fresh) _optionalChain([cache, 'optionalAccess',
|
|
17281
|
+
if (fresh) _optionalChain([cache, 'optionalAccess', _140 => _140.invalidate, 'call', _141 => _141(resource)]);
|
|
16451
17282
|
const projectList = (kind, list) => {
|
|
16452
|
-
const projected = list.map((f) => projectFieldRow(f, labels));
|
|
17283
|
+
const projected = list.map((f) => projectFieldRow(f, labels, kind === "udf"));
|
|
16453
17284
|
if (kind === "fields") applyFieldsFilter(projected, fieldsFilter, row);
|
|
16454
17285
|
else row.udf = projected;
|
|
16455
17286
|
for (const f of list) if (exposesPicklistValues(f)) tally.anyPicklistValues = true;
|
|
@@ -16489,6 +17320,19 @@ async function sweepResource(ctx, resource, tally) {
|
|
|
16489
17320
|
}
|
|
16490
17321
|
}
|
|
16491
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 _nullishCoalesce(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
|
+
}
|
|
16492
17336
|
return row;
|
|
16493
17337
|
}
|
|
16494
17338
|
async function fieldCatalog(client, opts) {
|
|
@@ -16503,7 +17347,7 @@ async function fieldCatalog(client, opts) {
|
|
|
16503
17347
|
const zone = _nullishCoalesce(client.config.zone, () => ( "unknown"));
|
|
16504
17348
|
const rows = [];
|
|
16505
17349
|
const tally = { wireUsed: 0, anyPicklistValues: false };
|
|
16506
|
-
const ctx = { client, include, fieldsFilter, labels, fresh: _optionalChain([opts, 'optionalAccess',
|
|
17350
|
+
const ctx = { client, include, fieldsFilter, labels, fresh: _optionalChain([opts, 'optionalAccess', _142 => _142.fresh]) === true, fieldOps, udfOps };
|
|
16507
17351
|
for (const resource of targets) {
|
|
16508
17352
|
const row = await sweepResource(ctx, resource, tally);
|
|
16509
17353
|
if (row !== void 0) rows.push(row);
|
|
@@ -16513,7 +17357,7 @@ async function fieldCatalog(client, opts) {
|
|
|
16513
17357
|
label: zone,
|
|
16514
17358
|
cached: cache !== void 0,
|
|
16515
17359
|
labels,
|
|
16516
|
-
ttlMs: _nullishCoalesce(_optionalChain([cache, 'optionalAccess',
|
|
17360
|
+
ttlMs: _nullishCoalesce(_optionalChain([cache, 'optionalAccess', _143 => _143.ttlMs]), () => ( null)),
|
|
16517
17361
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16518
17362
|
rows,
|
|
16519
17363
|
wireUsed: tally.wireUsed,
|
|
@@ -16678,7 +17522,7 @@ async function resolveCompositeNames(http, plan, opts = {}) {
|
|
|
16678
17522
|
} else {
|
|
16679
17523
|
for (const f of plan.labelFields) {
|
|
16680
17524
|
const frow = row.fields.find((x) => x.name === f);
|
|
16681
|
-
picklists[f] = _optionalChain([frow, 'optionalAccess',
|
|
17525
|
+
picklists[f] = _optionalChain([frow, 'optionalAccess', _144 => _144.picklistValues]);
|
|
16682
17526
|
}
|
|
16683
17527
|
}
|
|
16684
17528
|
} catch (err) {
|
|
@@ -16689,8 +17533,8 @@ async function resolveCompositeNames(http, plan, opts = {}) {
|
|
|
16689
17533
|
}
|
|
16690
17534
|
return {
|
|
16691
17535
|
section,
|
|
16692
|
-
resourceName: (id) => _nullishCoalesce(_optionalChain([section, 'access',
|
|
16693
|
-
recordName: (table, id) => _nullishCoalesce(_optionalChain([section, 'access',
|
|
17536
|
+
resourceName: (id) => _nullishCoalesce(_optionalChain([section, 'access', _145 => _145.rows, 'access', _146 => _146[`resource:${id}`], 'optionalAccess', _147 => _147.name]), () => ( null)),
|
|
17537
|
+
recordName: (table, id) => _nullishCoalesce(_optionalChain([section, 'access', _148 => _148.rows, 'access', _149 => _149[`${table}:${id}`], 'optionalAccess', _150 => _150.name]), () => ( null)),
|
|
16694
17538
|
labelFor: (field, value) => {
|
|
16695
17539
|
if (value === null || value === void 0) return null;
|
|
16696
17540
|
const values = picklists[field];
|
|
@@ -16712,6 +17556,7 @@ async function resolveCompositeNames(http, plan, opts = {}) {
|
|
|
16712
17556
|
var MODEL_FIELD_SETS = {
|
|
16713
17557
|
"appointments": ["id", "createDateTime", "creatorResourceID", "description", "endDateTime", "resourceID", "startDateTime", "title", "updateDateTime"],
|
|
16714
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"],
|
|
16715
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"],
|
|
16716
17561
|
"change_request_links": ["id", "changeRequestTicketID", "problemOrIncidentTicketID"],
|
|
16717
17562
|
"checklist_libraries": ["id", "description", "entityType", "isActive", "name"],
|
|
@@ -16758,6 +17603,7 @@ var MODEL_FIELD_SETS = {
|
|
|
16758
17603
|
"contract_ticket_purchases": ["id", "contractID", "datePurchased", "endDate", "invoiceNumber", "isPaid", "paymentNumber", "paymentType", "perTicketRate", "startDate", "status", "ticketsPurchased", "ticketsUsed", "soapParentPropertyId"],
|
|
16759
17604
|
"contracts": ["id", "billingPreference", "billToCompanyContactID", "billToCompanyID", "companyID", "contactID", "contactName", "contractCategory", "contractExclusionSetID", "contractName", "contractNumber", "contractPeriodType", "contractType", "description", "endDate", "estimatedCost", "estimatedHours", "estimatedRevenue", "exclusionContractID", "internalCurrencyOverageBillingRate", "internalCurrencySetupFee", "isCompliant", "isDefaultContract", "lastModifiedDateTime", "opportunityID", "organizationalLevelAssociationID", "overageBillingRate", "purchaseOrderNumber", "renewedContractID", "serviceLevelAgreementID", "setupFee", "setupFeeBillingCodeID", "startDate", "status", "timeReportingRequiresStartAndStopTimes", "userDefinedFields"],
|
|
16760
17605
|
"countries": ["id", "addressFormatID", "countryCode", "displayName", "invoiceTemplateID", "isActive", "isDefaultCountry", "name", "purchaseOrderTemplateID", "quoteTemplateID"],
|
|
17606
|
+
"currencies": ["id", "currencyNegativeFormat", "currencyPositiveFormat", "description", "displaySymbol", "exchangeRate", "isActive", "isInternalCurrency", "lastModifiedDateTime", "name", "updateResourceId"],
|
|
16761
17607
|
"departments": ["id", "description", "name", "number", "primaryLocationID"],
|
|
16762
17608
|
"domain_registrars": ["id", "name", "url"],
|
|
16763
17609
|
"expense_item_attachments": ["id", "attachDate", "attachedByContactID", "attachedByResourceID", "attachmentType", "contentType", "creatorType", "expenseItemID", "expenseReportID", "fileSize", "fullPath", "impersonatorCreatorResourceID", "opportunityID", "parentID", "publish", "title", "data", "parentType", "soapParentPropertyId", "isTaskAttachment"],
|
|
@@ -16766,11 +17612,15 @@ var MODEL_FIELD_SETS = {
|
|
|
16766
17612
|
"holiday_sets": ["id", "holidaySetDescription", "holidaySetName"],
|
|
16767
17613
|
"holidays": ["id", "holidayDate", "holidayName", "holidaySetID", "soapParentPropertyId"],
|
|
16768
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"],
|
|
16769
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"],
|
|
16770
17617
|
"notification_history": ["id", "companyID", "entityNumber", "entityTitle", "initiatingContactID", "initiatingResourceID", "isActive", "isDeleted", "isTemplateJob", "notificationHistoryTypeID", "notificationSentTime", "opportunityID", "projectID", "quoteID", "recipientDisplayName", "recipientEmailAddress", "taskID", "templateName", "ticketID", "timeEntryID"],
|
|
16771
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"],
|
|
16772
17619
|
"opportunity_attachments": ["id", "attachDate", "attachedByContactID", "attachedByResourceID", "attachmentType", "contentType", "creatorType", "fileSize", "fullPath", "impersonatorCreatorResourceID", "opportunityID", "parentAttachmentID", "parentID", "publish", "title", "data", "parentType", "soapParentPropertyId", "isTaskAttachment"],
|
|
16773
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"],
|
|
16774
17624
|
"phases": ["id", "createDate", "creatorResourceID", "description", "dueDate", "estimatedHours", "externalID", "isScheduled", "lastActivityDateTime", "parentPhaseID", "phaseNumber", "projectID", "startDate", "title", "soapParentPropertyId"],
|
|
16775
17625
|
"product_vendors": ["id", "isActive", "isDefault", "productID", "vendorCost", "vendorID", "vendorPartNumber", "soapParentPropertyId"],
|
|
16776
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"],
|
|
@@ -16792,6 +17642,7 @@ var MODEL_FIELD_SETS = {
|
|
|
16792
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"],
|
|
16793
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"],
|
|
16794
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"],
|
|
16795
17646
|
"service_call_task_resources": ["id", "resourceID", "serviceCallTaskID", "soapParentPropertyId"],
|
|
16796
17647
|
"service_call_tasks": ["id", "serviceCallID", "taskID", "soapParentPropertyId"],
|
|
16797
17648
|
"service_call_ticket_resources": ["id", "resourceID", "serviceCallTicketID", "soapParentPropertyId"],
|
|
@@ -16809,6 +17660,7 @@ var MODEL_FIELD_SETS = {
|
|
|
16809
17660
|
"tags": ["id", "createDateTime", "isActive", "isExcludedFromAutomaticTagging", "isSystem", "label", "lastModifiedDateTime", "tagGroupID"],
|
|
16810
17661
|
"task_secondary_resources": ["id", "resourceID", "roleID", "taskID", "soapParentPropertyId"],
|
|
16811
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"],
|
|
16812
17664
|
"ticket_additional_configuration_items": ["id", "configurationItemID", "ticketID", "soapParentPropertyId"],
|
|
16813
17665
|
"ticket_additional_contacts": ["id", "contactID", "ticketID", "soapParentPropertyId"],
|
|
16814
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"],
|
|
@@ -16830,6 +17682,7 @@ var MODEL_FIELD_SETS = {
|
|
|
16830
17682
|
};
|
|
16831
17683
|
var MODEL_DATE_FIELDS = {
|
|
16832
17684
|
"appointments": ["createDateTime", "endDateTime", "startDateTime", "updateDateTime"],
|
|
17685
|
+
"billing_item_approval_levels": ["approvalDateTime"],
|
|
16833
17686
|
"billing_items": ["itemDate", "postedDate", "postedOnTime", "webServiceDate"],
|
|
16834
17687
|
"companies": ["createDate", "lastActivityDate", "lastTrackedModifiedDateTime"],
|
|
16835
17688
|
"company_notes": ["completedDateTime", "createDateTime", "endDateTime", "lastModifiedDate", "startDateTime"],
|
|
@@ -16848,6 +17701,7 @@ var MODEL_DATE_FIELDS = {
|
|
|
16848
17701
|
"contract_service_units": ["approveAndPostDate", "endDate", "startDate"],
|
|
16849
17702
|
"contract_ticket_purchases": ["datePurchased", "endDate", "startDate"],
|
|
16850
17703
|
"contracts": ["endDate", "lastModifiedDateTime", "startDate"],
|
|
17704
|
+
"currencies": ["lastModifiedDateTime"],
|
|
16851
17705
|
"expense_item_attachments": ["attachDate"],
|
|
16852
17706
|
"expense_items": ["expenseDate"],
|
|
16853
17707
|
"expense_reports": ["approvedDate", "submitDate", "weekEnding"],
|
|
@@ -16868,6 +17722,7 @@ var MODEL_DATE_FIELDS = {
|
|
|
16868
17722
|
"quote_templates": ["createDate", "lastActivityDate"],
|
|
16869
17723
|
"quotes": ["approvalStatusChangedDate", "createDate", "effectiveDate", "expirationDate", "extApprovalResponseDate", "lastActivityDate", "lastPublishedDateTime"],
|
|
16870
17724
|
"resources": ["hireDate"],
|
|
17725
|
+
"sales_orders": ["promisedFulfillmentDate", "salesOrderDate"],
|
|
16871
17726
|
"service_calls": ["canceledDateTime", "createDateTime", "endDateTime", "lastModifiedDateTime", "startDateTime"],
|
|
16872
17727
|
"services": ["createDate", "lastModifiedDate"],
|
|
16873
17728
|
"subscription_periods": ["periodDate", "postedDate"],
|
|
@@ -16961,8 +17816,8 @@ function validateFetchManyItems(items, cap, opName = "fetchMany", capRef = `FETC
|
|
|
16961
17816
|
problems.push(`${at}.fields: must be an array of exact vendor field names (discover them via operations.fieldCatalog)`);
|
|
16962
17817
|
continue;
|
|
16963
17818
|
}
|
|
16964
|
-
if (_optionalChain([validation, 'optionalAccess',
|
|
16965
|
-
const authoritative = _nullishCoalesce(_optionalChain([validation, 'optionalAccess',
|
|
17819
|
+
if (_optionalChain([validation, 'optionalAccess', _151 => _151.fieldCheck]) !== false) {
|
|
17820
|
+
const authoritative = _nullishCoalesce(_optionalChain([validation, 'optionalAccess', _152 => _152.fieldSetsByResource, 'optionalAccess', _153 => _153.get, 'call', _154 => _154(resourceKey)]), () => ( fields));
|
|
16966
17821
|
for (const f of item.fields) {
|
|
16967
17822
|
if (!authoritative.includes(f)) {
|
|
16968
17823
|
problems.push(
|
|
@@ -17066,7 +17921,7 @@ function project2(value, fields) {
|
|
|
17066
17921
|
return out;
|
|
17067
17922
|
}
|
|
17068
17923
|
function resourcePathOf(key, holder) {
|
|
17069
|
-
const path = _optionalChain([holder, 'optionalAccess',
|
|
17924
|
+
const path = _optionalChain([holder, 'optionalAccess', _155 => _155.resourcePath]);
|
|
17070
17925
|
if (typeof path !== "string" || path === "") {
|
|
17071
17926
|
throw new AutotaskConfigError(`fetchByIds: the client exposes no ${key} resource path (registry drift)`, {
|
|
17072
17927
|
suggestedAction: "Rebuild the client from the SDK build that ships this registry (the resource set is pinned by the plan)."
|
|
@@ -17202,7 +18057,7 @@ function uiHostFromBase(baseUrl) {
|
|
|
17202
18057
|
} catch (e18) {
|
|
17203
18058
|
return void 0;
|
|
17204
18059
|
}
|
|
17205
|
-
const n = _optionalChain([REST_HOST, 'access',
|
|
18060
|
+
const n = _optionalChain([REST_HOST, 'access', _156 => _156.exec, 'call', _157 => _157(hostname), 'optionalAccess', _158 => _158[1]]);
|
|
17206
18061
|
return n === void 0 ? void 0 : `ww${n}.autotask.net`;
|
|
17207
18062
|
}
|
|
17208
18063
|
function buildUiLink(input) {
|
|
@@ -17308,7 +18163,7 @@ function blindEmptyReason(stamp) {
|
|
|
17308
18163
|
};
|
|
17309
18164
|
}
|
|
17310
18165
|
function attachUpdateTargetMissReason(err, key) {
|
|
17311
|
-
const pinned = _optionalChain([EMPTY_REASON_STAMPS, 'access',
|
|
18166
|
+
const pinned = _optionalChain([EMPTY_REASON_STAMPS, 'access', _159 => _159[key], 'optionalAccess', _160 => _160.update]);
|
|
17312
18167
|
if (pinned === void 0) return;
|
|
17313
18168
|
err.details = { ..._nullishCoalesce(err.details, () => ( {})), emptyReason: pinned };
|
|
17314
18169
|
}
|
|
@@ -17493,7 +18348,7 @@ var QueryBase = class {
|
|
|
17493
18348
|
}
|
|
17494
18349
|
/** @internal */
|
|
17495
18350
|
walkPageSize(params) {
|
|
17496
|
-
return clampPageSize(_nullishCoalesce(_optionalChain([params, 'optionalAccess',
|
|
18351
|
+
return clampPageSize(_nullishCoalesce(_optionalChain([params, 'optionalAccess', _161 => _161.maxRecords]), () => ( this.defaultPageSize)));
|
|
17497
18352
|
}
|
|
17498
18353
|
/** Stream items across pages (the resource `query` surface). */
|
|
17499
18354
|
queryItems(params) {
|
|
@@ -17505,7 +18360,7 @@ var QueryBase = class {
|
|
|
17505
18360
|
}
|
|
17506
18361
|
/** Collect every item across all pages (the resource `queryAll` surface; 1000-page guarded). */
|
|
17507
18362
|
async queryAllItems(params) {
|
|
17508
|
-
return collectAll(this.pageFetcher(params), { pageSize: this.walkPageSize(params), maxRecords: _optionalChain([params, 'optionalAccess',
|
|
18363
|
+
return collectAll(this.pageFetcher(params), { pageSize: this.walkPageSize(params), maxRecords: _optionalChain([params, 'optionalAccess', _162 => _162.maxTotalRecords]) });
|
|
17509
18364
|
}
|
|
17510
18365
|
/**
|
|
17511
18366
|
* `queryBounded` — server-side pagination (the MCP query surface): ONE call
|
|
@@ -17542,19 +18397,19 @@ var QueryBase = class {
|
|
|
17542
18397
|
"queryBounded: params must be an object { filter?, limit?, latest?, includeFields? } \u2014 a bare conditions array is not accepted (wrap it: { filter: [...] })"
|
|
17543
18398
|
);
|
|
17544
18399
|
}
|
|
17545
|
-
const limit = _nullishCoalesce(_optionalChain([params, 'optionalAccess',
|
|
18400
|
+
const limit = _nullishCoalesce(_optionalChain([params, 'optionalAccess', _163 => _163.limit]), () => ( BOUNDED_QUERY_DEFAULT_LIMIT));
|
|
17546
18401
|
if (!Number.isInteger(limit) || limit < 1 || limit > BOUNDED_QUERY_MAX_LIMIT) {
|
|
17547
18402
|
throw new AutotaskConfigError(
|
|
17548
18403
|
`queryBounded: limit must be an integer 1..${BOUNDED_QUERY_MAX_LIMIT} (got ${String(limit)}) \u2014 it is the TOTAL record cap, not a page size`
|
|
17549
18404
|
);
|
|
17550
18405
|
}
|
|
17551
|
-
const noteChars = _optionalChain([params, 'optionalAccess',
|
|
18406
|
+
const noteChars = _optionalChain([params, 'optionalAccess', _164 => _164.noteChars]);
|
|
17552
18407
|
if (noteChars !== void 0 && (!Number.isInteger(noteChars) || noteChars < 1)) {
|
|
17553
18408
|
throw new AutotaskConfigError(
|
|
17554
18409
|
`queryBounded: noteChars must be an integer >= 1 (got ${String(noteChars)}) \u2014 it is the per-field char cap on the untrusted-class free-text fields (absent = the raw, untruncated result)`
|
|
17555
18410
|
);
|
|
17556
18411
|
}
|
|
17557
|
-
const walkParams = _optionalChain([params, 'optionalAccess',
|
|
18412
|
+
const walkParams = _optionalChain([params, 'optionalAccess', _165 => _165.fieldsPreset]) !== void 0 ? { ...params, includeFields: resolveFieldsPreset(params.fieldsPreset, this.config.key, params.includeFields) } : _nullishCoalesce(params, () => ( {}));
|
|
17558
18413
|
const latest = walkParams.latest;
|
|
17559
18414
|
if (latest !== void 0) {
|
|
17560
18415
|
if (!Number.isInteger(latest) || latest < 1 || latest > BOUNDED_QUERY_MAX_LIMIT) {
|
|
@@ -17562,7 +18417,7 @@ var QueryBase = class {
|
|
|
17562
18417
|
`queryBounded: latest must be an integer 1..${BOUNDED_QUERY_MAX_LIMIT} (got ${String(latest)}) \u2014 it is the count of the highest-id rows to return`
|
|
17563
18418
|
);
|
|
17564
18419
|
}
|
|
17565
|
-
if (_optionalChain([params, 'optionalAccess',
|
|
18420
|
+
if (_optionalChain([params, 'optionalAccess', _166 => _166.limit]) !== void 0 && limit < latest) {
|
|
17566
18421
|
throw new AutotaskConfigError(
|
|
17567
18422
|
`queryBounded: limit (${String(limit)}) must be >= latest (${String(latest)}) \u2014 latest governs the returned count and limit is the walk window`
|
|
17568
18423
|
);
|
|
@@ -17648,8 +18503,8 @@ var QueryBase = class {
|
|
|
17648
18503
|
* @internal */
|
|
17649
18504
|
stampEmptyQueryResult(result, params) {
|
|
17650
18505
|
if (result.items.length !== 0) return;
|
|
17651
|
-
result.blindSurface = blindStampFor(_optionalChain([BLIND_SURFACE_STAMPS, 'access',
|
|
17652
|
-
const pinnedReason = normalizedConditions(_optionalChain([params, 'optionalAccess',
|
|
18506
|
+
result.blindSurface = blindStampFor(_optionalChain([BLIND_SURFACE_STAMPS, 'access', _167 => _167[this.config.key], 'optionalAccess', _168 => _168.query]), _optionalChain([params, 'optionalAccess', _169 => _169.filter]));
|
|
18507
|
+
const pinnedReason = normalizedConditions(_optionalChain([params, 'optionalAccess', _170 => _170.filter])) === void 0 ? _optionalChain([EMPTY_REASON_STAMPS, 'access', _171 => _171[this.config.key], 'optionalAccess', _172 => _172.query]) : void 0;
|
|
17653
18508
|
if (result.blindSurface !== void 0 || pinnedReason !== void 0) {
|
|
17654
18509
|
result.emptyReason = result.blindSurface !== void 0 ? blindEmptyReason(result.blindSurface) : pinnedReason;
|
|
17655
18510
|
}
|
|
@@ -17878,7 +18733,7 @@ var QueryBase = class {
|
|
|
17878
18733
|
if (result.items.length === 0) {
|
|
17879
18734
|
this.stampEmptyQueryResult(result, params);
|
|
17880
18735
|
} else {
|
|
17881
|
-
result.blindSurface = blindStampFor(_optionalChain([BLIND_SURFACE_STAMPS, 'access',
|
|
18736
|
+
result.blindSurface = blindStampFor(_optionalChain([BLIND_SURFACE_STAMPS, 'access', _173 => _173[this.config.key], 'optionalAccess', _174 => _174.query]), params.filter);
|
|
17882
18737
|
}
|
|
17883
18738
|
return result;
|
|
17884
18739
|
}
|
|
@@ -17919,7 +18774,7 @@ var QueryBase = class {
|
|
|
17919
18774
|
* or, on a plan-pinned blind surface, the `{ count: 0, blindSurface }`
|
|
17920
18775
|
* typed sentinel (S12-C T10; see `BlindCountResult`). */
|
|
17921
18776
|
async countGlobal(params) {
|
|
17922
|
-
const conditions = normalizedConditions(_optionalChain([params, 'optionalAccess',
|
|
18777
|
+
const conditions = normalizedConditions(_optionalChain([params, 'optionalAccess', _175 => _175.filter]));
|
|
17923
18778
|
const body = {};
|
|
17924
18779
|
body.filter = conditions === void 0 ? [] : buildFilter(conditions).filter;
|
|
17925
18780
|
const res = await this.http.request({
|
|
@@ -17930,9 +18785,9 @@ var QueryBase = class {
|
|
|
17930
18785
|
idempotent: true
|
|
17931
18786
|
});
|
|
17932
18787
|
const count = unwrapQueryCount(res, `${this.config.key}.count`);
|
|
17933
|
-
const stamp = blindStampFor(_optionalChain([BLIND_SURFACE_STAMPS, 'access',
|
|
18788
|
+
const stamp = blindStampFor(_optionalChain([BLIND_SURFACE_STAMPS, 'access', _176 => _176[this.config.key], 'optionalAccess', _177 => _177.count]), _optionalChain([params, 'optionalAccess', _178 => _178.filter]));
|
|
17934
18789
|
if (count === 0) {
|
|
17935
|
-
const pinnedReason = conditions === void 0 ? _optionalChain([EMPTY_REASON_STAMPS, 'access',
|
|
18790
|
+
const pinnedReason = conditions === void 0 ? _optionalChain([EMPTY_REASON_STAMPS, 'access', _179 => _179[this.config.key], 'optionalAccess', _180 => _180.count]) : void 0;
|
|
17936
18791
|
if (stamp !== void 0 || pinnedReason !== void 0) {
|
|
17937
18792
|
return {
|
|
17938
18793
|
count,
|
|
@@ -17968,9 +18823,9 @@ var MetaBase = class extends QueryBase {
|
|
|
17968
18823
|
const hit = cache.get(path);
|
|
17969
18824
|
if (hit !== void 0) return hit;
|
|
17970
18825
|
}
|
|
17971
|
-
const epoch = _optionalChain([cache, 'optionalAccess',
|
|
18826
|
+
const epoch = _optionalChain([cache, 'optionalAccess', _181 => _181.epoch]);
|
|
17972
18827
|
const res = await this.http.request({ method: "GET", path, operation });
|
|
17973
|
-
_optionalChain([cache, 'optionalAccess',
|
|
18828
|
+
_optionalChain([cache, 'optionalAccess', _182 => _182.set, 'call', _183 => _183(path, res, resource, epoch)]);
|
|
17974
18829
|
return res;
|
|
17975
18830
|
}
|
|
17976
18831
|
/**
|
|
@@ -18010,7 +18865,7 @@ var MetaBase = class extends QueryBase {
|
|
|
18010
18865
|
return value;
|
|
18011
18866
|
});
|
|
18012
18867
|
work.catch((err) => {
|
|
18013
|
-
if (err instanceof AutotaskError && (err.code === "INVALID_RESPONSE" || _optionalChain([err, 'access',
|
|
18868
|
+
if (err instanceof AutotaskError && (err.code === "INVALID_RESPONSE" || _optionalChain([err, 'access', _184 => _184.details, 'optionalAccess', _185 => _185.deterministic]) === true)) {
|
|
18014
18869
|
cache.invalidate(key);
|
|
18015
18870
|
}
|
|
18016
18871
|
});
|
|
@@ -18040,7 +18895,7 @@ var MetaBase = class extends QueryBase {
|
|
|
18040
18895
|
path: `${this.resourcePath}/${numeric}`,
|
|
18041
18896
|
operation: `${this.config.key}.get`,
|
|
18042
18897
|
skipResponseRedaction: true,
|
|
18043
|
-
maxRetries: _optionalChain([readOpts, 'optionalAccess',
|
|
18898
|
+
maxRetries: _optionalChain([readOpts, 'optionalAccess', _186 => _186.maxRetries])
|
|
18044
18899
|
});
|
|
18045
18900
|
return unwrapItem(res, numeric, `${this.config.key}.get`, this.entityName);
|
|
18046
18901
|
}
|
|
@@ -18059,7 +18914,7 @@ var MetaBase = class extends QueryBase {
|
|
|
18059
18914
|
path: this.scopedItemPath(parentId, numeric),
|
|
18060
18915
|
operation: `${this.config.key}.get`,
|
|
18061
18916
|
skipResponseRedaction: true,
|
|
18062
|
-
maxRetries: _optionalChain([readOpts, 'optionalAccess',
|
|
18917
|
+
maxRetries: _optionalChain([readOpts, 'optionalAccess', _187 => _187.maxRetries])
|
|
18063
18918
|
});
|
|
18064
18919
|
return unwrapItem(res, numeric, `${this.config.key}.get`, this.entityName);
|
|
18065
18920
|
}
|
|
@@ -18268,12 +19123,12 @@ var MetaBase = class extends QueryBase {
|
|
|
18268
19123
|
return null;
|
|
18269
19124
|
}
|
|
18270
19125
|
}
|
|
18271
|
-
const epoch = _optionalChain([cache, 'optionalAccess',
|
|
19126
|
+
const epoch = _optionalChain([cache, 'optionalAccess', _188 => _188.epoch]);
|
|
18272
19127
|
try {
|
|
18273
19128
|
return await this.fetchRecordRaw(entityPath, referenceId);
|
|
18274
19129
|
} catch (err) {
|
|
18275
19130
|
if (err instanceof NotFoundError) {
|
|
18276
|
-
_optionalChain([cache, 'optionalAccess',
|
|
19131
|
+
_optionalChain([cache, 'optionalAccess', _189 => _189.set, 'call', _190 => _190(absentKey, CONTEXT_ABSENT_MARKER, RESOURCE_KEY_BY_PATH[entityPath], epoch)]);
|
|
18277
19132
|
return null;
|
|
18278
19133
|
}
|
|
18279
19134
|
throw err;
|
|
@@ -18390,7 +19245,7 @@ var MetaBase = class extends QueryBase {
|
|
|
18390
19245
|
missDetail(operator, fields) {
|
|
18391
19246
|
const key = this.config.key;
|
|
18392
19247
|
const probe = fields.map((field) => ({ field, op: operator, value: "" }));
|
|
18393
|
-
const blind = blindStampFor(_optionalChain([BLIND_SURFACE_STAMPS, 'access',
|
|
19248
|
+
const blind = blindStampFor(_optionalChain([BLIND_SURFACE_STAMPS, 'access', _191 => _191[key], 'optionalAccess', _192 => _192.query]), probe);
|
|
18394
19249
|
const next = [];
|
|
18395
19250
|
if (blind !== void 0) {
|
|
18396
19251
|
next.push(`This surface is blind to records the API user does not own, so a miss is not proof of absence: ${blind.authority} returns the record when the id is known.`);
|
|
@@ -19049,7 +19904,7 @@ var MutationBase = class extends MetaBase {
|
|
|
19049
19904
|
current = parentId === void 0 ? await this.getGlobal(id, true) : this.config.attachmentGet ? await this.getScopedModel(parentId, id, true) : await this.getScopedRaw(parentId, id, true);
|
|
19050
19905
|
} catch (err) {
|
|
19051
19906
|
if (err instanceof NotFoundError) {
|
|
19052
|
-
const updateReason = _optionalChain([EMPTY_REASON_STAMPS, 'access',
|
|
19907
|
+
const updateReason = _optionalChain([EMPTY_REASON_STAMPS, 'access', _193 => _193[this.config.key], 'optionalAccess', _194 => _194.update]);
|
|
19053
19908
|
checks.push({
|
|
19054
19909
|
name: "current-record-exists",
|
|
19055
19910
|
ok: false,
|
|
@@ -19220,7 +20075,7 @@ function readIncludeNames(record, includeFields) {
|
|
|
19220
20075
|
function resolveAuthority(record, live) {
|
|
19221
20076
|
if (live !== null) return { known: live, authority: "the tenant's live entity field metadata" };
|
|
19222
20077
|
const vendored = MODEL_FIELD_SETS[record.resource];
|
|
19223
|
-
const liveOnlyExempt = Array.isArray(_optionalChain([record, 'access',
|
|
20078
|
+
const liveOnlyExempt = Array.isArray(_optionalChain([record, 'access', _195 => _195.metadata, 'optionalAccess', _196 => _196.liveOnlyFields])) ? record.metadata.liveOnlyFields : [];
|
|
19224
20079
|
if (vendored === void 0) return void 0;
|
|
19225
20080
|
return {
|
|
19226
20081
|
known: [...vendored, ...liveOnlyExempt],
|
|
@@ -19446,4 +20301,10 @@ async function validateQueryFieldNames(record, holder, args) {
|
|
|
19446
20301
|
|
|
19447
20302
|
|
|
19448
20303
|
|
|
19449
|
-
|
|
20304
|
+
|
|
20305
|
+
|
|
20306
|
+
|
|
20307
|
+
|
|
20308
|
+
|
|
20309
|
+
|
|
20310
|
+
exports.AUTH_HEADERS = AUTH_HEADERS; exports.buildAuthHeaders = buildAuthHeaders; exports.withAuthHeaders = withAuthHeaders; exports.AutotaskError = AutotaskError; exports.AutotaskConfigError = AutotaskConfigError; exports.isAutotaskError = isAutotaskError; exports.AutotaskNetworkError = AutotaskNetworkError; exports.AutotaskTimeoutError = AutotaskTimeoutError; exports.AutotaskAbortError = AutotaskAbortError; exports.ResponseRejectedError = ResponseRejectedError; exports.BadRequestError = BadRequestError; exports.UnauthorizedError = UnauthorizedError; exports.ForbiddenError = ForbiddenError; exports.NotFoundError = NotFoundError; exports.ConflictError = ConflictError; exports.UnprocessableEntityError = UnprocessableEntityError; exports.RateLimitError = RateLimitError; exports.ServerError = ServerError; exports.UnexpectedContentTypeError = UnexpectedContentTypeError; exports.EmptyResponseError = EmptyResponseError; exports.CircuitBreakerError = CircuitBreakerError; exports.HostPolicyDeniedError = HostPolicyDeniedError; exports.ResolutionError = ResolutionError; exports.PaginationLimitError = PaginationLimitError; exports.QueryTooLongError = QueryTooLongError; exports.parseVendorErrors = parseVendorErrors; exports.isDeterministicVendor500 = isDeterministicVendor500; exports.formatVendorDetail = formatVendorDetail; exports.NoopLogger = NoopLogger; exports.REDACTED = REDACTED; exports.CREDENTIAL_HEADER_NAMES = CREDENTIAL_HEADER_NAMES; exports.isCredentialHeaderName = isCredentialHeaderName; exports.redactRecord = redactRecord; exports.SECRET_RESPONSE_FIELDS = SECRET_RESPONSE_FIELDS; exports.PERSONAL_RESPONSE_FIELDS = PERSONAL_RESPONSE_FIELDS; exports.CONFIDENTIAL_RESPONSE_FIELDS = CONFIDENTIAL_RESPONSE_FIELDS; exports.isRedactedFieldName = isRedactedFieldName; exports.redactResponseBody = redactResponseBody; exports.CREDENTIAL_SHAPE_POINTER = CREDENTIAL_SHAPE_POINTER; exports.mergeDetails = mergeDetails; exports.errorFromStatus = errorFromStatus; exports.StaleObjectError = StaleObjectError; exports.ConfirmationRequiredError = ConfirmationRequiredError; exports.DeleteBoundaryError = DeleteBoundaryError; exports.MarkerUnsafeIdError = MarkerUnsafeIdError; exports.RecoveryTruncatedError = RecoveryTruncatedError; exports.MoveRefusedError = MoveRefusedError; exports.READ_CACHE_MAX_ENTRIES = READ_CACHE_MAX_ENTRIES; exports.ReadCache = ReadCache; exports.ZONE_CATALOG = ZONE_CATALOG; exports.ZONES = ZONES; exports.DEFAULT_ZONE = DEFAULT_ZONE; exports.zoneUrl = zoneUrl; exports.resolveBaseUrl = resolveBaseUrl; exports.AGENT_PROFILE = AGENT_PROFILE; exports.DEFAULT_PAGE_SIZE = DEFAULT_PAGE_SIZE; exports.MAX_PAGE_SIZE = MAX_PAGE_SIZE; exports.DEFAULT_TIMEOUT_MS = DEFAULT_TIMEOUT_MS; exports.DEFAULT_MAX_RETRIES = DEFAULT_MAX_RETRIES; exports.DEFAULT_MAINTENANCE_MAX_WAIT_MS = DEFAULT_MAINTENANCE_MAX_WAIT_MS; exports.DEFAULT_MAINTENANCE_POLL_MS = DEFAULT_MAINTENANCE_POLL_MS; exports.MAINTENANCE_WINDOW_MAX_MS = MAINTENANCE_WINDOW_MAX_MS; exports.DEFAULT_MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT; exports.DEFAULT_MAX_RESPONSE_BYTES = DEFAULT_MAX_RESPONSE_BYTES; exports.DEFAULT_MAX_SCAN_RECORDS = DEFAULT_MAX_SCAN_RECORDS; exports.DEFAULT_MAX_SCAN_PAGES = DEFAULT_MAX_SCAN_PAGES; exports.DEFAULT_READ_CACHE_TTL_MS = DEFAULT_READ_CACHE_TTL_MS; exports.DEFAULT_FIELD_CACHE_TTL_MS = DEFAULT_FIELD_CACHE_TTL_MS; exports.DEFAULT_RESOURCE_NAME_CACHE_TTL_MS = DEFAULT_RESOURCE_NAME_CACHE_TTL_MS; exports.hasSurroundingQuotes = hasSurroundingQuotes; exports.credentialShapeProblem = credentialShapeProblem; exports.CREDENTIAL_ENV_LOAD_ACTION = CREDENTIAL_ENV_LOAD_ACTION; exports.MIN_PREFIX_SUMMARY_LENGTH = MIN_PREFIX_SUMMARY_LENGTH; exports.credentialValueSummary = credentialValueSummary; exports.FIELD_CACHE_KINDS = FIELD_CACHE_KINDS; exports.DEFAULT_CIRCUIT_BREAKER_WINDOW_MS = DEFAULT_CIRCUIT_BREAKER_WINDOW_MS; exports.DEFAULT_CIRCUIT_BREAKER_FAILURE_THRESHOLD = DEFAULT_CIRCUIT_BREAKER_FAILURE_THRESHOLD; exports.DEFAULT_CIRCUIT_BREAKER_OPEN_TIMEOUT_MS = DEFAULT_CIRCUIT_BREAKER_OPEN_TIMEOUT_MS; exports.DEFAULT_CIRCUIT_BREAKER_SUCCESSES_TO_CLOSE = DEFAULT_CIRCUIT_BREAKER_SUCCESSES_TO_CLOSE; exports.DEFAULT_CIRCUIT_BREAKER_MAX_ENTRIES = DEFAULT_CIRCUIT_BREAKER_MAX_ENTRIES; exports.InMemoryCircuitBreakerStore = InMemoryCircuitBreakerStore; exports.defaultCircuitBreakerStore = defaultCircuitBreakerStore; exports.resetDefaultCircuitBreakerStore = resetDefaultCircuitBreakerStore; exports.buildBreakerKey = buildBreakerKey; exports.isBreakerFailure = isBreakerFailure; exports.DEFAULT_COOLDOWN_MAX_MS = DEFAULT_COOLDOWN_MAX_MS; exports.DEFAULT_COOLDOWN_DEFAULT_MS = DEFAULT_COOLDOWN_DEFAULT_MS; exports.DEFAULT_COOLDOWN_MAX_ENTRIES = DEFAULT_COOLDOWN_MAX_ENTRIES; exports.InMemoryCooldownStore = InMemoryCooldownStore; exports.defaultCooldownStore = defaultCooldownStore; exports.resetDefaultCooldownStore = resetDefaultCooldownStore; exports.buildTenantKey = buildTenantKey; exports.cooldownDurationMs = cooldownDurationMs; exports.resolveCredentials = resolveCredentials; exports.buildReadCache = buildReadCache; exports.resolveConfig = resolveConfig; exports.IDEMPOTENT_METHODS = IDEMPOTENT_METHODS; exports.isRecord = isRecord2; exports.assertRecord = assertRecord; exports.deepMergeParams = deepMergeParams; exports.isIdentifierCandidate = isIdentifierCandidate; exports.parseIdentifier = parseIdentifier; exports.flattenUdfs = flattenUdfs; exports.newCorrelationId = newCorrelationId; exports.redactAuditBody = redactAuditBody; exports.camelKey = camelKey; exports.FILTER_OPERATORS = FILTER_OPERATORS; exports.GROUPING_OPERATORS = GROUPING_OPERATORS; exports.MAX_OR_CONDITIONS = MAX_OR_CONDITIONS; exports.MAX_UDF_PER_QUERY = MAX_UDF_PER_QUERY; exports.MAX_QUERY_LENGTH = MAX_QUERY_LENGTH; exports.MAX_GET_LENGTH = MAX_GET_LENGTH; exports.MAX_FIELD_LENGTH = MAX_FIELD_LENGTH; exports.isFilterOperator = isFilterOperator; exports.serializeFilter = serializeFilter; exports.validateFilter = validateFilter; exports.buildFilter = buildFilter; exports.normalizedConditions = normalizedConditions; exports.buildUrl = buildUrl; exports.cursorToPath = cursorToPath; exports.buildQueryBody = buildQueryBody; exports.buildQueryRequest = buildQueryRequest; exports.runWithSignal = runWithSignal; exports.RELATIONSHIP_ZONE = RELATIONSHIP_ZONE; exports.RELATIONSHIP_MAP = RELATIONSHIP_MAP; exports.BLIND_SURFACE_STAMPS = BLIND_SURFACE_STAMPS; exports.DELETE_BOUNDARY_NOTES = DELETE_BOUNDARY_NOTES; exports.MARKER_FIELDS = MARKER_FIELDS; exports.EMPTY_REASON_STAMPS = EMPTY_REASON_STAMPS; exports.BLIND_SURFACE_INVENTORY = BLIND_SURFACE_INVENTORY; exports.REACHABILITY_PROBE_DEFAULTS = REACHABILITY_PROBE_DEFAULTS; exports.CREATE_GUIDANCE = CREATE_GUIDANCE; exports.UNTRUSTED_FIELDS_BY_RESOURCE = UNTRUSTED_FIELDS_BY_RESOURCE; exports.unwrapItems = unwrapItems; exports.unwrapItem = unwrapItem; exports.unwrapQueryCount = unwrapQueryCount; exports.unwrapOperation = unwrapOperation; exports.passthrough = passthrough; exports.HttpClient = HttpClient; exports.BOUNDED_QUERY_MAX_LIMIT = BOUNDED_QUERY_MAX_LIMIT; exports.truncateNoteChars = truncateNoteChars; exports.buildDryRunResult = buildDryRunResult; exports.mergePartialBody = mergePartialBody; exports.blindStampFor = blindStampFor; exports.decodeFileData = decodeFileData; exports.MAX_PAGES = MAX_PAGES; exports.clampPageSize = clampPageSize; exports.totalPagesFor = totalPagesFor; exports.paginate = paginate; exports.paginateItems = paginateItems; exports.collectAll = collectAll; exports.toArray = toArray; exports.FIELD_PRESETS = FIELD_PRESETS; exports.FIELD_PRESET_NAMES = FIELD_PRESET_NAMES; exports.resolveFieldsPreset = resolveFieldsPreset; exports.BaseResource = BaseResource; exports.MODEL_FIELD_SETS = MODEL_FIELD_SETS; exports.MODEL_DATE_FIELDS = MODEL_DATE_FIELDS; exports.formatUnknownNameList = formatUnknownNameList; exports.validateQueryFieldNames = validateQueryFieldNames; exports.EXPAND_RESOURCE_NAMES_MAX_IDS = EXPAND_RESOURCE_NAMES_MAX_IDS; exports.expandResourceNames = expandResourceNames; exports.ENTITY_TYPE_TO_RESOURCE = ENTITY_TYPE_TO_RESOURCE; exports.resourceForEntityType = resourceForEntityType; exports.isEnumerableResource = isEnumerableResource; exports.WORKFLOW_RESOURCES = WORKFLOW_RESOURCES; exports.MAX_FIELD_CATALOG_WIRE = MAX_FIELD_CATALOG_WIRE; exports.FIELD_CATALOG_HONESTY_NOTE = FIELD_CATALOG_HONESTY_NOTE; exports.fieldCatalog = fieldCatalog; exports.PICKLIST_VALUE_NOT_SERVED_NOTE = PICKLIST_VALUE_NOT_SERVED_NOTE; exports.TICKET_LABEL_FIELDS = TICKET_LABEL_FIELDS; exports.createNamePlan = createNamePlan; exports.addNameSibling = addNameSibling; exports.addLabelSibling = addLabelSibling; exports.resolveCompositeNames = resolveCompositeNames; exports.FETCH_MANY_MAX_ITEMS = FETCH_MANY_MAX_ITEMS; exports.validateFetchManyItems = validateFetchManyItems; exports.fetchMany = fetchMany; exports.FETCH_BY_IDS_MAX_ITEMS = FETCH_BY_IDS_MAX_ITEMS; exports.FETCH_BY_IDS_CHUNK_SIZE = FETCH_BY_IDS_CHUNK_SIZE; exports.fetchByIds = fetchByIds; exports.UI_LINK_ENTITIES = UI_LINK_ENTITIES; exports.buildUiLink = buildUiLink; exports.uiLink = uiLink;
|