@fourier-labs/harbour-contracts 0.102.0 → 0.104.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/contract-release.json +23 -23
- package/dist/gen-ts/ai-policy-snapshot.d.ts +1 -1
- package/dist/gen-ts/ai-pricing-revision.d.ts +1 -1
- package/dist/gen-ts/ai-trace-event.d.ts +2 -2
- package/dist/gen-ts/binding-classification-subject.d.ts +1 -1
- package/dist/gen-ts/contract-release.d.ts +6 -6
- package/dist/gen-ts/contract-release.js +6 -6
- package/dist/gen-ts/deploy-request.d.ts +2 -2
- package/dist/gen-ts/integration-execute-input-rules.d.ts +20 -1
- package/dist/gen-ts/integration-execute-input-rules.js +4 -1
- package/dist/gen-ts/integration-execute-request.d.ts +13 -1
- package/dist/gen-ts/promotion-request.d.ts +2 -2
- package/dist/gen-ts/sanitized-binding-evidence.d.ts +1 -1
- package/dist/resolver/index.d.ts +1 -1
- package/dist/resolver/index.js +5 -5
- package/gen-ts/ai-policy-snapshot.ts +2 -1
- package/gen-ts/ai-pricing-revision.ts +2 -1
- package/gen-ts/ai-trace-event.ts +4 -2
- package/gen-ts/binding-classification-subject.ts +10 -1
- package/gen-ts/contract-release.ts +6 -6
- package/gen-ts/deploy-request.ts +20 -2
- package/gen-ts/integration-execute-input-rules.ts +4 -1
- package/gen-ts/integration-execute-request.ts +13 -1
- package/gen-ts/promotion-request.ts +20 -2
- package/gen-ts/sanitized-binding-evidence.ts +10 -1
- package/package.json +1 -1
- package/schema/ai-policy-snapshot.schema.json +1 -1
- package/schema/ai-pricing-revision.schema.json +1 -1
- package/schema/ai-trace-event.schema.json +2 -2
- package/schema/binding-classification-subject.schema.json +1 -1
- package/schema/integration-execute-request.schema.json +20 -3
- package/schema/sanitized-binding-evidence.schema.json +1 -1
package/contract-release.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "harbour.contract-release/1.0",
|
|
3
|
-
"repositoryVersion": "0.
|
|
4
|
-
"publishVersion": "0.
|
|
5
|
-
"publishTag": "v0.
|
|
6
|
-
"schemasDigest": "sha256:
|
|
3
|
+
"repositoryVersion": "0.104.0.0",
|
|
4
|
+
"publishVersion": "0.104.0",
|
|
5
|
+
"publishTag": "v0.104.0",
|
|
6
|
+
"schemasDigest": "sha256:e5912b264382f93a4a505d7d4d447c26909e5faae4f8ac9917ce6f351ee2c767",
|
|
7
7
|
"aiFixturesDigest": "sha256:edac31c92e146ca1c40130f2fb5649db82e24b8cd1ac758153b90612052fddb6",
|
|
8
|
-
"generatedGoDigest": "sha256:
|
|
9
|
-
"generatedTypeScriptDigest": "sha256:
|
|
8
|
+
"generatedGoDigest": "sha256:34ea126e68d00e09b3a61d3b65d699b451e8840d3ea1c40f4abd5b066fc5f1a4",
|
|
9
|
+
"generatedTypeScriptDigest": "sha256:386ffce01eaf19ecd3ab800edf41c3288b672acf935b2a468be1edccc7980c7e",
|
|
10
10
|
"generatedExclusions": {
|
|
11
11
|
"gen-go/contract_release.go": "contains the generated aggregate digests (self-reference)",
|
|
12
12
|
"gen-ts/contract-release.ts": "contains the generated aggregate digests (self-reference)"
|
|
@@ -21,12 +21,12 @@
|
|
|
21
21
|
"schema/ai-gateway-key-lookup.schema.json": "sha256:7d362ded73c0da6b433f3c73afeabea4c38c5d6fc92c391c7ded727324deddf2",
|
|
22
22
|
"schema/ai-governance-decision.schema.json": "sha256:0b7bffb67306087eea0f80a0a15c748e206a6e0df7184d77bf13eae8cf2a7047",
|
|
23
23
|
"schema/ai-metering-policy.schema.json": "sha256:044115938d254d914feac162219d20ee48f741cd7ad32df4613b45f9c862fe8c",
|
|
24
|
-
"schema/ai-policy-snapshot.schema.json": "sha256:
|
|
25
|
-
"schema/ai-pricing-revision.schema.json": "sha256:
|
|
24
|
+
"schema/ai-policy-snapshot.schema.json": "sha256:d8cdfad6eca8157e2bc3258ab44cce6dc7ad516738d65aa35a46f4d8f897f51e",
|
|
25
|
+
"schema/ai-pricing-revision.schema.json": "sha256:79fda413bddab821fc25e7485a56ddeee578f7c718ad29b62086887ceac04410",
|
|
26
26
|
"schema/ai-runtime-binding.schema.json": "sha256:e99f983e78478b50114e0b2c940bb5bb30a4645cfd7fbddb7e0cf161d6d28502",
|
|
27
27
|
"schema/ai-runtime-contract.schema.json": "sha256:02e0d919de3bdc1823cd51b9c0cb51ee6ecb5f4bd5c242d3ecb962e8055c90c7",
|
|
28
28
|
"schema/ai-trace-event-v2.schema.json": "sha256:b479199bb6e44ea23a1da53f69943cb8f3886c433914fdb9bf9e9bdbc3dd767d",
|
|
29
|
-
"schema/ai-trace-event.schema.json": "sha256:
|
|
29
|
+
"schema/ai-trace-event.schema.json": "sha256:a77fb20e7b1217684e1aa01689008fa3e04cdfd7f6cebef7358aa4f72bfcba04",
|
|
30
30
|
"schema/ai-transform-event.schema.json": "sha256:b845762e653b19afdaf959f7bd1624db490cd10c760daa9aaa61fb83f2a86b6e",
|
|
31
31
|
"schema/ai-transform-result.schema.json": "sha256:244e380a36957ab2dcb526ea22aaecb56b53664ce1fda6934d0021c084c99133",
|
|
32
32
|
"schema/ai-verification-evidence.schema.json": "sha256:bdbc762df256d2a8dd0bdda60d4d13915ce40034cd756af9515871d145f10ad9",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"schema/app-integrations-declaration.schema.json": "sha256:2fab400674c79e53279d68cfa97a0bf8dc70d3379d4a0197ca945b4bb446b85b",
|
|
35
35
|
"schema/app-sign-in.schema.json": "sha256:2093740131b84a69757c2e474d16e32ff5d0bf0edd6f6f8de62ede7f82988f29",
|
|
36
36
|
"schema/artifact-contract.schema.json": "sha256:8047b461a1c6d07bbe867a259c57bdf5cc0fdf282cf842ec7b683a9e93713b10",
|
|
37
|
-
"schema/binding-classification-subject.schema.json": "sha256:
|
|
37
|
+
"schema/binding-classification-subject.schema.json": "sha256:c76c0232f0377d3b86162222d5789ac64c357899ea9f722d889b138593967af3",
|
|
38
38
|
"schema/builder-input-proposal.schema.json": "sha256:fe85cffa6d76b1e1effe1f5d75525f8fe0e1eaa3be4a304e491aa23ad72c0e72",
|
|
39
39
|
"schema/data-dependency.schema.json": "sha256:b4cc2b2484e982cfed64c0f56b8f1e9d1363c71854cd71f845b24fbe7d85c971",
|
|
40
40
|
"schema/data-grant-v2.schema.json": "sha256:5018753512a27cf844f465104fee9716e410832f37ac7f01185b81633cd15b5e",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"schema/identity-context.schema.json": "sha256:a0be3d3499b70f1641887ec66ab5b21ca5ab71063e9209290905738943a36e59",
|
|
59
59
|
"schema/integration-connect-result.schema.json": "sha256:3f254b67ef739dc1fa395bdc8c4dc93359b16d481dba2a2d777aa5b6f34b7af8",
|
|
60
60
|
"schema/integration-error-details.schema.json": "sha256:dd997865b6061c37e298a0ad8e7bcee6186422e04e3ccf63d24d64ef860036d3",
|
|
61
|
-
"schema/integration-execute-request.schema.json": "sha256:
|
|
61
|
+
"schema/integration-execute-request.schema.json": "sha256:2f1c388e90b87ecc33a28f7e9b3474f563b5a3cd495af9c45bbe7664c6c62538",
|
|
62
62
|
"schema/integration-execute-result.schema.json": "sha256:057b787c28b5f7339a95184fafa5deb7ce2c6441254ad8423ce3238c7dd6996c",
|
|
63
63
|
"schema/internal-configuration-request.schema.json": "sha256:229d44a3458f68dceddfba802e5c1adcd95523a45af29b93b972706b88461a7d",
|
|
64
64
|
"schema/kit-bundle-manifest.schema.json": "sha256:d8fc6ca9c30d791e785b021687e084e9171c0ea1a3a176d0f1582fcccf2c0e19",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"schema/promotion-response.schema.json": "sha256:4129712d2e29d6ef21d93d4bd0bacfd60ada3f2ee0ade852824e64346b817634",
|
|
70
70
|
"schema/resolved-app-serving.schema.json": "sha256:3b49268e189429310c2a5dcfd45e9d2187c80b6dbb9d329a0177e96e065c31c0",
|
|
71
71
|
"schema/saas-connection.schema.json": "sha256:8482db96f53d1738b89f58035ac1e92bba400c8510a9694ece775936794132aa",
|
|
72
|
-
"schema/sanitized-binding-evidence.schema.json": "sha256:
|
|
72
|
+
"schema/sanitized-binding-evidence.schema.json": "sha256:2fe48771757930178a2cedf22a39b60cf9e871ea5615926ee1d6bb20bbbf892d",
|
|
73
73
|
"schema/secret-reference.schema.json": "sha256:db4e3c2c6a2dbd72d7ea0f9c91cb3b2343a7e67b601996c6818b2ef08e440895",
|
|
74
74
|
"schema/security-scan-input-v2.schema.json": "sha256:0d418342078c9b5046ea6f4bef3c2c57539285dfee99cc0850d4f0d03739ee13",
|
|
75
75
|
"schema/security-verdict.schema.json": "sha256:f4a1c109ed27779374c52daccb0a96589613db4f3cf030a8b0e4713bf1b3dbff",
|
|
@@ -114,11 +114,11 @@
|
|
|
114
114
|
"gen-go/contracts_test.go": "sha256:56376287cb1548be1b35ab4c65d6f0b558c5d34885f7a47cb3d9e8d786607bf5",
|
|
115
115
|
"gen-go/doc.go": "sha256:316d610ce568597a2ce6f38e9782e34fa5920f6f51ab0866e6d061b8a41cd822",
|
|
116
116
|
"gen-go/error_category.go": "sha256:b2ddea22dcfa030f1a45e721e635485b0bd816cf1f38e7654628a653f5ed4583",
|
|
117
|
-
"gen-go/integration_execute_input_rules.go": "sha256:
|
|
117
|
+
"gen-go/integration_execute_input_rules.go": "sha256:1897aa9906f7d1e642df904b3a72d74fc77869eb56633dcb6303232733070c15",
|
|
118
118
|
"gen-go/integration_execute_input_rules_test.go": "sha256:0b04eb79d07764796e72fc9f3407f5852d377e636af96f6cc5ee34e2691113ff",
|
|
119
119
|
"gen-go/integration_operations.go": "sha256:a60ac73a7860b1b330b022ddde0c82e7ef146cc40ad22821013c8bdb73f9db28",
|
|
120
120
|
"gen-go/schema_documents.go": "sha256:c19c0d540f602ee997a84b90e20702d9bc63ed7d27aec267e76c04655fc182e0",
|
|
121
|
-
"gen-go/types.go": "sha256:
|
|
121
|
+
"gen-go/types.go": "sha256:d0f941cbca1772c1e17805387e0ba177d697727ec190d21f5ef83ac03a114a5f",
|
|
122
122
|
"gen-go/version_state.go": "sha256:4ef8abb126414c0025cf2c59bc9c79a74ef4a2ff89e8f316cbf05acc872371c1"
|
|
123
123
|
},
|
|
124
124
|
"generatedTypeScript": {
|
|
@@ -133,12 +133,12 @@
|
|
|
133
133
|
"gen-ts/ai-gateway-key-token.ts": "sha256:ff6551ad3332cc665878d7ec93f42ce185c375e637531b2fbc82c697b877e784",
|
|
134
134
|
"gen-ts/ai-governance-decision.ts": "sha256:607806483ae210012cea76625b7b32f70a3d374d17e6187a27d719c7811b8b72",
|
|
135
135
|
"gen-ts/ai-metering-policy.ts": "sha256:dd261d57646a509cd46efaefac4aad58d018c7f7da98326dd8859e4ce951c56a",
|
|
136
|
-
"gen-ts/ai-policy-snapshot.ts": "sha256:
|
|
137
|
-
"gen-ts/ai-pricing-revision.ts": "sha256:
|
|
136
|
+
"gen-ts/ai-policy-snapshot.ts": "sha256:348174515a1b42240e797b5366dd40be94d1bb44d0fe2bc845324206685127db",
|
|
137
|
+
"gen-ts/ai-pricing-revision.ts": "sha256:a10df43b88feaae5ecd21c11b6c60b64006879cfc06857387acb878980e161bb",
|
|
138
138
|
"gen-ts/ai-runtime-binding.ts": "sha256:3930989c01e2b90041b5a8f9eaf9d8612854c9088090ca82e5687b85f26e106f",
|
|
139
139
|
"gen-ts/ai-runtime-contract.ts": "sha256:9c252777abc88d154d1a8479dd22f268c6abda28669a0940aa0454868661bb46",
|
|
140
140
|
"gen-ts/ai-trace-event-v2.ts": "sha256:8c994355f290864da1cf42850c3eceb0e4a1567b45ed989de865213430d3ce0e",
|
|
141
|
-
"gen-ts/ai-trace-event.ts": "sha256:
|
|
141
|
+
"gen-ts/ai-trace-event.ts": "sha256:bc7c8c6bc4bb00401532be2f12daa759ace8e2b15d4770b9de133b457ab8f003",
|
|
142
142
|
"gen-ts/ai-transform-event.ts": "sha256:c8b520e01ce12b0e3a5ebe03a3ca63cc83368f26e1eef933de732c4fc1c504f9",
|
|
143
143
|
"gen-ts/ai-transform-result.ts": "sha256:208c66b2aeb425c0cbcc18b7191f6e8989443f2b2c1690648e0e06cc1448ce25",
|
|
144
144
|
"gen-ts/ai-verification-evidence.ts": "sha256:979439d77f8b47631d1eb3b6c3c54ea6fec41089d2a51dc815fd370b1c4917fc",
|
|
@@ -147,13 +147,13 @@
|
|
|
147
147
|
"gen-ts/app-sign-in.ts": "sha256:bf88671c00e9d9badb5ffc961a7e803cf92cee5a98c2f6c9e3172bbf5aaf0424",
|
|
148
148
|
"gen-ts/artifact-contract.ts": "sha256:4a6dc6d2caaeed4bb2066cc8a333e6e09e5a0d4745e0b1038293d54ab9403aeb",
|
|
149
149
|
"gen-ts/binding-classification-digest-helper.ts": "sha256:40fc7d85b4c3f3ffc5caf7d7950c62d013c83ee42058c7453b2100d95817f167",
|
|
150
|
-
"gen-ts/binding-classification-subject.ts": "sha256:
|
|
150
|
+
"gen-ts/binding-classification-subject.ts": "sha256:0dce37745279d69fc013757020befec5d966d21822971710d6c0a5476b8ee9e1",
|
|
151
151
|
"gen-ts/builder-input-proposal.ts": "sha256:b0108c3787873d3cf1a39f00967379418a6766275d3474cfa55f5a9d93ead174",
|
|
152
152
|
"gen-ts/data-dependency.ts": "sha256:259f19e2759395d72ead90b8ed74a6dcef0c2641124f4f182823138cfd19bedf",
|
|
153
153
|
"gen-ts/data-grant-v2.ts": "sha256:d03de6b7c3165a8f26ae4d5f0fad8864a5b6ad5506b4b68140191d9bc0cf177f",
|
|
154
154
|
"gen-ts/data-grant.ts": "sha256:2358579d8aa1e57b01a6f2b0eacce5531e7f21ef226404c9809925365e0d6155",
|
|
155
155
|
"gen-ts/data-source.ts": "sha256:2566f0d5c72e44278869f55211cf3d433aeb3552e57ae0ace0ff0b85e769dde6",
|
|
156
|
-
"gen-ts/deploy-request.ts": "sha256:
|
|
156
|
+
"gen-ts/deploy-request.ts": "sha256:9b0b58822f0e072c61df42c38679b34e449330d4909876c86b915afc6c1b05b6",
|
|
157
157
|
"gen-ts/deploy-response.ts": "sha256:364d9f1acf32e491498237cdd3f402d5f8e102f208db7748034f4ec68c6a6137",
|
|
158
158
|
"gen-ts/deployment-app-registration.ts": "sha256:bc6f5d8410b8dc9595f2feb2a32898ef0ef9f15d2a54da94cd362dc05e1bbd5f",
|
|
159
159
|
"gen-ts/deployment-continuation.ts": "sha256:cc9f63af4d0da5086a79103789e4f043783b75b4ed11c6512f044439a551a79c",
|
|
@@ -173,8 +173,8 @@
|
|
|
173
173
|
"gen-ts/index.ts": "sha256:5e903bb40fbf6599dc0d65171eaef7bc62b52d4cea090124a0c51ef876ad2909",
|
|
174
174
|
"gen-ts/integration-connect-result.ts": "sha256:4b10f169b6e1af364e9b418de21caa9fadbfb77b43cbff77d741cfae0b52180c",
|
|
175
175
|
"gen-ts/integration-error-details.ts": "sha256:ec082f2d302c1ef6c0bf768134c2bde4efa5fd5acf9cc0d3ccc4676e857ae43c",
|
|
176
|
-
"gen-ts/integration-execute-input-rules.ts": "sha256:
|
|
177
|
-
"gen-ts/integration-execute-request.ts": "sha256:
|
|
176
|
+
"gen-ts/integration-execute-input-rules.ts": "sha256:4ec1623b4cadf336070751dad850f276123d5464880b4ea0aff7d553ed644fb3",
|
|
177
|
+
"gen-ts/integration-execute-request.ts": "sha256:3d0d9375176bdd9f3a5d5363ec0e6f24b63270fdbd34f95772e6402ef7915d53",
|
|
178
178
|
"gen-ts/integration-execute-result.ts": "sha256:e4772c27615de03284f7686aa49f92ff83b79a12587292129783443cf3ca0f80",
|
|
179
179
|
"gen-ts/integration-operations.ts": "sha256:fc468da58ab6177e755bb21b0907d7c0a510d6dd291476f0abc1c832c7820734",
|
|
180
180
|
"gen-ts/internal-configuration-request.ts": "sha256:7032437797473fa1c581d134adef2f3d4b4f4132f482cd17743e9d47097886bc",
|
|
@@ -182,12 +182,12 @@
|
|
|
182
182
|
"gen-ts/kit-lock.ts": "sha256:06bddeaf1e2c449c9cc0dbbc696210355a9005349c604d4050eb22385fb4c22e",
|
|
183
183
|
"gen-ts/kvs-routing-entry.ts": "sha256:d92e85ee9f257d77850d1d3aac9438e2055f38084ff84a48fcedae239d47d4ca",
|
|
184
184
|
"gen-ts/mail-arrival-event.ts": "sha256:deb342c7f930a2c7bf66a46e4c0973e3b9047cd9725e714ccaeab8c64a89d25f",
|
|
185
|
-
"gen-ts/promotion-request.ts": "sha256:
|
|
185
|
+
"gen-ts/promotion-request.ts": "sha256:77b7e8bf6a867cf0c9c207c45bf99aae2bbcd9edb65ace593ea75183efadb683",
|
|
186
186
|
"gen-ts/promotion-response.ts": "sha256:f1c9cafac96faeb02a443a31786f67714e818f38d90108e7af41958396524d6f",
|
|
187
187
|
"gen-ts/resolved-app-serving.ts": "sha256:3264e85827be47bf391781cb13a1e58318d356f7bee8c2ff3e5b00a062253b23",
|
|
188
188
|
"gen-ts/saas-connection.ts": "sha256:d811dc7a0cd7d1a83e134928fc41e122262add238a8e424ef0b538bde532380d",
|
|
189
189
|
"gen-ts/sanitized-binding-digest-helper.ts": "sha256:c47d7fdc20500e2e72c23fe39ecdd610fc397c47fcba51335ebec3c380fe6872",
|
|
190
|
-
"gen-ts/sanitized-binding-evidence.ts": "sha256:
|
|
190
|
+
"gen-ts/sanitized-binding-evidence.ts": "sha256:6bcf5e34960048e8a3f5d2e2cbf3c2254a7ecbfc7d8a72e18a927ae74ca7ead9",
|
|
191
191
|
"gen-ts/secret-reference.ts": "sha256:731fbcde7315cb4128d5b01bdbe6e6f248f13c7ad8dea04a3a4e927ac4890198",
|
|
192
192
|
"gen-ts/security-scan-input-v2.ts": "sha256:cccbfc5dae0ea5a328e6b15525ac190a0aae522e3220dffe7e6c80c445d54610",
|
|
193
193
|
"gen-ts/security-verdict.ts": "sha256:beef7e4e23b385f3b18579f43bb4eb92b19aeef9e5089f3e9a149bf0067be4e8",
|
|
@@ -90,7 +90,7 @@ export interface AiPolicyClassificationMinimum {
|
|
|
90
90
|
}
|
|
91
91
|
export interface AiPolicyProvider {
|
|
92
92
|
id: AiPolicyIdentifier;
|
|
93
|
-
provider: 'openai' | 'anthropic' | 'gemini' | 'openrouter' | 'deepseek' | 'elevenlabs' | 'deepgram' | 'higgsfield' | 'mistral' | 'datalab';
|
|
93
|
+
provider: 'openai' | 'anthropic' | 'gemini' | 'openrouter' | 'deepseek' | 'elevenlabs' | 'deepgram' | 'higgsfield' | 'mistral' | 'datalab' | 'deepinfra';
|
|
94
94
|
baseUrl?: string;
|
|
95
95
|
credentialSecretRef: string;
|
|
96
96
|
enabled: boolean;
|
|
@@ -6,7 +6,7 @@ export type AiPricingDigest = string;
|
|
|
6
6
|
export interface AiPricingRevision {
|
|
7
7
|
schema: 'harbour.ai-pricing-revision/2.0';
|
|
8
8
|
revisionId: AiPricingIdentifier;
|
|
9
|
-
provider: 'openai' | 'anthropic' | 'gemini' | 'openrouter' | 'deepseek' | 'elevenlabs' | 'deepgram' | 'higgsfield' | 'mistral' | 'datalab';
|
|
9
|
+
provider: 'openai' | 'anthropic' | 'gemini' | 'openrouter' | 'deepseek' | 'elevenlabs' | 'deepgram' | 'higgsfield' | 'mistral' | 'datalab' | 'deepinfra';
|
|
10
10
|
providerModel: string;
|
|
11
11
|
region?: AiPricingIdentifier;
|
|
12
12
|
currency: 'USD';
|
|
@@ -14,7 +14,7 @@ export type AiTraceEvent = {
|
|
|
14
14
|
routeRevision?: string;
|
|
15
15
|
requestedModel?: string;
|
|
16
16
|
governedModelAlias?: string;
|
|
17
|
-
provider?: 'openai' | 'anthropic' | 'gemini' | 'openrouter' | 'deepseek' | 'elevenlabs' | 'deepgram' | 'higgsfield' | 'mistral' | 'datalab';
|
|
17
|
+
provider?: 'openai' | 'anthropic' | 'gemini' | 'openrouter' | 'deepseek' | 'elevenlabs' | 'deepgram' | 'higgsfield' | 'mistral' | 'datalab' | 'deepinfra';
|
|
18
18
|
providerModel?: string;
|
|
19
19
|
outcome: 'succeeded' | 'blocked' | 'failed' | 'cancelled';
|
|
20
20
|
/**
|
|
@@ -45,7 +45,7 @@ export type AiTraceIdentifier = string;
|
|
|
45
45
|
export type AiTraceDigest = string;
|
|
46
46
|
export type AiTraceAttempt = {
|
|
47
47
|
attempt: number;
|
|
48
|
-
provider: 'openai' | 'anthropic' | 'gemini' | 'openrouter' | 'deepseek' | 'elevenlabs' | 'deepgram' | 'higgsfield' | 'mistral' | 'datalab';
|
|
48
|
+
provider: 'openai' | 'anthropic' | 'gemini' | 'openrouter' | 'deepseek' | 'elevenlabs' | 'deepgram' | 'higgsfield' | 'mistral' | 'datalab' | 'deepinfra';
|
|
49
49
|
providerModel: string;
|
|
50
50
|
priceRevision: AiTraceIdentifier;
|
|
51
51
|
outcome: 'succeeded' | 'failed' | 'timed_out' | 'cancelled';
|
|
@@ -15,7 +15,7 @@ export type BindingClassificationEntry = {
|
|
|
15
15
|
category?: BindingClassificationCredentialCategory;
|
|
16
16
|
requestedAiMappingId?: BindingClassificationIdentifier;
|
|
17
17
|
};
|
|
18
|
-
export type BindingClassificationProviderId = 'openai' | 'anthropic' | 'gemini' | 'openrouter' | 'deepseek' | 'deepgram' | 'higgsfield' | 'mistral' | 'datalab';
|
|
18
|
+
export type BindingClassificationProviderId = 'openai' | 'anthropic' | 'gemini' | 'openrouter' | 'deepseek' | 'deepgram' | 'higgsfield' | 'mistral' | 'datalab' | 'deepinfra';
|
|
19
19
|
/**
|
|
20
20
|
* Closed current credential category. Add a reviewed contract version before supporting another credential mechanism.
|
|
21
21
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export declare const ContractRepositoryVersion: "0.
|
|
2
|
-
export declare const ContractPublishVersion: "0.
|
|
3
|
-
export declare const ContractPublishTag: "v0.
|
|
4
|
-
export declare const ContractSchemasDigest: "sha256:
|
|
1
|
+
export declare const ContractRepositoryVersion: "0.104.0.0";
|
|
2
|
+
export declare const ContractPublishVersion: "0.104.0";
|
|
3
|
+
export declare const ContractPublishTag: "v0.104.0";
|
|
4
|
+
export declare const ContractSchemasDigest: "sha256:e5912b264382f93a4a505d7d4d447c26909e5faae4f8ac9917ce6f351ee2c767";
|
|
5
5
|
export declare const ContractAiFixturesDigest: "sha256:edac31c92e146ca1c40130f2fb5649db82e24b8cd1ac758153b90612052fddb6";
|
|
6
|
-
export declare const ContractGeneratedGoDigest: "sha256:
|
|
7
|
-
export declare const ContractGeneratedTypeScriptDigest: "sha256:
|
|
6
|
+
export declare const ContractGeneratedGoDigest: "sha256:34ea126e68d00e09b3a61d3b65d699b451e8840d3ea1c40f4abd5b066fc5f1a4";
|
|
7
|
+
export declare const ContractGeneratedTypeScriptDigest: "sha256:386ffce01eaf19ecd3ab800edf41c3288b672acf935b2a468be1edccc7980c7e";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
2
|
// Code generated by tools/gen/gen.mjs from schema/*.json. DO NOT EDIT.
|
|
3
|
-
export const ContractRepositoryVersion = "0.
|
|
4
|
-
export const ContractPublishVersion = "0.
|
|
5
|
-
export const ContractPublishTag = "v0.
|
|
6
|
-
export const ContractSchemasDigest = "sha256:
|
|
3
|
+
export const ContractRepositoryVersion = "0.104.0.0";
|
|
4
|
+
export const ContractPublishVersion = "0.104.0";
|
|
5
|
+
export const ContractPublishTag = "v0.104.0";
|
|
6
|
+
export const ContractSchemasDigest = "sha256:e5912b264382f93a4a505d7d4d447c26909e5faae4f8ac9917ce6f351ee2c767";
|
|
7
7
|
export const ContractAiFixturesDigest = "sha256:edac31c92e146ca1c40130f2fb5649db82e24b8cd1ac758153b90612052fddb6";
|
|
8
|
-
export const ContractGeneratedGoDigest = "sha256:
|
|
9
|
-
export const ContractGeneratedTypeScriptDigest = "sha256:
|
|
8
|
+
export const ContractGeneratedGoDigest = "sha256:34ea126e68d00e09b3a61d3b65d699b451e8840d3ea1c40f4abd5b066fc5f1a4";
|
|
9
|
+
export const ContractGeneratedTypeScriptDigest = "sha256:386ffce01eaf19ecd3ab800edf41c3288b672acf935b2a468be1edccc7980c7e";
|
|
@@ -21,7 +21,7 @@ export type DeployRequestEnvironmentBinding1 = {
|
|
|
21
21
|
type BindingClassificationEntry = {
|
|
22
22
|
kind: 'configuration' | 'secret' | 'provider_credential';
|
|
23
23
|
confidence: 'high' | 'low';
|
|
24
|
-
providerId?: 'openai' | 'anthropic' | 'gemini' | 'openrouter' | 'deepseek' | 'deepgram' | 'higgsfield' | 'mistral' | 'datalab';
|
|
24
|
+
providerId?: 'openai' | 'anthropic' | 'gemini' | 'openrouter' | 'deepseek' | 'deepgram' | 'higgsfield' | 'mistral' | 'datalab' | 'deepinfra';
|
|
25
25
|
/**
|
|
26
26
|
* Closed current credential category. Add a reviewed contract version before supporting another credential mechanism.
|
|
27
27
|
*/
|
|
@@ -144,6 +144,6 @@ interface BindingClassificationSubject {
|
|
|
144
144
|
}
|
|
145
145
|
interface BindingClassificationAiMapping {
|
|
146
146
|
mappingVersion: string;
|
|
147
|
-
providerId: 'openai' | 'anthropic' | 'gemini' | 'openrouter' | 'deepseek' | 'deepgram' | 'higgsfield' | 'mistral' | 'datalab';
|
|
147
|
+
providerId: 'openai' | 'anthropic' | 'gemini' | 'openrouter' | 'deepseek' | 'deepgram' | 'higgsfield' | 'mistral' | 'datalab' | 'deepinfra';
|
|
148
148
|
}
|
|
149
149
|
export {};
|
|
@@ -284,7 +284,7 @@ export declare const IntegrationExecuteInputRules: {
|
|
|
284
284
|
readonly fields: {
|
|
285
285
|
readonly to: {
|
|
286
286
|
readonly kind: "string[]";
|
|
287
|
-
readonly required:
|
|
287
|
+
readonly required: false;
|
|
288
288
|
readonly minItems: 1;
|
|
289
289
|
readonly maxItems: 50;
|
|
290
290
|
readonly uniqueItems: true;
|
|
@@ -368,6 +368,25 @@ export declare const IntegrationExecuteInputRules: {
|
|
|
368
368
|
readonly minLength: 0;
|
|
369
369
|
readonly pattern: "^[A-Za-z0-9_-]{1,64}$";
|
|
370
370
|
};
|
|
371
|
+
readonly replyTo: {
|
|
372
|
+
readonly kind: "string";
|
|
373
|
+
readonly required: false;
|
|
374
|
+
readonly minLength: 3;
|
|
375
|
+
readonly maxLength: 254;
|
|
376
|
+
readonly pattern: "^[^\\s@<>,;\"]+@[^\\s@<>,;\"]+\\.[^\\s@<>,;\"]+$";
|
|
377
|
+
};
|
|
378
|
+
readonly fromName: {
|
|
379
|
+
readonly kind: "string";
|
|
380
|
+
readonly required: false;
|
|
381
|
+
readonly minLength: 1;
|
|
382
|
+
readonly maxLength: 120;
|
|
383
|
+
};
|
|
384
|
+
readonly inReplyTo: {
|
|
385
|
+
readonly kind: "string";
|
|
386
|
+
readonly required: false;
|
|
387
|
+
readonly minLength: 0;
|
|
388
|
+
readonly pattern: "^<[^\\s<>]{1,250}>$";
|
|
389
|
+
};
|
|
371
390
|
};
|
|
372
391
|
};
|
|
373
392
|
readonly "gmail.attachment.read": {
|
|
@@ -70,7 +70,7 @@ export const IntegrationExecuteInputRules = {
|
|
|
70
70
|
"gmail.message.send": {
|
|
71
71
|
idempotencyKey: true,
|
|
72
72
|
fields: {
|
|
73
|
-
to: { kind: "string[]", required:
|
|
73
|
+
to: { kind: "string[]", required: false, minItems: 1, maxItems: 50, uniqueItems: true, item: { minLength: 3, maxLength: 254, pattern: "^[^\\s@<>,;\"]+@[^\\s@<>,;\"]+\\.[^\\s@<>,;\"]+$" } },
|
|
74
74
|
cc: { kind: "string[]", required: false, minItems: 1, maxItems: 50, uniqueItems: true, item: { minLength: 3, maxLength: 254, pattern: "^[^\\s@<>,;\"]+@[^\\s@<>,;\"]+\\.[^\\s@<>,;\"]+$" } },
|
|
75
75
|
bcc: { kind: "string[]", required: false, minItems: 1, maxItems: 50, uniqueItems: true, item: { minLength: 3, maxLength: 254, pattern: "^[^\\s@<>,;\"]+@[^\\s@<>,;\"]+\\.[^\\s@<>,;\"]+$" } },
|
|
76
76
|
subject: { kind: "string", required: true, minLength: 1, maxLength: 256 },
|
|
@@ -82,6 +82,9 @@ export const IntegrationExecuteInputRules = {
|
|
|
82
82
|
dataBase64: { kind: "string", required: true, minLength: 1, maxLength: 2796203 },
|
|
83
83
|
} },
|
|
84
84
|
replyToMessageId: { kind: "string", required: false, minLength: 0, pattern: "^[A-Za-z0-9_-]{1,64}$" },
|
|
85
|
+
replyTo: { kind: "string", required: false, minLength: 3, maxLength: 254, pattern: "^[^\\s@<>,;\"]+@[^\\s@<>,;\"]+\\.[^\\s@<>,;\"]+$" },
|
|
86
|
+
fromName: { kind: "string", required: false, minLength: 1, maxLength: 120 },
|
|
87
|
+
inReplyTo: { kind: "string", required: false, minLength: 0, pattern: "^<[^\\s<>]{1,250}>$" },
|
|
85
88
|
},
|
|
86
89
|
},
|
|
87
90
|
"gmail.attachment.read": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 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) — the same input either way — 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 — 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 — 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). SharePoint (0.78.0, ADR 0024; every id a Microsoft Graph id — GraphId, 1..256 characters — every operation user mode on a site alias): sharepoint.list.list {pageToken?}; sharepoint.item.list {listId, filter? 1..512 (an OData filter on `fields/...`), pageToken?}; sharepoint.item.create {listId, fields (1..32 columns, each a string <= 4000, a number, a boolean or null)} with a required idempotencyKey; sharepoint.item.update {listId, itemId, fields} (a PATCH, idempotent at Graph, so no key); sharepoint.drive.list {pageToken?}; sharepoint.file.list {driveId?, folderId?, pageToken?} (no driveId: the site's default drive; no folderId: its root); sharepoint.file.search {q 1..256, driveId?, pageToken?}; sharepoint.file.read {fileId, driveId?}; sharepoint.file.upload {filename 1..255, contentType, dataBase64 <= 2 MiB, driveId?, folderId?, conflict? rename|replace|fail} with a required idempotencyKey. A SharePoint `pageToken` is Graph's `$skiptoken` (up to 2048 characters; the shared field is that wide, the Gmail and Basecamp operations narrow it back to 256). Google Workspace and Microsoft 365 (0.86.0, ADR 0032; every operation user mode; the seven personal providers run on their fixed alias, teams.* on a channel alias): calendar.calendar.list {pageToken?}; calendar.event.list {calendarId?, timeMin, timeMax, q?, pageToken?} (RFC 3339 date-times with a zone); calendar.event.read {calendarId?, eventId}; calendar.event.create {calendarId?, title 1..256, start, end, timeZone?, allDay?, description? <= 8000, location? <= 512, attendees? 1..100 emails, notify?} with a required idempotencyKey; calendar.event.update {calendarId?, eventId, title?, start?, end?, timeZone?, description?, location?, attendees?, notify?} and calendar.event.cancel {calendarId?, eventId, notify?} (both idempotent at Google, so no key); drive.file.list {folderId?, pageToken?}; drive.file.search {q, pageToken?}; drive.file.read {fileId, exportAs? text|csv|pdf} (exportAs renders a Google Docs, Sheets or Slides file; a binary file is downloaded as is); drive.file.upload {filename, contentType, dataBase64 <= 2 MiB, folderId?, conflict?} and drive.folder.create {title, folderId?} with a required idempotencyKey; docs.document.read {documentId}; docs.document.create {title, text? <= 64 KiB} with a required idempotencyKey; docs.document.append {documentId, text <= 64 KiB} and docs.text.replace {documentId, replacements 1..64 of {find 1..512, replace <= 4000, matchCase?}} (no key: the app owns the document's state); sheets.spreadsheet.read {spreadsheetId}; sheets.values.read {spreadsheetId, range} (A1 notation, 1..256); sheets.values.append {spreadsheetId, range, values, valueInput? raw|user} with a required idempotencyKey; sheets.values.update {spreadsheetId, range, values, valueInput?} and sheets.values.clear {spreadsheetId, range} (no key); sheets.spreadsheet.create {title, sheets? 1..20 titles} with a required idempotencyKey (`values` is 1..1000 rows of 1..100 cells, each a string <= 4000, a number, a boolean or null); outlook.message.list {folder?, q?, pageToken?}; outlook.message.read {messageId}; outlook.attachment.read {messageId, attachmentId}; outlook.message.send {to, cc?, bcc?, subject, text 1..4000, html?, attachments?} and outlook.message.reply {messageId, text 1..4000, attachments?} (0.95.0: existing EmailAttachment bounds; recipients remain provider-resolved) with a required idempotencyKey like gmail.message.send; outlook.event.list {start, end, pageToken?}; outlook.event.read {eventId}; outlook.event.create (as calendar.event.create without calendarId) with a required idempotencyKey; outlook.event.update (as calendar.event.update without calendarId) and outlook.event.cancel {eventId, comment? <= 4000} (no key); onedrive.file.list, onedrive.file.search, onedrive.file.read {fileId}, onedrive.file.upload and onedrive.folder.create as the drive.* operations (Graph ids, no exportAs); excel.worksheet.list {fileId, driveId?}; excel.range.read {fileId, driveId?, worksheet, address? 1..64} (no address: the used range); excel.range.update {fileId, driveId?, worksheet, address, values} (no key: a PATCH); excel.table.list {fileId, driveId?, worksheet?}; excel.row.add {fileId, driveId?, tableName, values} and excel.worksheet.add {fileId, driveId?, title} with a required idempotencyKey; teams.message.list {pageToken?}; teams.message.post {text 1..4000, html?} and teams.reply.post {messageId, text, html?} with a required idempotencyKey. An Outlook or Teams `messageId` is a Graph id (the shared field widens to ^[A-Za-z0-9._=-]{1,256}$; the Gmail and Slack operations narrow it back to ^[A-Za-z0-9._-]{1,64}$ in their then-blocks, so their rules are unchanged), and `text` widens to 64 KiB for the Docs body (every other operation that takes it narrows it back to 4000). 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) and a sharepoint.file.upload, drive.file.upload or onedrive.file.upload (its 2 MiB file as base64; governance sizes it like the Gmail attachment route), an outlook.message.send or outlook.message.reply with attachments (the Gmail route), a docs.document.create or docs.document.append (its 64 KiB body; governance allows 80 KiB there, as for basecamp.message.post) and a sheets.values.append, sheets.values.update, excel.range.update or excel.row.add (its 64 KiB `values`), total deadline 10 s.
|
|
2
|
+
* 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) — the same input either way — 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; since 0.104.0 `to` may be absent when cc or bcc names a recipient — governance refuses a send with no recipient at all), cc?, bcc?, subject 1..256 chars, text 1..4000 chars, html? <= 64 KiB, attachments? 1..5 of <= 2 MiB each as base64, replyToMessageId?, replyTo? (one address), fromName? 1..120 chars, inReplyTo? (an RFC Message-ID; not with 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 — 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 — 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). SharePoint (0.78.0, ADR 0024; every id a Microsoft Graph id — GraphId, 1..256 characters — every operation user mode on a site alias): sharepoint.list.list {pageToken?}; sharepoint.item.list {listId, filter? 1..512 (an OData filter on `fields/...`), pageToken?}; sharepoint.item.create {listId, fields (1..32 columns, each a string <= 4000, a number, a boolean or null)} with a required idempotencyKey; sharepoint.item.update {listId, itemId, fields} (a PATCH, idempotent at Graph, so no key); sharepoint.drive.list {pageToken?}; sharepoint.file.list {driveId?, folderId?, pageToken?} (no driveId: the site's default drive; no folderId: its root); sharepoint.file.search {q 1..256, driveId?, pageToken?}; sharepoint.file.read {fileId, driveId?}; sharepoint.file.upload {filename 1..255, contentType, dataBase64 <= 2 MiB, driveId?, folderId?, conflict? rename|replace|fail} with a required idempotencyKey. A SharePoint `pageToken` is Graph's `$skiptoken` (up to 2048 characters; the shared field is that wide, the Gmail and Basecamp operations narrow it back to 256). Google Workspace and Microsoft 365 (0.86.0, ADR 0032; every operation user mode; the seven personal providers run on their fixed alias, teams.* on a channel alias): calendar.calendar.list {pageToken?}; calendar.event.list {calendarId?, timeMin, timeMax, q?, pageToken?} (RFC 3339 date-times with a zone); calendar.event.read {calendarId?, eventId}; calendar.event.create {calendarId?, title 1..256, start, end, timeZone?, allDay?, description? <= 8000, location? <= 512, attendees? 1..100 emails, notify?} with a required idempotencyKey; calendar.event.update {calendarId?, eventId, title?, start?, end?, timeZone?, description?, location?, attendees?, notify?} and calendar.event.cancel {calendarId?, eventId, notify?} (both idempotent at Google, so no key); drive.file.list {folderId?, pageToken?}; drive.file.search {q, pageToken?}; drive.file.read {fileId, exportAs? text|csv|pdf} (exportAs renders a Google Docs, Sheets or Slides file; a binary file is downloaded as is); drive.file.upload {filename, contentType, dataBase64 <= 2 MiB, folderId?, conflict?} and drive.folder.create {title, folderId?} with a required idempotencyKey; docs.document.read {documentId}; docs.document.create {title, text? <= 64 KiB} with a required idempotencyKey; docs.document.append {documentId, text <= 64 KiB} and docs.text.replace {documentId, replacements 1..64 of {find 1..512, replace <= 4000, matchCase?}} (no key: the app owns the document's state); sheets.spreadsheet.read {spreadsheetId}; sheets.values.read {spreadsheetId, range} (A1 notation, 1..256); sheets.values.append {spreadsheetId, range, values, valueInput? raw|user} with a required idempotencyKey; sheets.values.update {spreadsheetId, range, values, valueInput?} and sheets.values.clear {spreadsheetId, range} (no key); sheets.spreadsheet.create {title, sheets? 1..20 titles} with a required idempotencyKey (`values` is 1..1000 rows of 1..100 cells, each a string <= 4000, a number, a boolean or null); outlook.message.list {folder?, q?, pageToken?}; outlook.message.read {messageId}; outlook.attachment.read {messageId, attachmentId}; outlook.message.send {to, cc?, bcc?, subject, text 1..4000, html?, attachments?} and outlook.message.reply {messageId, text 1..4000, attachments?} (0.95.0: existing EmailAttachment bounds; recipients remain provider-resolved) with a required idempotencyKey like gmail.message.send; outlook.event.list {start, end, pageToken?}; outlook.event.read {eventId}; outlook.event.create (as calendar.event.create without calendarId) with a required idempotencyKey; outlook.event.update (as calendar.event.update without calendarId) and outlook.event.cancel {eventId, comment? <= 4000} (no key); onedrive.file.list, onedrive.file.search, onedrive.file.read {fileId}, onedrive.file.upload and onedrive.folder.create as the drive.* operations (Graph ids, no exportAs); excel.worksheet.list {fileId, driveId?}; excel.range.read {fileId, driveId?, worksheet, address? 1..64} (no address: the used range); excel.range.update {fileId, driveId?, worksheet, address, values} (no key: a PATCH); excel.table.list {fileId, driveId?, worksheet?}; excel.row.add {fileId, driveId?, tableName, values} and excel.worksheet.add {fileId, driveId?, title} with a required idempotencyKey; teams.message.list {pageToken?}; teams.message.post {text 1..4000, html?} and teams.reply.post {messageId, text, html?} with a required idempotencyKey. An Outlook or Teams `messageId` is a Graph id (the shared field widens to ^[A-Za-z0-9._=-]{1,256}$; the Gmail and Slack operations narrow it back to ^[A-Za-z0-9._-]{1,64}$ in their then-blocks, so their rules are unchanged), and `text` widens to 64 KiB for the Docs body (every other operation that takes it narrows it back to 4000). 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) and a sharepoint.file.upload, drive.file.upload or onedrive.file.upload (its 2 MiB file as base64; governance sizes it like the Gmail attachment route), an outlook.message.send or outlook.message.reply with attachments (the Gmail route), a docs.document.create or docs.document.append (its 64 KiB body; governance allows 80 KiB there, as for basecamp.message.post) and a sheets.values.append, sheets.values.update, excel.range.update or excel.row.add (its 64 KiB `values`), total deadline 10 s.
|
|
3
3
|
*/
|
|
4
4
|
export type IntegrationExecuteRequest = {
|
|
5
5
|
/**
|
|
@@ -81,6 +81,18 @@ export type IntegrationExecuteRequest = {
|
|
|
81
81
|
* gmail.message.send: a Gmail message id (from gmail.thread.list / gmail.message.read) the email replies to; the send joins that thread.
|
|
82
82
|
*/
|
|
83
83
|
replyToMessageId?: string;
|
|
84
|
+
/**
|
|
85
|
+
* One bare email address (no display name).
|
|
86
|
+
*/
|
|
87
|
+
replyTo?: string;
|
|
88
|
+
/**
|
|
89
|
+
* gmail.message.send (0.104.0): the display name shown beside the sending mailbox's address (From: "Name" <address>), one line of 1..120 characters. The address itself is always the mailbox that sends.
|
|
90
|
+
*/
|
|
91
|
+
fromName?: string;
|
|
92
|
+
/**
|
|
93
|
+
* gmail.message.send (0.104.0): the RFC 5322 Message-ID (angle brackets included) of a message this email answers when that message is not in the sending mailbox; sets In-Reply-To and References so the recipient's mail client threads it. Not accepted together with replyToMessageId.
|
|
94
|
+
*/
|
|
95
|
+
inReplyTo?: string;
|
|
84
96
|
/**
|
|
85
97
|
* gmail.message.send (0.71.0): an HTML body sent beside `text` (which stays the plain-text alternative), at most 64 KiB. outlook.message.send / teams.message.post / teams.reply.post (0.86.0): an HTML body beside `text`, the same way.
|
|
86
98
|
*/
|
|
@@ -21,7 +21,7 @@ export type PromotionRequestSecretBinding1 = {
|
|
|
21
21
|
type BindingClassificationEntry = {
|
|
22
22
|
kind: 'configuration' | 'secret' | 'provider_credential';
|
|
23
23
|
confidence: 'high' | 'low';
|
|
24
|
-
providerId?: 'openai' | 'anthropic' | 'gemini' | 'openrouter' | 'deepseek' | 'deepgram' | 'higgsfield' | 'mistral' | 'datalab';
|
|
24
|
+
providerId?: 'openai' | 'anthropic' | 'gemini' | 'openrouter' | 'deepseek' | 'deepgram' | 'higgsfield' | 'mistral' | 'datalab' | 'deepinfra';
|
|
25
25
|
/**
|
|
26
26
|
* Closed current credential category. Add a reviewed contract version before supporting another credential mechanism.
|
|
27
27
|
*/
|
|
@@ -94,6 +94,6 @@ interface BindingClassificationSubject {
|
|
|
94
94
|
}
|
|
95
95
|
interface BindingClassificationAiMapping {
|
|
96
96
|
mappingVersion: string;
|
|
97
|
-
providerId: 'openai' | 'anthropic' | 'gemini' | 'openrouter' | 'deepseek' | 'deepgram' | 'higgsfield' | 'mistral' | 'datalab';
|
|
97
|
+
providerId: 'openai' | 'anthropic' | 'gemini' | 'openrouter' | 'deepseek' | 'deepgram' | 'higgsfield' | 'mistral' | 'datalab' | 'deepinfra';
|
|
98
98
|
}
|
|
99
99
|
export {};
|
|
@@ -13,7 +13,7 @@ export type SanitizedRuntimeBinding = {
|
|
|
13
13
|
*/
|
|
14
14
|
secretRef?: string;
|
|
15
15
|
};
|
|
16
|
-
export type SanitizedBindingProviderId = 'openai' | 'anthropic' | 'gemini' | 'openrouter' | 'deepseek' | 'deepgram' | 'higgsfield' | 'mistral' | 'datalab';
|
|
16
|
+
export type SanitizedBindingProviderId = 'openai' | 'anthropic' | 'gemini' | 'openrouter' | 'deepseek' | 'deepgram' | 'higgsfield' | 'mistral' | 'datalab' | 'deepinfra';
|
|
17
17
|
/**
|
|
18
18
|
* Immutable DCP allocation receipt and sanitized runtime-binding set for one exact allocated version and normalized source revision. DCP persists this evidence atomically with version admission before publish or provisioning. classificationDigest chains to the caller's pre-allocation BindingClassificationSubject; bindings contain only approved configuration, app secrets or approved data-source credential references and never an AI-mapping-owned provider credential.
|
|
19
19
|
*/
|
package/dist/resolver/index.d.ts
CHANGED
|
@@ -42,7 +42,7 @@ export type { AiPolicySnapshot, AiPolicyGuardrailRule, AiPolicyGuardrailParamete
|
|
|
42
42
|
* revision rather than guessed at. Bump on ANY change to the merge rules, the
|
|
43
43
|
* platform baseline, or the classification minimums. */
|
|
44
44
|
export declare const RESOLVER_VERSION = "1.0.0";
|
|
45
|
-
export type AiProviderType = "openai" | "anthropic" | "gemini" | "openrouter" | "deepseek" | "elevenlabs" | "deepgram" | "higgsfield" | "mistral" | "datalab";
|
|
45
|
+
export type AiProviderType = "openai" | "anthropic" | "gemini" | "openrouter" | "deepseek" | "elevenlabs" | "deepgram" | "higgsfield" | "mistral" | "datalab" | "deepinfra";
|
|
46
46
|
export type AiCaptureMode = "OFF" | "BEST_EFFORT" | "REQUIRED";
|
|
47
47
|
export type AiDataClassification = "Green" | "Yellow" | "Orange" | "Red";
|
|
48
48
|
export type AiGuardrailAction = "ALLOW" | "OBSERVE" | "REDACT" | "BLOCK";
|
package/dist/resolver/index.js
CHANGED
|
@@ -49,9 +49,9 @@ const SECRET_OUTPUT_GUARDRAIL = { ruleId: "platform.secret.output", detectorId:
|
|
|
49
49
|
const MAX_REQUEST_BYTES = 20 * 1024 * 1024;
|
|
50
50
|
export const AI_PLATFORM_BASELINE = {
|
|
51
51
|
schema: "harbour.ai-platform-baseline/1.0",
|
|
52
|
-
artifactVersion: "1.
|
|
52
|
+
artifactVersion: "1.3.0",
|
|
53
53
|
controls: {
|
|
54
|
-
permittedProviderTypes: ["anthropic", "datalab", "gemini", "higgsfield", "mistral", "openai", "openrouter"],
|
|
54
|
+
permittedProviderTypes: ["anthropic", "datalab", "deepinfra", "gemini", "higgsfield", "mistral", "openai", "openrouter"],
|
|
55
55
|
requireApprovedModels: false,
|
|
56
56
|
maxCaptureMode: "BEST_EFFORT",
|
|
57
57
|
maxRetentionDays: 90,
|
|
@@ -70,11 +70,11 @@ export const AI_PLATFORM_BASELINE = {
|
|
|
70
70
|
* and are versioned by `artifactVersion` plus `RESOLVER_VERSION`. */
|
|
71
71
|
export const AI_CLASSIFICATION_MINIMUMS = {
|
|
72
72
|
schema: "harbour.ai-classification-minimums/1.0",
|
|
73
|
-
artifactVersion: "1.
|
|
73
|
+
artifactVersion: "1.3.0",
|
|
74
74
|
defaultClassification: "Yellow",
|
|
75
75
|
classes: {
|
|
76
76
|
Green: {
|
|
77
|
-
permittedProviderTypes: ["anthropic", "datalab", "gemini", "higgsfield", "mistral", "openai", "openrouter"],
|
|
77
|
+
permittedProviderTypes: ["anthropic", "datalab", "deepinfra", "gemini", "higgsfield", "mistral", "openai", "openrouter"],
|
|
78
78
|
requireApprovedModels: false,
|
|
79
79
|
maxCaptureMode: "BEST_EFFORT",
|
|
80
80
|
maxRetentionDays: 90,
|
|
@@ -88,7 +88,7 @@ export const AI_CLASSIFICATION_MINIMUMS = {
|
|
|
88
88
|
requiredGuardrails: [],
|
|
89
89
|
},
|
|
90
90
|
Yellow: {
|
|
91
|
-
permittedProviderTypes: ["anthropic", "datalab", "gemini", "higgsfield", "mistral", "openai", "openrouter"],
|
|
91
|
+
permittedProviderTypes: ["anthropic", "datalab", "deepinfra", "gemini", "higgsfield", "mistral", "openai", "openrouter"],
|
|
92
92
|
requireApprovedModels: true,
|
|
93
93
|
maxCaptureMode: "BEST_EFFORT",
|
|
94
94
|
maxRetentionDays: 60,
|
package/gen-ts/ai-trace-event.ts
CHANGED
|
@@ -27,7 +27,8 @@ export type AiTraceEvent = {
|
|
|
27
27
|
| 'deepgram'
|
|
28
28
|
| 'higgsfield'
|
|
29
29
|
| 'mistral'
|
|
30
|
-
| 'datalab'
|
|
30
|
+
| 'datalab'
|
|
31
|
+
| 'deepinfra';
|
|
31
32
|
providerModel?: string;
|
|
32
33
|
outcome: 'succeeded' | 'blocked' | 'failed' | 'cancelled';
|
|
33
34
|
/**
|
|
@@ -68,7 +69,8 @@ export type AiTraceAttempt = {
|
|
|
68
69
|
| 'deepgram'
|
|
69
70
|
| 'higgsfield'
|
|
70
71
|
| 'mistral'
|
|
71
|
-
| 'datalab'
|
|
72
|
+
| 'datalab'
|
|
73
|
+
| 'deepinfra';
|
|
72
74
|
providerModel: string;
|
|
73
75
|
priceRevision: AiTraceIdentifier;
|
|
74
76
|
outcome: 'succeeded' | 'failed' | 'timed_out' | 'cancelled';
|
|
@@ -19,7 +19,16 @@ export type BindingClassificationEntry = {
|
|
|
19
19
|
requestedAiMappingId?: BindingClassificationIdentifier;
|
|
20
20
|
};
|
|
21
21
|
export type BindingClassificationProviderId =
|
|
22
|
-
|
|
22
|
+
| 'openai'
|
|
23
|
+
| 'anthropic'
|
|
24
|
+
| 'gemini'
|
|
25
|
+
| 'openrouter'
|
|
26
|
+
| 'deepseek'
|
|
27
|
+
| 'deepgram'
|
|
28
|
+
| 'higgsfield'
|
|
29
|
+
| 'mistral'
|
|
30
|
+
| 'datalab'
|
|
31
|
+
| 'deepinfra';
|
|
23
32
|
/**
|
|
24
33
|
* Closed current credential category. Add a reviewed contract version before supporting another credential mechanism.
|
|
25
34
|
*/
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
2
|
// Code generated by tools/gen/gen.mjs from schema/*.json. DO NOT EDIT.
|
|
3
3
|
|
|
4
|
-
export const ContractRepositoryVersion = "0.
|
|
5
|
-
export const ContractPublishVersion = "0.
|
|
6
|
-
export const ContractPublishTag = "v0.
|
|
7
|
-
export const ContractSchemasDigest = "sha256:
|
|
4
|
+
export const ContractRepositoryVersion = "0.104.0.0" as const;
|
|
5
|
+
export const ContractPublishVersion = "0.104.0" as const;
|
|
6
|
+
export const ContractPublishTag = "v0.104.0" as const;
|
|
7
|
+
export const ContractSchemasDigest = "sha256:e5912b264382f93a4a505d7d4d447c26909e5faae4f8ac9917ce6f351ee2c767" as const;
|
|
8
8
|
export const ContractAiFixturesDigest = "sha256:edac31c92e146ca1c40130f2fb5649db82e24b8cd1ac758153b90612052fddb6" as const;
|
|
9
|
-
export const ContractGeneratedGoDigest = "sha256:
|
|
10
|
-
export const ContractGeneratedTypeScriptDigest = "sha256:
|
|
9
|
+
export const ContractGeneratedGoDigest = "sha256:34ea126e68d00e09b3a61d3b65d699b451e8840d3ea1c40f4abd5b066fc5f1a4" as const;
|
|
10
|
+
export const ContractGeneratedTypeScriptDigest = "sha256:386ffce01eaf19ecd3ab800edf41c3288b672acf935b2a468be1edccc7980c7e" as const;
|
package/gen-ts/deploy-request.ts
CHANGED
|
@@ -25,7 +25,16 @@ type BindingClassificationEntry = {
|
|
|
25
25
|
kind: 'configuration' | 'secret' | 'provider_credential';
|
|
26
26
|
confidence: 'high' | 'low';
|
|
27
27
|
providerId?:
|
|
28
|
-
|
|
28
|
+
| 'openai'
|
|
29
|
+
| 'anthropic'
|
|
30
|
+
| 'gemini'
|
|
31
|
+
| 'openrouter'
|
|
32
|
+
| 'deepseek'
|
|
33
|
+
| 'deepgram'
|
|
34
|
+
| 'higgsfield'
|
|
35
|
+
| 'mistral'
|
|
36
|
+
| 'datalab'
|
|
37
|
+
| 'deepinfra';
|
|
29
38
|
/**
|
|
30
39
|
* Closed current credential category. Add a reviewed contract version before supporting another credential mechanism.
|
|
31
40
|
*/
|
|
@@ -150,5 +159,14 @@ interface BindingClassificationSubject {
|
|
|
150
159
|
interface BindingClassificationAiMapping {
|
|
151
160
|
mappingVersion: string;
|
|
152
161
|
providerId:
|
|
153
|
-
|
|
162
|
+
| 'openai'
|
|
163
|
+
| 'anthropic'
|
|
164
|
+
| 'gemini'
|
|
165
|
+
| 'openrouter'
|
|
166
|
+
| 'deepseek'
|
|
167
|
+
| 'deepgram'
|
|
168
|
+
| 'higgsfield'
|
|
169
|
+
| 'mistral'
|
|
170
|
+
| 'datalab'
|
|
171
|
+
| 'deepinfra';
|
|
154
172
|
}
|
|
@@ -99,7 +99,7 @@ export const IntegrationExecuteInputRules = {
|
|
|
99
99
|
"gmail.message.send": {
|
|
100
100
|
idempotencyKey: true,
|
|
101
101
|
fields: {
|
|
102
|
-
to: { kind: "string[]", required:
|
|
102
|
+
to: { kind: "string[]", required: false, minItems: 1, maxItems: 50, uniqueItems: true, item: { minLength: 3, maxLength: 254, pattern: "^[^\\s@<>,;\"]+@[^\\s@<>,;\"]+\\.[^\\s@<>,;\"]+$" } },
|
|
103
103
|
cc: { kind: "string[]", required: false, minItems: 1, maxItems: 50, uniqueItems: true, item: { minLength: 3, maxLength: 254, pattern: "^[^\\s@<>,;\"]+@[^\\s@<>,;\"]+\\.[^\\s@<>,;\"]+$" } },
|
|
104
104
|
bcc: { kind: "string[]", required: false, minItems: 1, maxItems: 50, uniqueItems: true, item: { minLength: 3, maxLength: 254, pattern: "^[^\\s@<>,;\"]+@[^\\s@<>,;\"]+\\.[^\\s@<>,;\"]+$" } },
|
|
105
105
|
subject: { kind: "string", required: true, minLength: 1, maxLength: 256 },
|
|
@@ -111,6 +111,9 @@ export const IntegrationExecuteInputRules = {
|
|
|
111
111
|
dataBase64: { kind: "string", required: true, minLength: 1, maxLength: 2796203 },
|
|
112
112
|
} },
|
|
113
113
|
replyToMessageId: { kind: "string", required: false, minLength: 0, pattern: "^[A-Za-z0-9_-]{1,64}$" },
|
|
114
|
+
replyTo: { kind: "string", required: false, minLength: 3, maxLength: 254, pattern: "^[^\\s@<>,;\"]+@[^\\s@<>,;\"]+\\.[^\\s@<>,;\"]+$" },
|
|
115
|
+
fromName: { kind: "string", required: false, minLength: 1, maxLength: 120 },
|
|
116
|
+
inReplyTo: { kind: "string", required: false, minLength: 0, pattern: "^<[^\\s<>]{1,250}>$" },
|
|
114
117
|
},
|
|
115
118
|
},
|
|
116
119
|
"gmail.attachment.read": {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Code generated by tools/gen/gen.mjs from schema/*.json. DO NOT EDIT.
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* 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) — the same input either way — 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 — 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 — 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). SharePoint (0.78.0, ADR 0024; every id a Microsoft Graph id — GraphId, 1..256 characters — every operation user mode on a site alias): sharepoint.list.list {pageToken?}; sharepoint.item.list {listId, filter? 1..512 (an OData filter on `fields/...`), pageToken?}; sharepoint.item.create {listId, fields (1..32 columns, each a string <= 4000, a number, a boolean or null)} with a required idempotencyKey; sharepoint.item.update {listId, itemId, fields} (a PATCH, idempotent at Graph, so no key); sharepoint.drive.list {pageToken?}; sharepoint.file.list {driveId?, folderId?, pageToken?} (no driveId: the site's default drive; no folderId: its root); sharepoint.file.search {q 1..256, driveId?, pageToken?}; sharepoint.file.read {fileId, driveId?}; sharepoint.file.upload {filename 1..255, contentType, dataBase64 <= 2 MiB, driveId?, folderId?, conflict? rename|replace|fail} with a required idempotencyKey. A SharePoint `pageToken` is Graph's `$skiptoken` (up to 2048 characters; the shared field is that wide, the Gmail and Basecamp operations narrow it back to 256). Google Workspace and Microsoft 365 (0.86.0, ADR 0032; every operation user mode; the seven personal providers run on their fixed alias, teams.* on a channel alias): calendar.calendar.list {pageToken?}; calendar.event.list {calendarId?, timeMin, timeMax, q?, pageToken?} (RFC 3339 date-times with a zone); calendar.event.read {calendarId?, eventId}; calendar.event.create {calendarId?, title 1..256, start, end, timeZone?, allDay?, description? <= 8000, location? <= 512, attendees? 1..100 emails, notify?} with a required idempotencyKey; calendar.event.update {calendarId?, eventId, title?, start?, end?, timeZone?, description?, location?, attendees?, notify?} and calendar.event.cancel {calendarId?, eventId, notify?} (both idempotent at Google, so no key); drive.file.list {folderId?, pageToken?}; drive.file.search {q, pageToken?}; drive.file.read {fileId, exportAs? text|csv|pdf} (exportAs renders a Google Docs, Sheets or Slides file; a binary file is downloaded as is); drive.file.upload {filename, contentType, dataBase64 <= 2 MiB, folderId?, conflict?} and drive.folder.create {title, folderId?} with a required idempotencyKey; docs.document.read {documentId}; docs.document.create {title, text? <= 64 KiB} with a required idempotencyKey; docs.document.append {documentId, text <= 64 KiB} and docs.text.replace {documentId, replacements 1..64 of {find 1..512, replace <= 4000, matchCase?}} (no key: the app owns the document's state); sheets.spreadsheet.read {spreadsheetId}; sheets.values.read {spreadsheetId, range} (A1 notation, 1..256); sheets.values.append {spreadsheetId, range, values, valueInput? raw|user} with a required idempotencyKey; sheets.values.update {spreadsheetId, range, values, valueInput?} and sheets.values.clear {spreadsheetId, range} (no key); sheets.spreadsheet.create {title, sheets? 1..20 titles} with a required idempotencyKey (`values` is 1..1000 rows of 1..100 cells, each a string <= 4000, a number, a boolean or null); outlook.message.list {folder?, q?, pageToken?}; outlook.message.read {messageId}; outlook.attachment.read {messageId, attachmentId}; outlook.message.send {to, cc?, bcc?, subject, text 1..4000, html?, attachments?} and outlook.message.reply {messageId, text 1..4000, attachments?} (0.95.0: existing EmailAttachment bounds; recipients remain provider-resolved) with a required idempotencyKey like gmail.message.send; outlook.event.list {start, end, pageToken?}; outlook.event.read {eventId}; outlook.event.create (as calendar.event.create without calendarId) with a required idempotencyKey; outlook.event.update (as calendar.event.update without calendarId) and outlook.event.cancel {eventId, comment? <= 4000} (no key); onedrive.file.list, onedrive.file.search, onedrive.file.read {fileId}, onedrive.file.upload and onedrive.folder.create as the drive.* operations (Graph ids, no exportAs); excel.worksheet.list {fileId, driveId?}; excel.range.read {fileId, driveId?, worksheet, address? 1..64} (no address: the used range); excel.range.update {fileId, driveId?, worksheet, address, values} (no key: a PATCH); excel.table.list {fileId, driveId?, worksheet?}; excel.row.add {fileId, driveId?, tableName, values} and excel.worksheet.add {fileId, driveId?, title} with a required idempotencyKey; teams.message.list {pageToken?}; teams.message.post {text 1..4000, html?} and teams.reply.post {messageId, text, html?} with a required idempotencyKey. An Outlook or Teams `messageId` is a Graph id (the shared field widens to ^[A-Za-z0-9._=-]{1,256}$; the Gmail and Slack operations narrow it back to ^[A-Za-z0-9._-]{1,64}$ in their then-blocks, so their rules are unchanged), and `text` widens to 64 KiB for the Docs body (every other operation that takes it narrows it back to 4000). 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) and a sharepoint.file.upload, drive.file.upload or onedrive.file.upload (its 2 MiB file as base64; governance sizes it like the Gmail attachment route), an outlook.message.send or outlook.message.reply with attachments (the Gmail route), a docs.document.create or docs.document.append (its 64 KiB body; governance allows 80 KiB there, as for basecamp.message.post) and a sheets.values.append, sheets.values.update, excel.range.update or excel.row.add (its 64 KiB `values`), total deadline 10 s.
|
|
5
|
+
* 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) — the same input either way — 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; since 0.104.0 `to` may be absent when cc or bcc names a recipient — governance refuses a send with no recipient at all), cc?, bcc?, subject 1..256 chars, text 1..4000 chars, html? <= 64 KiB, attachments? 1..5 of <= 2 MiB each as base64, replyToMessageId?, replyTo? (one address), fromName? 1..120 chars, inReplyTo? (an RFC Message-ID; not with 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 — 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 — 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). SharePoint (0.78.0, ADR 0024; every id a Microsoft Graph id — GraphId, 1..256 characters — every operation user mode on a site alias): sharepoint.list.list {pageToken?}; sharepoint.item.list {listId, filter? 1..512 (an OData filter on `fields/...`), pageToken?}; sharepoint.item.create {listId, fields (1..32 columns, each a string <= 4000, a number, a boolean or null)} with a required idempotencyKey; sharepoint.item.update {listId, itemId, fields} (a PATCH, idempotent at Graph, so no key); sharepoint.drive.list {pageToken?}; sharepoint.file.list {driveId?, folderId?, pageToken?} (no driveId: the site's default drive; no folderId: its root); sharepoint.file.search {q 1..256, driveId?, pageToken?}; sharepoint.file.read {fileId, driveId?}; sharepoint.file.upload {filename 1..255, contentType, dataBase64 <= 2 MiB, driveId?, folderId?, conflict? rename|replace|fail} with a required idempotencyKey. A SharePoint `pageToken` is Graph's `$skiptoken` (up to 2048 characters; the shared field is that wide, the Gmail and Basecamp operations narrow it back to 256). Google Workspace and Microsoft 365 (0.86.0, ADR 0032; every operation user mode; the seven personal providers run on their fixed alias, teams.* on a channel alias): calendar.calendar.list {pageToken?}; calendar.event.list {calendarId?, timeMin, timeMax, q?, pageToken?} (RFC 3339 date-times with a zone); calendar.event.read {calendarId?, eventId}; calendar.event.create {calendarId?, title 1..256, start, end, timeZone?, allDay?, description? <= 8000, location? <= 512, attendees? 1..100 emails, notify?} with a required idempotencyKey; calendar.event.update {calendarId?, eventId, title?, start?, end?, timeZone?, description?, location?, attendees?, notify?} and calendar.event.cancel {calendarId?, eventId, notify?} (both idempotent at Google, so no key); drive.file.list {folderId?, pageToken?}; drive.file.search {q, pageToken?}; drive.file.read {fileId, exportAs? text|csv|pdf} (exportAs renders a Google Docs, Sheets or Slides file; a binary file is downloaded as is); drive.file.upload {filename, contentType, dataBase64 <= 2 MiB, folderId?, conflict?} and drive.folder.create {title, folderId?} with a required idempotencyKey; docs.document.read {documentId}; docs.document.create {title, text? <= 64 KiB} with a required idempotencyKey; docs.document.append {documentId, text <= 64 KiB} and docs.text.replace {documentId, replacements 1..64 of {find 1..512, replace <= 4000, matchCase?}} (no key: the app owns the document's state); sheets.spreadsheet.read {spreadsheetId}; sheets.values.read {spreadsheetId, range} (A1 notation, 1..256); sheets.values.append {spreadsheetId, range, values, valueInput? raw|user} with a required idempotencyKey; sheets.values.update {spreadsheetId, range, values, valueInput?} and sheets.values.clear {spreadsheetId, range} (no key); sheets.spreadsheet.create {title, sheets? 1..20 titles} with a required idempotencyKey (`values` is 1..1000 rows of 1..100 cells, each a string <= 4000, a number, a boolean or null); outlook.message.list {folder?, q?, pageToken?}; outlook.message.read {messageId}; outlook.attachment.read {messageId, attachmentId}; outlook.message.send {to, cc?, bcc?, subject, text 1..4000, html?, attachments?} and outlook.message.reply {messageId, text 1..4000, attachments?} (0.95.0: existing EmailAttachment bounds; recipients remain provider-resolved) with a required idempotencyKey like gmail.message.send; outlook.event.list {start, end, pageToken?}; outlook.event.read {eventId}; outlook.event.create (as calendar.event.create without calendarId) with a required idempotencyKey; outlook.event.update (as calendar.event.update without calendarId) and outlook.event.cancel {eventId, comment? <= 4000} (no key); onedrive.file.list, onedrive.file.search, onedrive.file.read {fileId}, onedrive.file.upload and onedrive.folder.create as the drive.* operations (Graph ids, no exportAs); excel.worksheet.list {fileId, driveId?}; excel.range.read {fileId, driveId?, worksheet, address? 1..64} (no address: the used range); excel.range.update {fileId, driveId?, worksheet, address, values} (no key: a PATCH); excel.table.list {fileId, driveId?, worksheet?}; excel.row.add {fileId, driveId?, tableName, values} and excel.worksheet.add {fileId, driveId?, title} with a required idempotencyKey; teams.message.list {pageToken?}; teams.message.post {text 1..4000, html?} and teams.reply.post {messageId, text, html?} with a required idempotencyKey. An Outlook or Teams `messageId` is a Graph id (the shared field widens to ^[A-Za-z0-9._=-]{1,256}$; the Gmail and Slack operations narrow it back to ^[A-Za-z0-9._-]{1,64}$ in their then-blocks, so their rules are unchanged), and `text` widens to 64 KiB for the Docs body (every other operation that takes it narrows it back to 4000). 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) and a sharepoint.file.upload, drive.file.upload or onedrive.file.upload (its 2 MiB file as base64; governance sizes it like the Gmail attachment route), an outlook.message.send or outlook.message.reply with attachments (the Gmail route), a docs.document.create or docs.document.append (its 64 KiB body; governance allows 80 KiB there, as for basecamp.message.post) and a sheets.values.append, sheets.values.update, excel.range.update or excel.row.add (its 64 KiB `values`), total deadline 10 s.
|
|
6
6
|
*/
|
|
7
7
|
export type IntegrationExecuteRequest = {
|
|
8
8
|
/**
|
|
@@ -180,6 +180,18 @@ export type IntegrationExecuteRequest = {
|
|
|
180
180
|
* gmail.message.send: a Gmail message id (from gmail.thread.list / gmail.message.read) the email replies to; the send joins that thread.
|
|
181
181
|
*/
|
|
182
182
|
replyToMessageId?: string;
|
|
183
|
+
/**
|
|
184
|
+
* One bare email address (no display name).
|
|
185
|
+
*/
|
|
186
|
+
replyTo?: string;
|
|
187
|
+
/**
|
|
188
|
+
* gmail.message.send (0.104.0): the display name shown beside the sending mailbox's address (From: "Name" <address>), one line of 1..120 characters. The address itself is always the mailbox that sends.
|
|
189
|
+
*/
|
|
190
|
+
fromName?: string;
|
|
191
|
+
/**
|
|
192
|
+
* gmail.message.send (0.104.0): the RFC 5322 Message-ID (angle brackets included) of a message this email answers when that message is not in the sending mailbox; sets In-Reply-To and References so the recipient's mail client threads it. Not accepted together with replyToMessageId.
|
|
193
|
+
*/
|
|
194
|
+
inReplyTo?: string;
|
|
183
195
|
/**
|
|
184
196
|
* gmail.message.send (0.71.0): an HTML body sent beside `text` (which stays the plain-text alternative), at most 64 KiB. outlook.message.send / teams.message.post / teams.reply.post (0.86.0): an HTML body beside `text`, the same way.
|
|
185
197
|
*/
|
|
@@ -25,7 +25,16 @@ type BindingClassificationEntry = {
|
|
|
25
25
|
kind: 'configuration' | 'secret' | 'provider_credential';
|
|
26
26
|
confidence: 'high' | 'low';
|
|
27
27
|
providerId?:
|
|
28
|
-
|
|
28
|
+
| 'openai'
|
|
29
|
+
| 'anthropic'
|
|
30
|
+
| 'gemini'
|
|
31
|
+
| 'openrouter'
|
|
32
|
+
| 'deepseek'
|
|
33
|
+
| 'deepgram'
|
|
34
|
+
| 'higgsfield'
|
|
35
|
+
| 'mistral'
|
|
36
|
+
| 'datalab'
|
|
37
|
+
| 'deepinfra';
|
|
29
38
|
/**
|
|
30
39
|
* Closed current credential category. Add a reviewed contract version before supporting another credential mechanism.
|
|
31
40
|
*/
|
|
@@ -100,5 +109,14 @@ interface BindingClassificationSubject {
|
|
|
100
109
|
interface BindingClassificationAiMapping {
|
|
101
110
|
mappingVersion: string;
|
|
102
111
|
providerId:
|
|
103
|
-
|
|
112
|
+
| 'openai'
|
|
113
|
+
| 'anthropic'
|
|
114
|
+
| 'gemini'
|
|
115
|
+
| 'openrouter'
|
|
116
|
+
| 'deepseek'
|
|
117
|
+
| 'deepgram'
|
|
118
|
+
| 'higgsfield'
|
|
119
|
+
| 'mistral'
|
|
120
|
+
| 'datalab'
|
|
121
|
+
| 'deepinfra';
|
|
104
122
|
}
|
|
@@ -17,7 +17,16 @@ export type SanitizedRuntimeBinding = {
|
|
|
17
17
|
secretRef?: string;
|
|
18
18
|
};
|
|
19
19
|
export type SanitizedBindingProviderId =
|
|
20
|
-
|
|
20
|
+
| 'openai'
|
|
21
|
+
| 'anthropic'
|
|
22
|
+
| 'gemini'
|
|
23
|
+
| 'openrouter'
|
|
24
|
+
| 'deepseek'
|
|
25
|
+
| 'deepgram'
|
|
26
|
+
| 'higgsfield'
|
|
27
|
+
| 'mistral'
|
|
28
|
+
| 'datalab'
|
|
29
|
+
| 'deepinfra';
|
|
21
30
|
|
|
22
31
|
/**
|
|
23
32
|
* Immutable DCP allocation receipt and sanitized runtime-binding set for one exact allocated version and normalized source revision. DCP persists this evidence atomically with version admission before publish or provisioning. classificationDigest chains to the caller's pre-allocation BindingClassificationSubject; bindings contain only approved configuration, app secrets or approved data-source credential references and never an AI-mapping-owned provider credential.
|
package/package.json
CHANGED
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
"required": ["id", "provider", "credentialSecretRef", "enabled"],
|
|
110
110
|
"properties": {
|
|
111
111
|
"id": { "$ref": "#/definitions/AiPolicyIdentifier" },
|
|
112
|
-
"provider": { "type": "string", "enum": ["openai", "anthropic", "gemini", "openrouter", "deepseek", "elevenlabs", "deepgram", "higgsfield", "mistral", "datalab"] },
|
|
112
|
+
"provider": { "type": "string", "enum": ["openai", "anthropic", "gemini", "openrouter", "deepseek", "elevenlabs", "deepgram", "higgsfield", "mistral", "datalab", "deepinfra"] },
|
|
113
113
|
"baseUrl": { "type": "string", "format": "uri", "maxLength": 512 },
|
|
114
114
|
"credentialSecretRef": {
|
|
115
115
|
"type": "string",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"properties": {
|
|
10
10
|
"schema": { "type": "string", "const": "harbour.ai-pricing-revision/2.0" },
|
|
11
11
|
"revisionId": { "$ref": "#/definitions/AiPricingIdentifier" },
|
|
12
|
-
"provider": { "type": "string", "enum": ["openai", "anthropic", "gemini", "openrouter", "deepseek", "elevenlabs", "deepgram", "higgsfield", "mistral", "datalab"] },
|
|
12
|
+
"provider": { "type": "string", "enum": ["openai", "anthropic", "gemini", "openrouter", "deepseek", "elevenlabs", "deepgram", "higgsfield", "mistral", "datalab", "deepinfra"] },
|
|
13
13
|
"providerModel": { "type": "string", "minLength": 1, "maxLength": 256 },
|
|
14
14
|
"region": { "$ref": "#/definitions/AiPricingIdentifier" },
|
|
15
15
|
"currency": { "type": "string", "const": "USD" },
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"routeRevision": { "type": "string", "minLength": 1, "maxLength": 256 },
|
|
43
43
|
"requestedModel": { "type": "string", "minLength": 1, "maxLength": 256 },
|
|
44
44
|
"governedModelAlias": { "type": "string", "minLength": 1, "maxLength": 160 },
|
|
45
|
-
"provider": { "type": "string", "enum": ["openai", "anthropic", "gemini", "openrouter", "deepseek", "elevenlabs", "deepgram", "higgsfield", "mistral", "datalab"] },
|
|
45
|
+
"provider": { "type": "string", "enum": ["openai", "anthropic", "gemini", "openrouter", "deepseek", "elevenlabs", "deepgram", "higgsfield", "mistral", "datalab", "deepinfra"] },
|
|
46
46
|
"providerModel": { "type": "string", "minLength": 1, "maxLength": 256 },
|
|
47
47
|
"outcome": { "type": "string", "enum": ["succeeded", "blocked", "failed", "cancelled"] },
|
|
48
48
|
"usage": {
|
|
@@ -140,7 +140,7 @@
|
|
|
140
140
|
"required": ["attempt", "provider", "providerModel", "priceRevision", "outcome", "usage", "costMicroUsd", "latencyMs"],
|
|
141
141
|
"properties": {
|
|
142
142
|
"attempt": { "type": "integer", "minimum": 1, "maximum": 32 },
|
|
143
|
-
"provider": { "type": "string", "enum": ["openai", "anthropic", "gemini", "openrouter", "deepseek", "elevenlabs", "deepgram", "higgsfield", "mistral", "datalab"] },
|
|
143
|
+
"provider": { "type": "string", "enum": ["openai", "anthropic", "gemini", "openrouter", "deepseek", "elevenlabs", "deepgram", "higgsfield", "mistral", "datalab", "deepinfra"] },
|
|
144
144
|
"providerModel": { "type": "string", "minLength": 1, "maxLength": 256 },
|
|
145
145
|
"priceRevision": { "$ref": "#/definitions/AiTraceIdentifier" },
|
|
146
146
|
"outcome": { "type": "string", "enum": ["succeeded", "failed", "timed_out", "cancelled"] },
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
},
|
|
65
65
|
"BindingClassificationProviderId": {
|
|
66
66
|
"type": "string",
|
|
67
|
-
"enum": ["openai", "anthropic", "gemini", "openrouter", "deepseek", "deepgram", "higgsfield", "mistral", "datalab"]
|
|
67
|
+
"enum": ["openai", "anthropic", "gemini", "openrouter", "deepseek", "deepgram", "higgsfield", "mistral", "datalab", "deepinfra"]
|
|
68
68
|
},
|
|
69
69
|
"BindingClassificationCredentialCategory": {
|
|
70
70
|
"description": "Closed current credential category. Add a reviewed contract version before supporting another credential mechanism.",
|
|
@@ -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). 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). SharePoint (0.78.0, ADR 0024; every id a Microsoft Graph id \u2014 GraphId, 1..256 characters \u2014 every operation user mode on a site alias): sharepoint.list.list {pageToken?}; sharepoint.item.list {listId, filter? 1..512 (an OData filter on `fields/...`), pageToken?}; sharepoint.item.create {listId, fields (1..32 columns, each a string <= 4000, a number, a boolean or null)} with a required idempotencyKey; sharepoint.item.update {listId, itemId, fields} (a PATCH, idempotent at Graph, so no key); sharepoint.drive.list {pageToken?}; sharepoint.file.list {driveId?, folderId?, pageToken?} (no driveId: the site's default drive; no folderId: its root); sharepoint.file.search {q 1..256, driveId?, pageToken?}; sharepoint.file.read {fileId, driveId?}; sharepoint.file.upload {filename 1..255, contentType, dataBase64 <= 2 MiB, driveId?, folderId?, conflict? rename|replace|fail} with a required idempotencyKey. A SharePoint `pageToken` is Graph's `$skiptoken` (up to 2048 characters; the shared field is that wide, the Gmail and Basecamp operations narrow it back to 256). Google Workspace and Microsoft 365 (0.86.0, ADR 0032; every operation user mode; the seven personal providers run on their fixed alias, teams.* on a channel alias): calendar.calendar.list {pageToken?}; calendar.event.list {calendarId?, timeMin, timeMax, q?, pageToken?} (RFC 3339 date-times with a zone); calendar.event.read {calendarId?, eventId}; calendar.event.create {calendarId?, title 1..256, start, end, timeZone?, allDay?, description? <= 8000, location? <= 512, attendees? 1..100 emails, notify?} with a required idempotencyKey; calendar.event.update {calendarId?, eventId, title?, start?, end?, timeZone?, description?, location?, attendees?, notify?} and calendar.event.cancel {calendarId?, eventId, notify?} (both idempotent at Google, so no key); drive.file.list {folderId?, pageToken?}; drive.file.search {q, pageToken?}; drive.file.read {fileId, exportAs? text|csv|pdf} (exportAs renders a Google Docs, Sheets or Slides file; a binary file is downloaded as is); drive.file.upload {filename, contentType, dataBase64 <= 2 MiB, folderId?, conflict?} and drive.folder.create {title, folderId?} with a required idempotencyKey; docs.document.read {documentId}; docs.document.create {title, text? <= 64 KiB} with a required idempotencyKey; docs.document.append {documentId, text <= 64 KiB} and docs.text.replace {documentId, replacements 1..64 of {find 1..512, replace <= 4000, matchCase?}} (no key: the app owns the document's state); sheets.spreadsheet.read {spreadsheetId}; sheets.values.read {spreadsheetId, range} (A1 notation, 1..256); sheets.values.append {spreadsheetId, range, values, valueInput? raw|user} with a required idempotencyKey; sheets.values.update {spreadsheetId, range, values, valueInput?} and sheets.values.clear {spreadsheetId, range} (no key); sheets.spreadsheet.create {title, sheets? 1..20 titles} with a required idempotencyKey (`values` is 1..1000 rows of 1..100 cells, each a string <= 4000, a number, a boolean or null); outlook.message.list {folder?, q?, pageToken?}; outlook.message.read {messageId}; outlook.attachment.read {messageId, attachmentId}; outlook.message.send {to, cc?, bcc?, subject, text 1..4000, html?, attachments?} and outlook.message.reply {messageId, text 1..4000, attachments?} (0.95.0: existing EmailAttachment bounds; recipients remain provider-resolved) with a required idempotencyKey like gmail.message.send; outlook.event.list {start, end, pageToken?}; outlook.event.read {eventId}; outlook.event.create (as calendar.event.create without calendarId) with a required idempotencyKey; outlook.event.update (as calendar.event.update without calendarId) and outlook.event.cancel {eventId, comment? <= 4000} (no key); onedrive.file.list, onedrive.file.search, onedrive.file.read {fileId}, onedrive.file.upload and onedrive.folder.create as the drive.* operations (Graph ids, no exportAs); excel.worksheet.list {fileId, driveId?}; excel.range.read {fileId, driveId?, worksheet, address? 1..64} (no address: the used range); excel.range.update {fileId, driveId?, worksheet, address, values} (no key: a PATCH); excel.table.list {fileId, driveId?, worksheet?}; excel.row.add {fileId, driveId?, tableName, values} and excel.worksheet.add {fileId, driveId?, title} with a required idempotencyKey; teams.message.list {pageToken?}; teams.message.post {text 1..4000, html?} and teams.reply.post {messageId, text, html?} with a required idempotencyKey. An Outlook or Teams `messageId` is a Graph id (the shared field widens to ^[A-Za-z0-9._=-]{1,256}$; the Gmail and Slack operations narrow it back to ^[A-Za-z0-9._-]{1,64}$ in their then-blocks, so their rules are unchanged), and `text` widens to 64 KiB for the Docs body (every other operation that takes it narrows it back to 4000). 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) and a sharepoint.file.upload, drive.file.upload or onedrive.file.upload (its 2 MiB file as base64; governance sizes it like the Gmail attachment route), an outlook.message.send or outlook.message.reply with attachments (the Gmail route), a docs.document.create or docs.document.append (its 64 KiB body; governance allows 80 KiB there, as for basecamp.message.post) and a sheets.values.append, sheets.values.update, excel.range.update or excel.row.add (its 64 KiB `values`), 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; since 0.104.0 `to` may be absent when cc or bcc names a recipient \u2014 governance refuses a send with no recipient at all), cc?, bcc?, subject 1..256 chars, text 1..4000 chars, html? <= 64 KiB, attachments? 1..5 of <= 2 MiB each as base64, replyToMessageId?, replyTo? (one address), fromName? 1..120 chars, inReplyTo? (an RFC Message-ID; not with 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). SharePoint (0.78.0, ADR 0024; every id a Microsoft Graph id \u2014 GraphId, 1..256 characters \u2014 every operation user mode on a site alias): sharepoint.list.list {pageToken?}; sharepoint.item.list {listId, filter? 1..512 (an OData filter on `fields/...`), pageToken?}; sharepoint.item.create {listId, fields (1..32 columns, each a string <= 4000, a number, a boolean or null)} with a required idempotencyKey; sharepoint.item.update {listId, itemId, fields} (a PATCH, idempotent at Graph, so no key); sharepoint.drive.list {pageToken?}; sharepoint.file.list {driveId?, folderId?, pageToken?} (no driveId: the site's default drive; no folderId: its root); sharepoint.file.search {q 1..256, driveId?, pageToken?}; sharepoint.file.read {fileId, driveId?}; sharepoint.file.upload {filename 1..255, contentType, dataBase64 <= 2 MiB, driveId?, folderId?, conflict? rename|replace|fail} with a required idempotencyKey. A SharePoint `pageToken` is Graph's `$skiptoken` (up to 2048 characters; the shared field is that wide, the Gmail and Basecamp operations narrow it back to 256). Google Workspace and Microsoft 365 (0.86.0, ADR 0032; every operation user mode; the seven personal providers run on their fixed alias, teams.* on a channel alias): calendar.calendar.list {pageToken?}; calendar.event.list {calendarId?, timeMin, timeMax, q?, pageToken?} (RFC 3339 date-times with a zone); calendar.event.read {calendarId?, eventId}; calendar.event.create {calendarId?, title 1..256, start, end, timeZone?, allDay?, description? <= 8000, location? <= 512, attendees? 1..100 emails, notify?} with a required idempotencyKey; calendar.event.update {calendarId?, eventId, title?, start?, end?, timeZone?, description?, location?, attendees?, notify?} and calendar.event.cancel {calendarId?, eventId, notify?} (both idempotent at Google, so no key); drive.file.list {folderId?, pageToken?}; drive.file.search {q, pageToken?}; drive.file.read {fileId, exportAs? text|csv|pdf} (exportAs renders a Google Docs, Sheets or Slides file; a binary file is downloaded as is); drive.file.upload {filename, contentType, dataBase64 <= 2 MiB, folderId?, conflict?} and drive.folder.create {title, folderId?} with a required idempotencyKey; docs.document.read {documentId}; docs.document.create {title, text? <= 64 KiB} with a required idempotencyKey; docs.document.append {documentId, text <= 64 KiB} and docs.text.replace {documentId, replacements 1..64 of {find 1..512, replace <= 4000, matchCase?}} (no key: the app owns the document's state); sheets.spreadsheet.read {spreadsheetId}; sheets.values.read {spreadsheetId, range} (A1 notation, 1..256); sheets.values.append {spreadsheetId, range, values, valueInput? raw|user} with a required idempotencyKey; sheets.values.update {spreadsheetId, range, values, valueInput?} and sheets.values.clear {spreadsheetId, range} (no key); sheets.spreadsheet.create {title, sheets? 1..20 titles} with a required idempotencyKey (`values` is 1..1000 rows of 1..100 cells, each a string <= 4000, a number, a boolean or null); outlook.message.list {folder?, q?, pageToken?}; outlook.message.read {messageId}; outlook.attachment.read {messageId, attachmentId}; outlook.message.send {to, cc?, bcc?, subject, text 1..4000, html?, attachments?} and outlook.message.reply {messageId, text 1..4000, attachments?} (0.95.0: existing EmailAttachment bounds; recipients remain provider-resolved) with a required idempotencyKey like gmail.message.send; outlook.event.list {start, end, pageToken?}; outlook.event.read {eventId}; outlook.event.create (as calendar.event.create without calendarId) with a required idempotencyKey; outlook.event.update (as calendar.event.update without calendarId) and outlook.event.cancel {eventId, comment? <= 4000} (no key); onedrive.file.list, onedrive.file.search, onedrive.file.read {fileId}, onedrive.file.upload and onedrive.folder.create as the drive.* operations (Graph ids, no exportAs); excel.worksheet.list {fileId, driveId?}; excel.range.read {fileId, driveId?, worksheet, address? 1..64} (no address: the used range); excel.range.update {fileId, driveId?, worksheet, address, values} (no key: a PATCH); excel.table.list {fileId, driveId?, worksheet?}; excel.row.add {fileId, driveId?, tableName, values} and excel.worksheet.add {fileId, driveId?, title} with a required idempotencyKey; teams.message.list {pageToken?}; teams.message.post {text 1..4000, html?} and teams.reply.post {messageId, text, html?} with a required idempotencyKey. An Outlook or Teams `messageId` is a Graph id (the shared field widens to ^[A-Za-z0-9._=-]{1,256}$; the Gmail and Slack operations narrow it back to ^[A-Za-z0-9._-]{1,64}$ in their then-blocks, so their rules are unchanged), and `text` widens to 64 KiB for the Docs body (every other operation that takes it narrows it back to 4000). 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) and a sharepoint.file.upload, drive.file.upload or onedrive.file.upload (its 2 MiB file as base64; governance sizes it like the Gmail attachment route), an outlook.message.send or outlook.message.reply with attachments (the Gmail route), a docs.document.create or docs.document.append (its 64 KiB body; governance allows 80 KiB there, as for basecamp.message.post) and a sheets.values.append, sheets.values.update, excel.range.update or excel.row.add (its 64 KiB `values`), total deadline 10 s.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"additionalProperties": false,
|
|
8
8
|
"required": [
|
|
@@ -128,6 +128,21 @@
|
|
|
128
128
|
"pattern": "^[A-Za-z0-9_-]{1,64}$",
|
|
129
129
|
"description": "gmail.message.send: a Gmail message id (from gmail.thread.list / gmail.message.read) the email replies to; the send joins that thread."
|
|
130
130
|
},
|
|
131
|
+
"replyTo": {
|
|
132
|
+
"$ref": "#/definitions/EmailAddress",
|
|
133
|
+
"description": "gmail.message.send (0.104.0): the one address a recipient's reply goes to (the Reply-To header), when it is not the sending mailbox."
|
|
134
|
+
},
|
|
135
|
+
"fromName": {
|
|
136
|
+
"type": "string",
|
|
137
|
+
"minLength": 1,
|
|
138
|
+
"maxLength": 120,
|
|
139
|
+
"description": "gmail.message.send (0.104.0): the display name shown beside the sending mailbox's address (From: \"Name\" <address>), one line of 1..120 characters. The address itself is always the mailbox that sends."
|
|
140
|
+
},
|
|
141
|
+
"inReplyTo": {
|
|
142
|
+
"type": "string",
|
|
143
|
+
"pattern": "^<[^\\s<>]{1,250}>$",
|
|
144
|
+
"description": "gmail.message.send (0.104.0): the RFC 5322 Message-ID (angle brackets included) of a message this email answers when that message is not in the sending mailbox; sets In-Reply-To and References so the recipient's mail client threads it. Not accepted together with replyToMessageId."
|
|
145
|
+
},
|
|
131
146
|
"html": {
|
|
132
147
|
"type": "string",
|
|
133
148
|
"minLength": 1,
|
|
@@ -1403,11 +1418,13 @@
|
|
|
1403
1418
|
"text",
|
|
1404
1419
|
"html",
|
|
1405
1420
|
"attachments",
|
|
1406
|
-
"replyToMessageId"
|
|
1421
|
+
"replyToMessageId",
|
|
1422
|
+
"replyTo",
|
|
1423
|
+
"fromName",
|
|
1424
|
+
"inReplyTo"
|
|
1407
1425
|
]
|
|
1408
1426
|
},
|
|
1409
1427
|
"required": [
|
|
1410
|
-
"to",
|
|
1411
1428
|
"subject",
|
|
1412
1429
|
"text"
|
|
1413
1430
|
],
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
},
|
|
63
63
|
"SanitizedBindingProviderId": {
|
|
64
64
|
"type": "string",
|
|
65
|
-
"enum": ["openai", "anthropic", "gemini", "openrouter", "deepseek", "deepgram", "higgsfield", "mistral", "datalab"]
|
|
65
|
+
"enum": ["openai", "anthropic", "gemini", "openrouter", "deepseek", "deepgram", "higgsfield", "mistral", "datalab", "deepinfra"]
|
|
66
66
|
},
|
|
67
67
|
"SanitizedBindingAiMapping": {
|
|
68
68
|
"type": "object",
|