@fourier-labs/harbour-contracts 0.73.0 → 0.76.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/README.md +4 -4
- package/contract-release.json +26 -26
- package/dist/gen-ts/app-integrations-declaration.d.ts +15 -1
- package/dist/gen-ts/contract-release.d.ts +6 -6
- package/dist/gen-ts/contract-release.js +6 -6
- package/dist/gen-ts/data-grant-v2.d.ts +5 -5
- package/dist/gen-ts/data-source.d.ts +19 -2
- package/dist/gen-ts/integration-error-details.d.ts +2 -2
- package/dist/gen-ts/integration-execute-input-rules.d.ts +214 -0
- package/dist/gen-ts/integration-execute-input-rules.js +85 -0
- package/dist/gen-ts/integration-execute-request.d.ts +61 -6
- package/dist/gen-ts/integration-execute-result.d.ts +165 -1
- package/dist/gen-ts/integration-operations.d.ts +77 -0
- package/dist/gen-ts/integration-operations.js +99 -0
- package/dist/gen-ts/saas-connection.d.ts +22 -8
- package/gen-ts/app-integrations-declaration.ts +15 -1
- package/gen-ts/contract-release.ts +6 -6
- package/gen-ts/data-grant-v2.ts +15 -4
- package/gen-ts/data-source.ts +19 -2
- package/gen-ts/integration-error-details.ts +3 -2
- package/gen-ts/integration-execute-input-rules.ts +86 -1
- package/gen-ts/integration-execute-request.ts +71 -5
- package/gen-ts/integration-execute-result.ts +165 -1
- package/gen-ts/integration-operations.ts +99 -0
- package/gen-ts/saas-connection.ts +32 -7
- package/package.json +1 -1
- package/schema/app-integrations-declaration.schema.json +233 -2
- package/schema/data-grant-v2.schema.json +4 -4
- package/schema/data-source.schema.json +57 -2
- package/schema/integration-error-details.schema.json +3 -2
- package/schema/integration-execute-request.schema.json +563 -4
- package/schema/integration-execute-result.schema.json +558 -2
- package/schema/saas-connection.schema.json +35 -7
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
3
|
"$id": "https://schemas.harbour.dev/integration-execute-request.schema.json",
|
|
4
4
|
"title": "IntegrationExecuteRequest",
|
|
5
|
-
"description": "Body of POST /_harbour/integrations/execute (app SDK), forwarded unchanged to the governance development and runtime execute routes. Exactly one declared operation against one declared resource. The identity mode is fixed by the operation for every operation but the declared-mode Slack operations (slack.channel.history, slack.message.post, slack.message.update, slack.message.delete; 0.71.0 widened history), and always enforced from an approved grant; any identity/userId/scope field is rejected by additionalProperties. A declared-mode operation runs as the app (for a post: the IT-approved per-app name from the grant, plus a \"Posted by <app> on Isomorph\" footer) or as the signed-in person (no name, no footer) \u2014 the same input either way \u2014 and since 0.55.0 the call names which of the app's approved modes it runs under (`mode`): required when IT approved both modes for the app (MODE_REQUIRED otherwise), optional when it approved one (that one is used), and a named mode without an approved grant is refused (MODE_NOT_GRANTED) rather than served under the other, so approval order never decides what a call does. Per-operation input bounds (0.71.0, ADR 0018): slack.channel.history {limit? 1..100, default 15, cursor?, oldest?, latest?}; slack.message.post {text 1..4000 chars, threadId?, format? plain|mrkdwn} and a required idempotencyKey retained across retries of one explicit Send; slack.message.update {messageId, text, format?}; slack.message.delete {messageId}; slack.dm.send {to 1..8 addresses, text, format?} (app mode only) with a required idempotencyKey; slack.user.lookup {email}; gmail.thread.list {limit? 1..50, default 15, q?, labelIds? default [INBOX], pageToken?}; gmail.thread.read {threadId}; gmail.message.read {messageId}; gmail.attachment.read {messageId, attachmentId}; gmail.message.send {to 1..50 addresses (to+cc+bcc <= 50 in total), cc?, bcc?, subject 1..256 chars, text 1..4000 chars, html? <= 64 KiB, attachments? 1..5 of <= 2 MiB each as base64, replyToMessageId?} and a required idempotencyKey like slack.message.post; warehouse.view.read {columns? 1..32, where? 1..16 filters, groupBy? 1..8 columns, aggregates? 1..16, orderBy? 1..8, limit? 1..1000, default 100} (0.70.0: a plain read names columns, an aggregate read names aggregates and optionally groupBy; the cross-field rules \u2014 exactly one of columns or aggregates, groupBy needs aggregates, a filter value that fits its op, orderBy naming a returned column, every named column approved \u2014 are enforced by governance, not expressible here; ADR 0017). Each operation's then-block is the one statement of its input rules: propertyNames.enum names the fields it accepts, required the ones it needs, and per-field overrides (maximum, default) narrow the shared property. Codegen derives IntegrationExecuteInputRules and validateIntegrationExecuteInput (gen-ts/integration-execute-input-rules.ts, gen-go/integration_execute_input_rules.go) from exactly these blocks, so the governance execute route, the app SDK and the kit's local check refuse the same request with the same message. Transport limits (not expressible here): request <= 16 KiB except a gmail.message.send carrying attachments (governance sizes that route for the attachment bound), total deadline 10 s.",
|
|
5
|
+
"description": "Body of POST /_harbour/integrations/execute (app SDK), forwarded unchanged to the governance development and runtime execute routes. Exactly one declared operation against one declared resource. The identity mode is fixed by the operation for every operation but the declared-mode Slack operations (slack.channel.history, slack.message.post, slack.message.update, slack.message.delete; 0.71.0 widened history), and always enforced from an approved grant; any identity/userId/scope field is rejected by additionalProperties. A declared-mode operation runs as the app (for a post: the IT-approved per-app name from the grant, plus a \"Posted by <app> on Isomorph\" footer) or as the signed-in person (no name, no footer) \u2014 the same input either way \u2014 and since 0.55.0 the call names which of the app's approved modes it runs under (`mode`): required when IT approved both modes for the app (MODE_REQUIRED otherwise), optional when it approved one (that one is used), and a named mode without an approved grant is refused (MODE_NOT_GRANTED) rather than served under the other, so approval order never decides what a call does. Per-operation input bounds (0.71.0, ADR 0018): slack.channel.history {limit? 1..100, default 15, cursor?, oldest?, latest?}; slack.message.post {text 1..4000 chars, threadId?, format? plain|mrkdwn} and a required idempotencyKey retained across retries of one explicit Send; slack.message.update {messageId, text, format?}; slack.message.delete {messageId}; slack.dm.send {to 1..8 addresses, text, format?} (app mode only) with a required idempotencyKey; slack.user.lookup {email}; gmail.thread.list {limit? 1..50, default 15, q?, labelIds? default [INBOX], pageToken?}; gmail.thread.read {threadId}; gmail.message.read {messageId}; gmail.attachment.read {messageId, attachmentId}; gmail.message.send {to 1..50 addresses (to+cc+bcc <= 50 in total), cc?, bcc?, subject 1..256 chars, text 1..4000 chars, html? <= 64 KiB, attachments? 1..5 of <= 2 MiB each as base64, replyToMessageId?} and a required idempotencyKey like slack.message.post; warehouse.view.read {columns? 1..32, where? 1..16 filters, groupBy? 1..8 columns, aggregates? 1..16, orderBy? 1..8, limit? 1..1000, default 100} (0.70.0: a plain read names columns, an aggregate read names aggregates and optionally groupBy; the cross-field rules \u2014 exactly one of columns or aggregates, groupBy needs aggregates, a filter value that fits its op, orderBy naming a returned column, every named column approved \u2014 are enforced by governance, not expressible here; ADR 0017). Basecamp (0.76.0, ADR 0022; every id a string of 1..20 digits, every operation user mode): basecamp.project.list {pageToken?, projectStatus? active|archived} on the fixed `account` alias; on a project alias basecamp.todolist.list {pageToken?}; basecamp.todo.list {todolistId, completed?, pageToken?}; basecamp.todo.create {todolistId, content 1..1000 (the to-do title), description? <= 16384, contentFormat? plain|html, dueOn? YYYY-MM-DD, assigneeIds? 1..20, notify?} with a required idempotencyKey; basecamp.todo.complete {todoId} (idempotent at Basecamp, so no key); basecamp.message.list {pageToken?}; basecamp.message.post {subject 1..256, content 1..65536, contentFormat?} with a required idempotencyKey; basecamp.comment.list {recordingId, pageToken?}; basecamp.comment.post {recordingId, content 1..16384, contentFormat?} with a required idempotencyKey; basecamp.campfire.post {content 1..4000, contentFormat?} with a required idempotencyKey; basecamp.people.list {pageToken?}. `pageToken` is the previous page's `nextPageToken` (a Basecamp page number as digits). Each operation's then-block is the one statement of its input rules: propertyNames.enum names the fields it accepts, required the ones it needs, and per-field overrides (maximum, default) narrow the shared property. Codegen derives IntegrationExecuteInputRules and validateIntegrationExecuteInput (gen-ts/integration-execute-input-rules.ts, gen-go/integration_execute_input_rules.go) from exactly these blocks, so the governance execute route, the app SDK and the kit's local check refuse the same request with the same message. Transport limits (not expressible here): request <= 16 KiB except a gmail.message.send carrying attachments (governance sizes that route for the attachment bound) and a basecamp.message.post (its 64 KiB body; governance allows 80 KiB there), total deadline 10 s.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"additionalProperties": false,
|
|
8
8
|
"required": [
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
"type": "string",
|
|
100
100
|
"minLength": 1,
|
|
101
101
|
"maxLength": 256,
|
|
102
|
-
"description": "gmail.thread.list (0.71.0): the `nextPageToken` of the previous page; absent reads the first page."
|
|
102
|
+
"description": "gmail.thread.list (0.71.0) and every basecamp.*.list operation (0.76.0): the `nextPageToken` of the previous page; absent reads the first page."
|
|
103
103
|
},
|
|
104
104
|
"email": {
|
|
105
105
|
"$ref": "#/definitions/EmailAddress",
|
|
@@ -121,7 +121,7 @@
|
|
|
121
121
|
"type": "string",
|
|
122
122
|
"minLength": 1,
|
|
123
123
|
"maxLength": 256,
|
|
124
|
-
"description": "gmail.message.send: one-line subject (no line breaks)."
|
|
124
|
+
"description": "gmail.message.send: one-line subject (no line breaks). basecamp.message.post (0.76.0): the message's title."
|
|
125
125
|
},
|
|
126
126
|
"replyToMessageId": {
|
|
127
127
|
"type": "string",
|
|
@@ -143,6 +143,61 @@
|
|
|
143
143
|
},
|
|
144
144
|
"description": "gmail.message.send (0.71.0): files to attach, 1..5, each at most 2 MiB (2,796,203 base64 characters)."
|
|
145
145
|
},
|
|
146
|
+
"todolistId": {
|
|
147
|
+
"$ref": "app-integrations-declaration.schema.json#/definitions/BasecampId",
|
|
148
|
+
"description": "basecamp.todo.list / basecamp.todo.create (0.76.0): the to-do list, as a basecamp.todolist.list result named it."
|
|
149
|
+
},
|
|
150
|
+
"todoId": {
|
|
151
|
+
"$ref": "app-integrations-declaration.schema.json#/definitions/BasecampId",
|
|
152
|
+
"description": "basecamp.todo.complete (0.76.0): the to-do, as a basecamp.todo.list or basecamp.todo.create result named it."
|
|
153
|
+
},
|
|
154
|
+
"recordingId": {
|
|
155
|
+
"$ref": "app-integrations-declaration.schema.json#/definitions/BasecampId",
|
|
156
|
+
"description": "basecamp.comment.list / basecamp.comment.post (0.76.0): the Basecamp recording commented on — a message, a to-do or any other id a basecamp.* result named."
|
|
157
|
+
},
|
|
158
|
+
"content": {
|
|
159
|
+
"type": "string",
|
|
160
|
+
"minLength": 1,
|
|
161
|
+
"maxLength": 65536,
|
|
162
|
+
"description": "basecamp.todo.create (0.76.0): the to-do's title, 1..1000 characters. basecamp.message.post: the body, at most 64 KiB; basecamp.comment.post: at most 16 KiB; basecamp.campfire.post: at most 4000 characters. Plain text unless `contentFormat` is html."
|
|
163
|
+
},
|
|
164
|
+
"contentFormat": {
|
|
165
|
+
"$ref": "#/definitions/BasecampContentFormat",
|
|
166
|
+
"description": "basecamp.todo.create / basecamp.message.post / basecamp.comment.post / basecamp.campfire.post (0.76.0): how `content` (and a to-do's `description`) is read; plain when absent."
|
|
167
|
+
},
|
|
168
|
+
"description": {
|
|
169
|
+
"type": "string",
|
|
170
|
+
"minLength": 1,
|
|
171
|
+
"maxLength": 16384,
|
|
172
|
+
"description": "basecamp.todo.create (0.76.0): the to-do's notes, at most 16 KiB, read the way `contentFormat` says."
|
|
173
|
+
},
|
|
174
|
+
"dueOn": {
|
|
175
|
+
"type": "string",
|
|
176
|
+
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
|
|
177
|
+
"description": "basecamp.todo.create (0.76.0): the due date as YYYY-MM-DD; absent leaves the to-do undated."
|
|
178
|
+
},
|
|
179
|
+
"assigneeIds": {
|
|
180
|
+
"type": "array",
|
|
181
|
+
"minItems": 1,
|
|
182
|
+
"maxItems": 20,
|
|
183
|
+
"uniqueItems": true,
|
|
184
|
+
"items": {
|
|
185
|
+
"$ref": "app-integrations-declaration.schema.json#/definitions/BasecampId"
|
|
186
|
+
},
|
|
187
|
+
"description": "basecamp.todo.create (0.76.0): the people assigned, 1..20, by the ids a basecamp.people.list result named."
|
|
188
|
+
},
|
|
189
|
+
"notify": {
|
|
190
|
+
"type": "boolean",
|
|
191
|
+
"description": "basecamp.todo.create (0.76.0): whether Basecamp notifies the assignees; false when absent."
|
|
192
|
+
},
|
|
193
|
+
"completed": {
|
|
194
|
+
"type": "boolean",
|
|
195
|
+
"description": "basecamp.todo.list (0.76.0): true lists the completed to-dos instead of the open ones; absent lists the open ones."
|
|
196
|
+
},
|
|
197
|
+
"projectStatus": {
|
|
198
|
+
"$ref": "#/definitions/BasecampProjectStatus",
|
|
199
|
+
"description": "basecamp.project.list (0.76.0): which projects to list; active when absent."
|
|
200
|
+
},
|
|
146
201
|
"columns": {
|
|
147
202
|
"type": "array",
|
|
148
203
|
"minItems": 1,
|
|
@@ -239,11 +294,23 @@
|
|
|
239
294
|
"idempotencyKey": {
|
|
240
295
|
"type": "string",
|
|
241
296
|
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
|
|
242
|
-
"description": "UUID of one explicit Send action; required for slack.message.post
|
|
297
|
+
"description": "UUID of one explicit Send action; required for the sends (slack.message.post, slack.dm.send, gmail.message.send) and the receipted Basecamp writes (basecamp.todo.create, basecamp.message.post, basecamp.comment.post, basecamp.campfire.post; 0.76.0), refused everywhere else. The same key with the same payload and subject returns the recorded outcome for seven days."
|
|
243
298
|
},
|
|
244
299
|
"mode": {
|
|
245
300
|
"$ref": "app-integrations-declaration.schema.json#/definitions/IntegrationIdentityMode",
|
|
246
301
|
"description": "The declared-mode Slack operations only (slack.message.post since 0.55.0; slack.channel.history, slack.message.update and slack.message.delete since 0.71.0): which of the app's IT-approved modes this call runs under \u2014 app (the company's Slack app; a post goes out under the grant's per-app name and the footer) or user (the signed-in person, after their consent; no name, no footer). Required when the app holds approved grants for both modes (else MODE_REQUIRED); may be omitted when it holds one, which is then used. A named mode without an approved grant is refused with MODE_NOT_GRANTED; governance never falls back to the other mode. Every other operation's mode is fixed, so the field is refused there."
|
|
302
|
+
},
|
|
303
|
+
"sampleRows": {
|
|
304
|
+
"type": "array",
|
|
305
|
+
"maxItems": 50,
|
|
306
|
+
"items": {
|
|
307
|
+
"type": "object",
|
|
308
|
+
"additionalProperties": {
|
|
309
|
+
"type": ["string", "number", "boolean", "null"]
|
|
310
|
+
},
|
|
311
|
+
"description": "One sample row keyed by column name; each value is a scalar that governance parses by the column's recorded type."
|
|
312
|
+
},
|
|
313
|
+
"description": "Development only (0.74.0). Rows the kit dev runtime attaches for the resource being read, from the sample-row file the agent wrote into the app's .isomorph/ folder. Governance serves them for a development warehouse.view.read when the source has no development copy (data-source.environments.development): it parses each value by the resource's recorded column type and refuses a value that does not parse, naming the column and the row. The field is refused with SAMPLE_ROWS_NOT_ALLOWED on any route but the development one, so a preview or production read never carries made-up data. Not part of the per-operation input rules; the dev runtime adds it beside the app's request."
|
|
247
314
|
}
|
|
248
315
|
},
|
|
249
316
|
"allOf": [
|
|
@@ -642,6 +709,360 @@
|
|
|
642
709
|
}
|
|
643
710
|
}
|
|
644
711
|
},
|
|
712
|
+
{
|
|
713
|
+
"if": {
|
|
714
|
+
"properties": {
|
|
715
|
+
"operation": {
|
|
716
|
+
"const": "basecamp.project.list"
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
},
|
|
720
|
+
"then": {
|
|
721
|
+
"x-read-only": true,
|
|
722
|
+
"x-primary-identity": "user",
|
|
723
|
+
"not": {
|
|
724
|
+
"required": [
|
|
725
|
+
"idempotencyKey"
|
|
726
|
+
]
|
|
727
|
+
},
|
|
728
|
+
"properties": {
|
|
729
|
+
"mode": false,
|
|
730
|
+
"input": {
|
|
731
|
+
"propertyNames": {
|
|
732
|
+
"enum": [
|
|
733
|
+
"pageToken",
|
|
734
|
+
"projectStatus"
|
|
735
|
+
]
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
},
|
|
741
|
+
{
|
|
742
|
+
"if": {
|
|
743
|
+
"properties": {
|
|
744
|
+
"operation": {
|
|
745
|
+
"const": "basecamp.todolist.list"
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
},
|
|
749
|
+
"then": {
|
|
750
|
+
"x-read-only": true,
|
|
751
|
+
"x-primary-identity": "user",
|
|
752
|
+
"not": {
|
|
753
|
+
"required": [
|
|
754
|
+
"idempotencyKey"
|
|
755
|
+
]
|
|
756
|
+
},
|
|
757
|
+
"properties": {
|
|
758
|
+
"mode": false,
|
|
759
|
+
"input": {
|
|
760
|
+
"propertyNames": {
|
|
761
|
+
"enum": [
|
|
762
|
+
"pageToken"
|
|
763
|
+
]
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
"if": {
|
|
771
|
+
"properties": {
|
|
772
|
+
"operation": {
|
|
773
|
+
"const": "basecamp.todo.list"
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
},
|
|
777
|
+
"then": {
|
|
778
|
+
"x-read-only": true,
|
|
779
|
+
"x-primary-identity": "user",
|
|
780
|
+
"not": {
|
|
781
|
+
"required": [
|
|
782
|
+
"idempotencyKey"
|
|
783
|
+
]
|
|
784
|
+
},
|
|
785
|
+
"properties": {
|
|
786
|
+
"mode": false,
|
|
787
|
+
"input": {
|
|
788
|
+
"propertyNames": {
|
|
789
|
+
"enum": [
|
|
790
|
+
"todolistId",
|
|
791
|
+
"completed",
|
|
792
|
+
"pageToken"
|
|
793
|
+
]
|
|
794
|
+
},
|
|
795
|
+
"required": [
|
|
796
|
+
"todolistId"
|
|
797
|
+
]
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
},
|
|
802
|
+
{
|
|
803
|
+
"if": {
|
|
804
|
+
"properties": {
|
|
805
|
+
"operation": {
|
|
806
|
+
"const": "basecamp.todo.create"
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
},
|
|
810
|
+
"then": {
|
|
811
|
+
"x-read-only": false,
|
|
812
|
+
"x-primary-identity": "user",
|
|
813
|
+
"required": [
|
|
814
|
+
"idempotencyKey"
|
|
815
|
+
],
|
|
816
|
+
"properties": {
|
|
817
|
+
"mode": false,
|
|
818
|
+
"input": {
|
|
819
|
+
"propertyNames": {
|
|
820
|
+
"enum": [
|
|
821
|
+
"todolistId",
|
|
822
|
+
"content",
|
|
823
|
+
"description",
|
|
824
|
+
"contentFormat",
|
|
825
|
+
"dueOn",
|
|
826
|
+
"assigneeIds",
|
|
827
|
+
"notify"
|
|
828
|
+
]
|
|
829
|
+
},
|
|
830
|
+
"required": [
|
|
831
|
+
"todolistId",
|
|
832
|
+
"content"
|
|
833
|
+
],
|
|
834
|
+
"properties": {
|
|
835
|
+
"content": {
|
|
836
|
+
"maxLength": 1000
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
},
|
|
843
|
+
{
|
|
844
|
+
"if": {
|
|
845
|
+
"properties": {
|
|
846
|
+
"operation": {
|
|
847
|
+
"const": "basecamp.todo.complete"
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
},
|
|
851
|
+
"then": {
|
|
852
|
+
"x-read-only": false,
|
|
853
|
+
"x-primary-identity": "user",
|
|
854
|
+
"not": {
|
|
855
|
+
"required": [
|
|
856
|
+
"idempotencyKey"
|
|
857
|
+
]
|
|
858
|
+
},
|
|
859
|
+
"properties": {
|
|
860
|
+
"mode": false,
|
|
861
|
+
"input": {
|
|
862
|
+
"propertyNames": {
|
|
863
|
+
"enum": [
|
|
864
|
+
"todoId"
|
|
865
|
+
]
|
|
866
|
+
},
|
|
867
|
+
"required": [
|
|
868
|
+
"todoId"
|
|
869
|
+
]
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
},
|
|
874
|
+
{
|
|
875
|
+
"if": {
|
|
876
|
+
"properties": {
|
|
877
|
+
"operation": {
|
|
878
|
+
"const": "basecamp.message.list"
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
},
|
|
882
|
+
"then": {
|
|
883
|
+
"x-read-only": true,
|
|
884
|
+
"x-primary-identity": "user",
|
|
885
|
+
"not": {
|
|
886
|
+
"required": [
|
|
887
|
+
"idempotencyKey"
|
|
888
|
+
]
|
|
889
|
+
},
|
|
890
|
+
"properties": {
|
|
891
|
+
"mode": false,
|
|
892
|
+
"input": {
|
|
893
|
+
"propertyNames": {
|
|
894
|
+
"enum": [
|
|
895
|
+
"pageToken"
|
|
896
|
+
]
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
},
|
|
902
|
+
{
|
|
903
|
+
"if": {
|
|
904
|
+
"properties": {
|
|
905
|
+
"operation": {
|
|
906
|
+
"const": "basecamp.message.post"
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
},
|
|
910
|
+
"then": {
|
|
911
|
+
"x-read-only": false,
|
|
912
|
+
"x-primary-identity": "user",
|
|
913
|
+
"required": [
|
|
914
|
+
"idempotencyKey"
|
|
915
|
+
],
|
|
916
|
+
"properties": {
|
|
917
|
+
"mode": false,
|
|
918
|
+
"input": {
|
|
919
|
+
"propertyNames": {
|
|
920
|
+
"enum": [
|
|
921
|
+
"subject",
|
|
922
|
+
"content",
|
|
923
|
+
"contentFormat"
|
|
924
|
+
]
|
|
925
|
+
},
|
|
926
|
+
"required": [
|
|
927
|
+
"subject",
|
|
928
|
+
"content"
|
|
929
|
+
]
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
},
|
|
934
|
+
{
|
|
935
|
+
"if": {
|
|
936
|
+
"properties": {
|
|
937
|
+
"operation": {
|
|
938
|
+
"const": "basecamp.comment.list"
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
},
|
|
942
|
+
"then": {
|
|
943
|
+
"x-read-only": true,
|
|
944
|
+
"x-primary-identity": "user",
|
|
945
|
+
"not": {
|
|
946
|
+
"required": [
|
|
947
|
+
"idempotencyKey"
|
|
948
|
+
]
|
|
949
|
+
},
|
|
950
|
+
"properties": {
|
|
951
|
+
"mode": false,
|
|
952
|
+
"input": {
|
|
953
|
+
"propertyNames": {
|
|
954
|
+
"enum": [
|
|
955
|
+
"recordingId",
|
|
956
|
+
"pageToken"
|
|
957
|
+
]
|
|
958
|
+
},
|
|
959
|
+
"required": [
|
|
960
|
+
"recordingId"
|
|
961
|
+
]
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
},
|
|
966
|
+
{
|
|
967
|
+
"if": {
|
|
968
|
+
"properties": {
|
|
969
|
+
"operation": {
|
|
970
|
+
"const": "basecamp.comment.post"
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
},
|
|
974
|
+
"then": {
|
|
975
|
+
"x-read-only": false,
|
|
976
|
+
"x-primary-identity": "user",
|
|
977
|
+
"required": [
|
|
978
|
+
"idempotencyKey"
|
|
979
|
+
],
|
|
980
|
+
"properties": {
|
|
981
|
+
"mode": false,
|
|
982
|
+
"input": {
|
|
983
|
+
"propertyNames": {
|
|
984
|
+
"enum": [
|
|
985
|
+
"recordingId",
|
|
986
|
+
"content",
|
|
987
|
+
"contentFormat"
|
|
988
|
+
]
|
|
989
|
+
},
|
|
990
|
+
"required": [
|
|
991
|
+
"recordingId",
|
|
992
|
+
"content"
|
|
993
|
+
],
|
|
994
|
+
"properties": {
|
|
995
|
+
"content": {
|
|
996
|
+
"maxLength": 16384
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
},
|
|
1003
|
+
{
|
|
1004
|
+
"if": {
|
|
1005
|
+
"properties": {
|
|
1006
|
+
"operation": {
|
|
1007
|
+
"const": "basecamp.campfire.post"
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
},
|
|
1011
|
+
"then": {
|
|
1012
|
+
"x-read-only": false,
|
|
1013
|
+
"x-primary-identity": "user",
|
|
1014
|
+
"required": [
|
|
1015
|
+
"idempotencyKey"
|
|
1016
|
+
],
|
|
1017
|
+
"properties": {
|
|
1018
|
+
"mode": false,
|
|
1019
|
+
"input": {
|
|
1020
|
+
"propertyNames": {
|
|
1021
|
+
"enum": [
|
|
1022
|
+
"content",
|
|
1023
|
+
"contentFormat"
|
|
1024
|
+
]
|
|
1025
|
+
},
|
|
1026
|
+
"required": [
|
|
1027
|
+
"content"
|
|
1028
|
+
],
|
|
1029
|
+
"properties": {
|
|
1030
|
+
"content": {
|
|
1031
|
+
"maxLength": 4000
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
},
|
|
1038
|
+
{
|
|
1039
|
+
"if": {
|
|
1040
|
+
"properties": {
|
|
1041
|
+
"operation": {
|
|
1042
|
+
"const": "basecamp.people.list"
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
},
|
|
1046
|
+
"then": {
|
|
1047
|
+
"x-read-only": true,
|
|
1048
|
+
"x-primary-identity": "user",
|
|
1049
|
+
"not": {
|
|
1050
|
+
"required": [
|
|
1051
|
+
"idempotencyKey"
|
|
1052
|
+
]
|
|
1053
|
+
},
|
|
1054
|
+
"properties": {
|
|
1055
|
+
"mode": false,
|
|
1056
|
+
"input": {
|
|
1057
|
+
"propertyNames": {
|
|
1058
|
+
"enum": [
|
|
1059
|
+
"pageToken"
|
|
1060
|
+
]
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
},
|
|
645
1066
|
{
|
|
646
1067
|
"if": {
|
|
647
1068
|
"properties": {
|
|
@@ -711,6 +1132,23 @@
|
|
|
711
1132
|
"default": "plain",
|
|
712
1133
|
"description": "How Slack renders a message body (0.71.0): plain posts the text verbatim; mrkdwn lets Slack interpret its markup (*bold*, links, lists)."
|
|
713
1134
|
},
|
|
1135
|
+
"BasecampContentFormat": {
|
|
1136
|
+
"type": "string",
|
|
1137
|
+
"enum": [
|
|
1138
|
+
"plain",
|
|
1139
|
+
"html"
|
|
1140
|
+
],
|
|
1141
|
+
"default": "plain",
|
|
1142
|
+
"description": "How Basecamp reads a body (0.76.0): plain is HTML-escaped by governance with newlines as <br>; html is passed to Basecamp's rich text as written."
|
|
1143
|
+
},
|
|
1144
|
+
"BasecampProjectStatus": {
|
|
1145
|
+
"type": "string",
|
|
1146
|
+
"enum": [
|
|
1147
|
+
"active",
|
|
1148
|
+
"archived"
|
|
1149
|
+
],
|
|
1150
|
+
"description": "Which projects basecamp.project.list returns (0.76.0): the active ones (the default) or the archived ones."
|
|
1151
|
+
},
|
|
714
1152
|
"EmailAttachment": {
|
|
715
1153
|
"type": "object",
|
|
716
1154
|
"additionalProperties": false,
|
|
@@ -1144,6 +1582,127 @@
|
|
|
1144
1582
|
"text": "approved"
|
|
1145
1583
|
}
|
|
1146
1584
|
}
|
|
1585
|
+
},
|
|
1586
|
+
{
|
|
1587
|
+
"connection": "sales-warehouse",
|
|
1588
|
+
"operation": "warehouse.view.read",
|
|
1589
|
+
"resource": "weekly_sales",
|
|
1590
|
+
"input": {
|
|
1591
|
+
"columns": [
|
|
1592
|
+
"week",
|
|
1593
|
+
"total"
|
|
1594
|
+
],
|
|
1595
|
+
"limit": 100
|
|
1596
|
+
},
|
|
1597
|
+
"sampleRows": [
|
|
1598
|
+
{
|
|
1599
|
+
"week": "2026-W36",
|
|
1600
|
+
"total": "1234.50"
|
|
1601
|
+
},
|
|
1602
|
+
{
|
|
1603
|
+
"week": "2026-W37",
|
|
1604
|
+
"total": null
|
|
1605
|
+
}
|
|
1606
|
+
]
|
|
1607
|
+
},
|
|
1608
|
+
{
|
|
1609
|
+
"connection": "company-basecamp",
|
|
1610
|
+
"operation": "basecamp.project.list",
|
|
1611
|
+
"resource": "account",
|
|
1612
|
+
"input": {
|
|
1613
|
+
"projectStatus": "active"
|
|
1614
|
+
}
|
|
1615
|
+
},
|
|
1616
|
+
{
|
|
1617
|
+
"connection": "company-basecamp",
|
|
1618
|
+
"operation": "basecamp.todolist.list",
|
|
1619
|
+
"resource": "launch",
|
|
1620
|
+
"input": {}
|
|
1621
|
+
},
|
|
1622
|
+
{
|
|
1623
|
+
"connection": "company-basecamp",
|
|
1624
|
+
"operation": "basecamp.todo.list",
|
|
1625
|
+
"resource": "launch",
|
|
1626
|
+
"input": {
|
|
1627
|
+
"todolistId": "1069479520",
|
|
1628
|
+
"completed": false
|
|
1629
|
+
}
|
|
1630
|
+
},
|
|
1631
|
+
{
|
|
1632
|
+
"connection": "company-basecamp",
|
|
1633
|
+
"operation": "basecamp.todo.create",
|
|
1634
|
+
"resource": "launch",
|
|
1635
|
+
"input": {
|
|
1636
|
+
"todolistId": "1069479520",
|
|
1637
|
+
"content": "Ship the weekly report",
|
|
1638
|
+
"description": "Attach the PDF to the message board post.",
|
|
1639
|
+
"dueOn": "2026-10-17",
|
|
1640
|
+
"assigneeIds": [
|
|
1641
|
+
"1049715914"
|
|
1642
|
+
],
|
|
1643
|
+
"notify": true
|
|
1644
|
+
},
|
|
1645
|
+
"idempotencyKey": "6f1c2c1e-3a1c-4c3e-9f0e-2b6f7d8a9c16"
|
|
1646
|
+
},
|
|
1647
|
+
{
|
|
1648
|
+
"connection": "company-basecamp",
|
|
1649
|
+
"operation": "basecamp.todo.complete",
|
|
1650
|
+
"resource": "launch",
|
|
1651
|
+
"input": {
|
|
1652
|
+
"todoId": "1069479526"
|
|
1653
|
+
}
|
|
1654
|
+
},
|
|
1655
|
+
{
|
|
1656
|
+
"connection": "company-basecamp",
|
|
1657
|
+
"operation": "basecamp.message.list",
|
|
1658
|
+
"resource": "launch",
|
|
1659
|
+
"input": {
|
|
1660
|
+
"pageToken": "2"
|
|
1661
|
+
}
|
|
1662
|
+
},
|
|
1663
|
+
{
|
|
1664
|
+
"connection": "company-basecamp",
|
|
1665
|
+
"operation": "basecamp.message.post",
|
|
1666
|
+
"resource": "launch",
|
|
1667
|
+
"input": {
|
|
1668
|
+
"subject": "Weekly report",
|
|
1669
|
+
"content": "<p>The weekly report is <b>attached</b>.</p>",
|
|
1670
|
+
"contentFormat": "html"
|
|
1671
|
+
},
|
|
1672
|
+
"idempotencyKey": "6f1c2c1e-3a1c-4c3e-9f0e-2b6f7d8a9c17"
|
|
1673
|
+
},
|
|
1674
|
+
{
|
|
1675
|
+
"connection": "company-basecamp",
|
|
1676
|
+
"operation": "basecamp.comment.list",
|
|
1677
|
+
"resource": "launch",
|
|
1678
|
+
"input": {
|
|
1679
|
+
"recordingId": "1069479530"
|
|
1680
|
+
}
|
|
1681
|
+
},
|
|
1682
|
+
{
|
|
1683
|
+
"connection": "company-basecamp",
|
|
1684
|
+
"operation": "basecamp.comment.post",
|
|
1685
|
+
"resource": "launch",
|
|
1686
|
+
"input": {
|
|
1687
|
+
"recordingId": "1069479530",
|
|
1688
|
+
"content": "Shipped, thanks."
|
|
1689
|
+
},
|
|
1690
|
+
"idempotencyKey": "6f1c2c1e-3a1c-4c3e-9f0e-2b6f7d8a9c18"
|
|
1691
|
+
},
|
|
1692
|
+
{
|
|
1693
|
+
"connection": "company-basecamp",
|
|
1694
|
+
"operation": "basecamp.campfire.post",
|
|
1695
|
+
"resource": "launch",
|
|
1696
|
+
"input": {
|
|
1697
|
+
"content": "Weekly report is up on the message board."
|
|
1698
|
+
},
|
|
1699
|
+
"idempotencyKey": "6f1c2c1e-3a1c-4c3e-9f0e-2b6f7d8a9c19"
|
|
1700
|
+
},
|
|
1701
|
+
{
|
|
1702
|
+
"connection": "company-basecamp",
|
|
1703
|
+
"operation": "basecamp.people.list",
|
|
1704
|
+
"resource": "launch",
|
|
1705
|
+
"input": {}
|
|
1147
1706
|
}
|
|
1148
1707
|
]
|
|
1149
1708
|
}
|