@fourier-labs/harbour-contracts 0.71.0 → 0.73.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.
Files changed (34) hide show
  1. package/contract-release.json +26 -24
  2. package/dist/gen-ts/app-integrations-declaration.d.ts +29 -20
  3. package/dist/gen-ts/contract-release.d.ts +6 -6
  4. package/dist/gen-ts/contract-release.js +6 -6
  5. package/dist/gen-ts/data-grant-v2.d.ts +2 -2
  6. package/dist/gen-ts/deployment-app-registration.d.ts +1 -1
  7. package/dist/gen-ts/deployment-preview-retirement.d.ts +1 -1
  8. package/dist/gen-ts/index.d.ts +1 -0
  9. package/dist/gen-ts/index.js +1 -0
  10. package/dist/gen-ts/integration-execute-input-rules.d.ts +35 -0
  11. package/dist/gen-ts/integration-execute-input-rules.js +15 -0
  12. package/dist/gen-ts/integration-execute-request.d.ts +16 -2
  13. package/dist/gen-ts/integration-execute-result.d.ts +5 -0
  14. package/dist/gen-ts/integration-operations.d.ts +94 -0
  15. package/dist/gen-ts/integration-operations.js +126 -0
  16. package/dist/gen-ts/saas-connection.d.ts +2 -2
  17. package/gen-ts/app-integrations-declaration.ts +29 -20
  18. package/gen-ts/contract-release.ts +6 -6
  19. package/gen-ts/data-grant-v2.ts +2 -1
  20. package/gen-ts/deployment-app-registration.ts +1 -1
  21. package/gen-ts/deployment-preview-retirement.ts +1 -1
  22. package/gen-ts/index.ts +1 -0
  23. package/gen-ts/integration-execute-input-rules.ts +15 -0
  24. package/gen-ts/integration-execute-request.ts +17 -2
  25. package/gen-ts/integration-execute-result.ts +5 -0
  26. package/gen-ts/integration-operations.ts +127 -0
  27. package/gen-ts/saas-connection.ts +2 -1
  28. package/package.json +1 -1
  29. package/schema/app-integrations-declaration.schema.json +478 -67
  30. package/schema/deployment-app-registration.schema.json +1 -1
  31. package/schema/deployment-preview-retirement.schema.json +1 -1
  32. package/schema/integration-execute-request.schema.json +884 -120
  33. package/schema/integration-execute-result.schema.json +505 -82
  34. package/schema/saas-connection.schema.json +1 -1
@@ -0,0 +1,126 @@
1
+ /* eslint-disable */
2
+ // Code generated by tools/gen/gen.mjs from schema/*.json. DO NOT EDIT.
3
+ /** Declaration and execute metadata from the contract schemas. */
4
+ export const IntegrationOperations = {
5
+ "slack.channel.history": {
6
+ "kind": "saas",
7
+ "identities": [
8
+ "user",
9
+ "app"
10
+ ],
11
+ "readOnly": true,
12
+ "declaredMode": true,
13
+ "idempotencyKey": false
14
+ },
15
+ "slack.message.post": {
16
+ "kind": "saas",
17
+ "identities": [
18
+ "app",
19
+ "user"
20
+ ],
21
+ "readOnly": false,
22
+ "declaredMode": true,
23
+ "idempotencyKey": true
24
+ },
25
+ "slack.message.update": {
26
+ "kind": "saas",
27
+ "identities": [
28
+ "app",
29
+ "user"
30
+ ],
31
+ "readOnly": false,
32
+ "declaredMode": true,
33
+ "idempotencyKey": false
34
+ },
35
+ "slack.message.delete": {
36
+ "kind": "saas",
37
+ "identities": [
38
+ "app",
39
+ "user"
40
+ ],
41
+ "readOnly": false,
42
+ "declaredMode": true,
43
+ "idempotencyKey": false
44
+ },
45
+ "slack.dm.send": {
46
+ "kind": "saas",
47
+ "identities": [
48
+ "app"
49
+ ],
50
+ "readOnly": false,
51
+ "declaredMode": false,
52
+ "idempotencyKey": true
53
+ },
54
+ "slack.user.lookup": {
55
+ "kind": "saas",
56
+ "identities": [
57
+ "app"
58
+ ],
59
+ "readOnly": true,
60
+ "declaredMode": false,
61
+ "idempotencyKey": false
62
+ },
63
+ "gmail.thread.list": {
64
+ "kind": "saas",
65
+ "identities": [
66
+ "user"
67
+ ],
68
+ "readOnly": true,
69
+ "declaredMode": false,
70
+ "idempotencyKey": false
71
+ },
72
+ "gmail.thread.read": {
73
+ "kind": "saas",
74
+ "identities": [
75
+ "user"
76
+ ],
77
+ "readOnly": true,
78
+ "declaredMode": false,
79
+ "idempotencyKey": false
80
+ },
81
+ "gmail.message.read": {
82
+ "kind": "saas",
83
+ "identities": [
84
+ "user"
85
+ ],
86
+ "readOnly": true,
87
+ "declaredMode": false,
88
+ "idempotencyKey": false
89
+ },
90
+ "gmail.message.send": {
91
+ "kind": "saas",
92
+ "identities": [
93
+ "user"
94
+ ],
95
+ "readOnly": false,
96
+ "declaredMode": false,
97
+ "idempotencyKey": true
98
+ },
99
+ "gmail.attachment.read": {
100
+ "kind": "saas",
101
+ "identities": [
102
+ "user"
103
+ ],
104
+ "readOnly": true,
105
+ "declaredMode": false,
106
+ "idempotencyKey": false
107
+ },
108
+ "warehouse.view.read": {
109
+ "kind": "database",
110
+ "identities": [
111
+ "app"
112
+ ],
113
+ "readOnly": true,
114
+ "declaredMode": false,
115
+ "idempotencyKey": false
116
+ },
117
+ "service.request": {
118
+ "kind": "service",
119
+ "identities": [
120
+ "app"
121
+ ],
122
+ "readOnly": false,
123
+ "declaredMode": false,
124
+ "idempotencyKey": false
125
+ }
126
+ };
@@ -16,7 +16,7 @@ export type UserModeApproval = 'automatic' | 'it';
16
16
  */
17
17
  export type DirectMessageAudience = 'signed_in_person' | 'channel_members' | 'anyone';
18
18
  /**
19
- * block — every recipient must be internal (the default when absent); allowlist — internal or in `allowedDomains`; allow — any address.
19
+ * block — every recipient must be internal (what a new Gmail connection is given; a connection stored without a policy reads as allow); allowlist — internal or in `allowedDomains`; allow — any address.
20
20
  */
21
21
  export type ExternalRecipientMode = 'block' | 'allowlist' | 'allow';
22
22
  /**
@@ -56,7 +56,7 @@ export interface SaasConnection {
56
56
  * @minItems 1
57
57
  * @maxItems 11
58
58
  */
59
- operations: ('slack.channel.history' | 'slack.message.post' | 'slack.message.update' | 'slack.message.delete' | 'slack.dm.send' | 'slack.user.lookup' | 'gmail.thread.list' | 'gmail.thread.read' | 'gmail.message.read' | 'gmail.message.send' | 'gmail.attachment.read' | 'warehouse.view.read')[];
59
+ operations: ('slack.channel.history' | 'slack.message.post' | 'slack.message.update' | 'slack.message.delete' | 'slack.dm.send' | 'slack.user.lookup' | 'gmail.thread.list' | 'gmail.thread.read' | 'gmail.message.read' | 'gmail.message.send' | 'gmail.attachment.read' | 'warehouse.view.read' | 'service.request')[];
60
60
  developmentPreapproval: DevelopmentPreapproval;
61
61
  oauthClient?: SaasOauthClient;
62
62
  userModeApproval?: UserModeApproval;
@@ -1,7 +1,26 @@
1
1
  /* eslint-disable */
2
2
  // Code generated by tools/gen/gen.mjs from schema/*.json. DO NOT EDIT.
3
3
 
4
- export type IntegrationConnectionKind = 'saas' | 'database';
4
+ export type DeclaredConnection = {
5
+ kind: IntegrationConnectionKind;
6
+ presentation?: IntegrationPresentation;
7
+ operations: {
8
+ 'slack.channel.history'?: DeclaredModeChannelOperation;
9
+ 'slack.message.post'?: DeclaredModeChannelOperation;
10
+ 'slack.message.update'?: DeclaredModeChannelOperation;
11
+ 'slack.message.delete'?: DeclaredModeChannelOperation;
12
+ 'slack.dm.send'?: AppModeChannelOperation;
13
+ 'slack.user.lookup'?: AppModeChannelOperation;
14
+ 'gmail.thread.list'?: UserModeChannelOperation;
15
+ 'gmail.thread.read'?: UserModeChannelOperation;
16
+ 'gmail.message.read'?: UserModeChannelOperation;
17
+ 'gmail.message.send'?: UserModeChannelOperation;
18
+ 'gmail.attachment.read'?: UserModeChannelOperation;
19
+ 'warehouse.view.read'?: AppModeViewOperation;
20
+ 'service.request'?: ServiceOperation;
21
+ };
22
+ };
23
+ export type IntegrationConnectionKind = 'saas' | 'database' | 'service';
5
24
  /**
6
25
  * Whose authority an operation runs under. Fixed per operation, except the declared-mode Slack operations (slack.message.post; since 0.71.0 also slack.channel.history, slack.message.update, slack.message.delete): declared per app for the access request, and named per call among the app's approved modes (execute request `mode`, 0.55.0).
7
26
  */
@@ -21,7 +40,7 @@ export type ResourceNames = IntegrationAlias[];
21
40
  export type ColumnName = string;
22
41
 
23
42
  /**
24
- * Committed `.isomorph/integrations.json`: the app's declared use of tenant-wide integration connections. Keys are logical connection aliases (the governance sourceId); resources are logical names (Slack channel alias, warehouse view name), never IDs, tokens or URLs. The operation set is closed (twelve operations since 0.71.0, ADR 0018). Each operation carries a fixed identity mode — slack.dm.send=app, slack.user.lookup=app, every gmail.* operation=user, warehouse.view.read=app — except the declared-mode Slack operations (slack.message.post, and since 0.71.0 slack.channel.history, slack.message.update and slack.message.delete), whose mode the app DECLARES: `app` acts as the company's Slack app (the one audited bot identity; a post goes out under the IT-approved per-app display name when the connection declares `presentation`), `user` acts as the signed-in person after their own consent (reads what they can read, edits what they wrote). The declared mode is the one the app requests access for; an app may hold approved grants for both modes after two requests, and each declared-mode call names which approved mode it runs under (`mode` on the execute request, 0.55.0) — a mode IT did not approve is refused, never swapped for the other. A `saas` connection may declare only the Slack and Gmail operations and a `database` connection only warehouse.view.read; `presentation` is a `saas` connection's optional per-app display name and icon for app-mode Slack posts, shown to IT at approval time and applied only from the approved grant. Gmail is user-mode only (reads, one send); its single resource is the fixed `inbox` alias. slack.dm.send and slack.user.lookup address people by email rather than a channel, so their single resource is the fixed `workspace` alias (the connection's installed workspace), the way Gmail's is `inbox`. This file also owns the shared IntegrationOperation / IntegrationIdentityMode / IntegrationEnvironment / IntegrationConnectionKind / IntegrationPresentation definitions referenced by the other integration schemas.
43
+ * Committed `.isomorph/integrations.json`: the app's declared use of tenant-wide integration connections. Keys are logical connection aliases (the governance sourceId); resources are logical names (Slack channel alias, warehouse view name), never IDs, tokens or URLs. The operation set is closed (thirteen operations since 0.73.0, ADR 0018). Each operation carries a fixed identity mode — slack.dm.send=app, slack.user.lookup=app, every gmail.* operation=user, warehouse.view.read=app — except the declared-mode Slack operations (slack.message.post, and since 0.71.0 slack.channel.history, slack.message.update and slack.message.delete), whose mode the app DECLARES: `app` acts as the company's Slack app (the one audited bot identity; a post goes out under the IT-approved per-app display name when the connection declares `presentation`), `user` acts as the signed-in person after their own consent (reads what they can read, edits what they wrote). The declared mode is the one the app requests access for; an app may hold approved grants for both modes after two requests, and each declared-mode call names which approved mode it runs under (`mode` on the execute request, 0.55.0) — a mode IT did not approve is refused, never swapped for the other. A `saas` connection may declare only the Slack and Gmail operations and a `database` connection only warehouse.view.read; `presentation` is a `saas` connection's optional per-app display name and icon for app-mode Slack posts, shown to IT at approval time and applied only from the approved grant. Gmail is user-mode only (reads, one send); its single resource is the fixed `inbox` alias. slack.dm.send and slack.user.lookup address people by email rather than a channel, so their single resource is the fixed `workspace` alias (the connection's installed workspace), the way Gmail's is `inbox`. This file also owns the shared IntegrationOperation / IntegrationIdentityMode / IntegrationEnvironment / IntegrationConnectionKind / IntegrationPresentation definitions referenced by the other integration schemas.
25
44
  */
26
45
  export interface AppIntegrationsDeclaration {
27
46
  schema: 'isomorph.app-integrations/2.0';
@@ -29,24 +48,6 @@ export interface AppIntegrationsDeclaration {
29
48
  [k: string]: DeclaredConnection;
30
49
  };
31
50
  }
32
- export interface DeclaredConnection {
33
- kind: IntegrationConnectionKind;
34
- presentation?: IntegrationPresentation;
35
- operations: {
36
- 'slack.channel.history'?: DeclaredModeChannelOperation;
37
- 'slack.message.post'?: DeclaredModeChannelOperation;
38
- 'slack.message.update'?: DeclaredModeChannelOperation;
39
- 'slack.message.delete'?: DeclaredModeChannelOperation;
40
- 'slack.dm.send'?: AppModeChannelOperation;
41
- 'slack.user.lookup'?: AppModeChannelOperation;
42
- 'gmail.thread.list'?: UserModeChannelOperation;
43
- 'gmail.thread.read'?: UserModeChannelOperation;
44
- 'gmail.message.read'?: UserModeChannelOperation;
45
- 'gmail.message.send'?: UserModeChannelOperation;
46
- 'gmail.attachment.read'?: UserModeChannelOperation;
47
- 'warehouse.view.read'?: AppModeViewOperation;
48
- };
49
- }
50
51
  /**
51
52
  * saas connections only (Slack): how this app's app-mode posts are presented; meaningless for every other operation.
52
53
  */
@@ -91,3 +92,11 @@ export interface ViewResource {
91
92
  */
92
93
  columns: ColumnName[];
93
94
  }
95
+ export interface ServiceOperation {
96
+ identity: 'app';
97
+ /**
98
+ * @minItems 1
99
+ * @maxItems 1
100
+ */
101
+ resources: 'api'[];
102
+ }
@@ -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.71.0.0" as const;
5
- export const ContractPublishVersion = "0.71.0" as const;
6
- export const ContractPublishTag = "v0.71.0" as const;
7
- export const ContractSchemasDigest = "sha256:25c5de2ee9586c6280dca7c733a7063f46bd5d400112fe60f928cf6db1a627c3" as const;
4
+ export const ContractRepositoryVersion = "0.73.0.0" as const;
5
+ export const ContractPublishVersion = "0.73.0" as const;
6
+ export const ContractPublishTag = "v0.73.0" as const;
7
+ export const ContractSchemasDigest = "sha256:c0f37c59c7c2decb4fb62d96596b787628483bdcdb09756c3ea286385d31a5f5" as const;
8
8
  export const ContractAiFixturesDigest = "sha256:edac31c92e146ca1c40130f2fb5649db82e24b8cd1ac758153b90612052fddb6" as const;
9
- export const ContractGeneratedGoDigest = "sha256:09bd95f079e733af9bf594a157d7396a645cc6c9866d48b7aee6b00a9762ac62" as const;
10
- export const ContractGeneratedTypeScriptDigest = "sha256:7fa5c1e4d8fdb68855b5e10208ee6c0a210f3595f7e74174efbf6bfa4c3673ce" as const;
9
+ export const ContractGeneratedGoDigest = "sha256:eb98ee80133c91e8562b95d92388c5bb637a06ae8d97a0827f528cd6decde8c9" as const;
10
+ export const ContractGeneratedTypeScriptDigest = "sha256:ad539efcc9e4a7521f9526dd6304215f6b764be64bd40cd598ec023f6bbb4583" as const;
@@ -30,7 +30,7 @@ export interface DataGrantV2 {
30
30
  * Whose authority an operation runs under. Fixed per operation, except the declared-mode Slack operations (slack.message.post; since 0.71.0 also slack.channel.history, slack.message.update, slack.message.delete): declared per app for the access request, and named per call among the app's approved modes (execute request `mode`, 0.55.0).
31
31
  */
32
32
  mode: 'app' | 'user';
33
- kind: 'saas' | 'database';
33
+ kind: 'saas' | 'database' | 'service';
34
34
  status: DataGrantV2Status;
35
35
  /**
36
36
  * Approved operations; each must match this grant's mode. Empty until the first approval. At most the eleven SaaS operations (0.71.0); a database grant holds one.
@@ -50,6 +50,7 @@ export interface DataGrantV2 {
50
50
  | 'gmail.message.send'
51
51
  | 'gmail.attachment.read'
52
52
  | 'warehouse.view.read'
53
+ | 'service.request'
53
54
  )[];
54
55
  /**
55
56
  * Approved logical resources. Never inherited by wildcard. Empty until the first approval.
@@ -2,7 +2,7 @@
2
2
  // Code generated by tools/gen/gen.mjs from schema/*.json. DO NOT EDIT.
3
3
 
4
4
  /**
5
- * IAM/SigV4 POST /v1/deployment/apps/register body. Governance derives tenant identity-provider configuration; no identity secrets are supplied. apiHostnames explicitly identifies API hosts among backendHostnames; runtime validates that subset. Omission preserves legacy .api. inference during the coordinated V2 auth migration.
5
+ * IAM/SigV4 POST /v1/internal/deployment/apps/{appId}/register (Internal API) or POST /v1/deployment/apps/register body. Governance derives tenant identity-provider configuration; no identity secrets are supplied. apiHostnames explicitly identifies API hosts among backendHostnames; runtime validates that subset. Omission preserves legacy .api. inference during the coordinated V2 auth migration.
6
6
  */
7
7
  export interface DeploymentAppRegistration {
8
8
  tenantId: string;
@@ -2,7 +2,7 @@
2
2
  // Code generated by tools/gen/gen.mjs from schema/*.json. DO NOT EDIT.
3
3
 
4
4
  /**
5
- * IAM-protected POST /v1/deployment/apps/retire-preview request after production is LIVE and the deployment plane holds the preview retirement reservation. Disables only the registered preview version's serving routes and workload authority.
5
+ * IAM-protected POST /v1/internal/deployment/apps/{appId}/retire-preview (Internal API) or POST /v1/deployment/apps/retire-preview request after production is LIVE and the deployment plane holds the preview retirement reservation. Disables only the registered preview version's serving routes and workload authority.
6
6
  */
7
7
  export interface DeploymentPreviewRetirement {
8
8
  tenantId: string;
package/gen-ts/index.ts CHANGED
@@ -51,6 +51,7 @@ export * from './integration-error-details.js';
51
51
  export * from './integration-execute-input-rules.js';
52
52
  export * from './integration-execute-request.js';
53
53
  export * from './integration-execute-result.js';
54
+ export * from './integration-operations.js';
54
55
  export * from './internal-configuration-request.js';
55
56
  export * from './kit-bundle-manifest.js';
56
57
  export * from './kit-lock.js';
@@ -9,6 +9,7 @@
9
9
  * same message wherever it is made.
10
10
  */
11
11
  export type IntegrationExecuteInputFieldRule =
12
+ | { kind: 'object'; required: boolean }
12
13
  | { kind: 'integer'; required: boolean; minimum: number; maximum: number; default?: number }
13
14
  | { kind: 'string'; required: boolean; minLength: number; maxLength?: number; pattern?: string }
14
15
  | { kind: 'string[]'; required: boolean; minItems: number; maxItems: number; uniqueItems: boolean; item: { minLength: number; maxLength?: number; pattern?: string }; default?: readonly string[] }
@@ -134,6 +135,17 @@ export const IntegrationExecuteInputRules = {
134
135
  limit: { kind: "integer", required: false, minimum: 1, maximum: 1000, default: 100 },
135
136
  },
136
137
  },
138
+ "service.request": {
139
+ idempotencyKey: false,
140
+ fields: {
141
+ method: { kind: "enum", required: true, values: ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"] },
142
+ path: { kind: "string", required: true, minLength: 0, maxLength: 16384 },
143
+ pathParams: { kind: "object", required: false },
144
+ query: { kind: "object", required: false },
145
+ headers: { kind: "object", required: false },
146
+ body: { kind: "object", required: false },
147
+ },
148
+ },
137
149
  } as const satisfies Record<string, IntegrationExecuteOperationRule>;
138
150
 
139
151
  export type IntegrationExecuteOperation = keyof typeof IntegrationExecuteInputRules;
@@ -194,6 +206,9 @@ function checkFields(operation: string, prefix: string, fields: Readonly<Record<
194
206
 
195
207
  function checkField(operation: string, path: string, name: string, field: IntegrationExecuteInputFieldRule, value: unknown): { ok: true; value: unknown } | Refusal {
196
208
  switch (field.kind) {
209
+ case 'object':
210
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) return refuse(path, `${path} must be a JSON object`);
211
+ return { ok: true, value };
197
212
  case 'integer':
198
213
  if (typeof value !== 'number' || !Number.isInteger(value) || value < field.minimum || value > field.maximum) return refuse(path, `${path} must be an integer between ${field.minimum} and ${field.maximum}`);
199
214
  return { ok: true, value };
@@ -24,11 +24,12 @@ export type IntegrationExecuteRequest = {
24
24
  | 'gmail.message.read'
25
25
  | 'gmail.message.send'
26
26
  | 'gmail.attachment.read'
27
- | 'warehouse.view.read';
27
+ | 'warehouse.view.read'
28
+ | 'service.request';
28
29
  /**
29
30
  * Tenant-wide logical alias of a connection (governance sourceId) or of a resource under it.
30
31
  */
31
- resource: string;
32
+ resource?: string;
32
33
  input: {
33
34
  /**
34
35
  * Read operations: how many items to return; the per-operation then-block sets the real ceiling (100 for slack.channel.history, 50 for gmail.thread.list, 1000 for warehouse.view.read) and the default.
@@ -142,6 +143,20 @@ export type IntegrationExecuteRequest = {
142
143
  * @maxItems 8
143
144
  */
144
145
  orderBy?: WarehouseOrder[];
146
+ method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
147
+ path?: string;
148
+ pathParams?: {
149
+ [k: string]: unknown;
150
+ };
151
+ query?: {
152
+ [k: string]: unknown;
153
+ };
154
+ headers?: {
155
+ [k: string]: unknown;
156
+ };
157
+ body?: {
158
+ [k: string]: unknown;
159
+ };
145
160
  };
146
161
  /**
147
162
  * UUID of one explicit Send action; required for slack.message.post and gmail.message.send only. The same key with the same payload and subject returns the recorded outcome for seven days.
@@ -74,6 +74,11 @@ export type IntegrationExecuteResult = {
74
74
  rows?: {
75
75
  [k: string]: unknown;
76
76
  }[];
77
+ status?: number;
78
+ headers?: {
79
+ [k: string]: string;
80
+ };
81
+ body?: unknown;
77
82
  };
78
83
 
79
84
  export interface ChannelMessage {
@@ -0,0 +1,127 @@
1
+ /* eslint-disable */
2
+ // Code generated by tools/gen/gen.mjs from schema/*.json. DO NOT EDIT.
3
+
4
+ /** Declaration and execute metadata from the contract schemas. */
5
+ export const IntegrationOperations = {
6
+ "slack.channel.history": {
7
+ "kind": "saas",
8
+ "identities": [
9
+ "user",
10
+ "app"
11
+ ],
12
+ "readOnly": true,
13
+ "declaredMode": true,
14
+ "idempotencyKey": false
15
+ },
16
+ "slack.message.post": {
17
+ "kind": "saas",
18
+ "identities": [
19
+ "app",
20
+ "user"
21
+ ],
22
+ "readOnly": false,
23
+ "declaredMode": true,
24
+ "idempotencyKey": true
25
+ },
26
+ "slack.message.update": {
27
+ "kind": "saas",
28
+ "identities": [
29
+ "app",
30
+ "user"
31
+ ],
32
+ "readOnly": false,
33
+ "declaredMode": true,
34
+ "idempotencyKey": false
35
+ },
36
+ "slack.message.delete": {
37
+ "kind": "saas",
38
+ "identities": [
39
+ "app",
40
+ "user"
41
+ ],
42
+ "readOnly": false,
43
+ "declaredMode": true,
44
+ "idempotencyKey": false
45
+ },
46
+ "slack.dm.send": {
47
+ "kind": "saas",
48
+ "identities": [
49
+ "app"
50
+ ],
51
+ "readOnly": false,
52
+ "declaredMode": false,
53
+ "idempotencyKey": true
54
+ },
55
+ "slack.user.lookup": {
56
+ "kind": "saas",
57
+ "identities": [
58
+ "app"
59
+ ],
60
+ "readOnly": true,
61
+ "declaredMode": false,
62
+ "idempotencyKey": false
63
+ },
64
+ "gmail.thread.list": {
65
+ "kind": "saas",
66
+ "identities": [
67
+ "user"
68
+ ],
69
+ "readOnly": true,
70
+ "declaredMode": false,
71
+ "idempotencyKey": false
72
+ },
73
+ "gmail.thread.read": {
74
+ "kind": "saas",
75
+ "identities": [
76
+ "user"
77
+ ],
78
+ "readOnly": true,
79
+ "declaredMode": false,
80
+ "idempotencyKey": false
81
+ },
82
+ "gmail.message.read": {
83
+ "kind": "saas",
84
+ "identities": [
85
+ "user"
86
+ ],
87
+ "readOnly": true,
88
+ "declaredMode": false,
89
+ "idempotencyKey": false
90
+ },
91
+ "gmail.message.send": {
92
+ "kind": "saas",
93
+ "identities": [
94
+ "user"
95
+ ],
96
+ "readOnly": false,
97
+ "declaredMode": false,
98
+ "idempotencyKey": true
99
+ },
100
+ "gmail.attachment.read": {
101
+ "kind": "saas",
102
+ "identities": [
103
+ "user"
104
+ ],
105
+ "readOnly": true,
106
+ "declaredMode": false,
107
+ "idempotencyKey": false
108
+ },
109
+ "warehouse.view.read": {
110
+ "kind": "database",
111
+ "identities": [
112
+ "app"
113
+ ],
114
+ "readOnly": true,
115
+ "declaredMode": false,
116
+ "idempotencyKey": false
117
+ },
118
+ "service.request": {
119
+ "kind": "service",
120
+ "identities": [
121
+ "app"
122
+ ],
123
+ "readOnly": false,
124
+ "declaredMode": false,
125
+ "idempotencyKey": false
126
+ }
127
+ } as const;
@@ -19,7 +19,7 @@ export type UserModeApproval = 'automatic' | 'it';
19
19
  */
20
20
  export type DirectMessageAudience = 'signed_in_person' | 'channel_members' | 'anyone';
21
21
  /**
22
- * block — every recipient must be internal (the default when absent); allowlist — internal or in `allowedDomains`; allow — any address.
22
+ * block — every recipient must be internal (what a new Gmail connection is given; a connection stored without a policy reads as allow); allowlist — internal or in `allowedDomains`; allow — any address.
23
23
  */
24
24
  export type ExternalRecipientMode = 'block' | 'allowlist' | 'allow';
25
25
  /**
@@ -73,6 +73,7 @@ export interface SaasConnection {
73
73
  | 'gmail.message.send'
74
74
  | 'gmail.attachment.read'
75
75
  | 'warehouse.view.read'
76
+ | 'service.request'
76
77
  )[];
77
78
  developmentPreapproval: DevelopmentPreapproval;
78
79
  oauthClient?: SaasOauthClient;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fourier-labs/harbour-contracts",
3
- "version": "0.71.0",
3
+ "version": "0.73.0",
4
4
  "description": "Single source of truth for every data shape that crosses a boundary between Isomorph components.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,