@fourier-labs/harbour-contracts 0.73.0 → 0.76.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/contract-release.json +26 -26
- package/dist/gen-ts/app-integrations-declaration.d.ts +15 -1
- package/dist/gen-ts/contract-release.d.ts +6 -6
- package/dist/gen-ts/contract-release.js +6 -6
- package/dist/gen-ts/data-grant-v2.d.ts +5 -5
- package/dist/gen-ts/data-source.d.ts +19 -2
- package/dist/gen-ts/integration-error-details.d.ts +2 -2
- package/dist/gen-ts/integration-execute-input-rules.d.ts +214 -0
- package/dist/gen-ts/integration-execute-input-rules.js +85 -0
- package/dist/gen-ts/integration-execute-request.d.ts +61 -6
- package/dist/gen-ts/integration-execute-result.d.ts +165 -1
- package/dist/gen-ts/integration-operations.d.ts +77 -0
- package/dist/gen-ts/integration-operations.js +99 -0
- package/dist/gen-ts/saas-connection.d.ts +22 -8
- package/gen-ts/app-integrations-declaration.ts +15 -1
- package/gen-ts/contract-release.ts +6 -6
- package/gen-ts/data-grant-v2.ts +15 -4
- package/gen-ts/data-source.ts +19 -2
- package/gen-ts/integration-error-details.ts +3 -2
- package/gen-ts/integration-execute-input-rules.ts +86 -1
- package/gen-ts/integration-execute-request.ts +71 -5
- package/gen-ts/integration-execute-result.ts +165 -1
- package/gen-ts/integration-operations.ts +99 -0
- package/gen-ts/saas-connection.ts +32 -7
- package/package.json +1 -1
- package/schema/app-integrations-declaration.schema.json +233 -2
- package/schema/data-grant-v2.schema.json +4 -4
- package/schema/data-source.schema.json +57 -2
- package/schema/integration-error-details.schema.json +3 -2
- package/schema/integration-execute-request.schema.json +563 -4
- package/schema/integration-execute-result.schema.json +558 -2
- package/schema/saas-connection.schema.json +35 -7
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
3
|
"$id": "https://schemas.harbour.dev/app-integrations-declaration.schema.json",
|
|
4
4
|
"title": "AppIntegrationsDeclaration",
|
|
5
|
-
"description": "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 (
|
|
5
|
+
"description": "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 (twenty-four operations since 0.76.0, ADR 0018 and ADR 0022). Each operation carries a fixed identity mode \u2014 slack.dm.send=app, slack.user.lookup=app, every gmail.* operation=user, every basecamp.* operation=user, warehouse.view.read=app, service.request=app \u2014 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) \u2014 a mode IT did not approve is refused, never swapped for the other. A `saas` connection may declare only the Slack, Gmail and Basecamp 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. Basecamp (0.76.0, ADR 0022) is user-mode only too: basecamp.project.list runs on the fixed `account` alias (the company's pinned Basecamp account) and every other basecamp.* operation on a project alias IT mapped in the connection's `channels` map, so Basecamp itself refuses an id outside that project. 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.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"additionalProperties": false,
|
|
8
8
|
"required": [
|
|
@@ -32,6 +32,11 @@
|
|
|
32
32
|
"pattern": "^[a-z0-9][a-z0-9._-]{0,63}$",
|
|
33
33
|
"description": "Tenant-wide logical alias of a connection (governance sourceId) or of a resource under it."
|
|
34
34
|
},
|
|
35
|
+
"BasecampId": {
|
|
36
|
+
"type": "string",
|
|
37
|
+
"pattern": "^[0-9]{1,20}$",
|
|
38
|
+
"description": "A Basecamp id (0.76.0): an account, project, to-do list, to-do, recording or person, as a string of 1..20 digits \u2014 how every basecamp.* result names one and every basecamp.* input takes one back."
|
|
39
|
+
},
|
|
35
40
|
"IntegrationConnectionKind": {
|
|
36
41
|
"type": "string",
|
|
37
42
|
"enum": [
|
|
@@ -54,10 +59,21 @@
|
|
|
54
59
|
"gmail.message.read",
|
|
55
60
|
"gmail.message.send",
|
|
56
61
|
"gmail.attachment.read",
|
|
62
|
+
"basecamp.project.list",
|
|
63
|
+
"basecamp.todolist.list",
|
|
64
|
+
"basecamp.todo.list",
|
|
65
|
+
"basecamp.todo.create",
|
|
66
|
+
"basecamp.todo.complete",
|
|
67
|
+
"basecamp.message.list",
|
|
68
|
+
"basecamp.message.post",
|
|
69
|
+
"basecamp.comment.list",
|
|
70
|
+
"basecamp.comment.post",
|
|
71
|
+
"basecamp.campfire.post",
|
|
72
|
+
"basecamp.people.list",
|
|
57
73
|
"warehouse.view.read",
|
|
58
74
|
"service.request"
|
|
59
75
|
],
|
|
60
|
-
"description": "Closed operation set. Extending it is a contracts change. gmail.message.send (0.50.0) sends one email as the signed-in person: a send like slack.message.post (explicit Send, idempotencyKey, write receipt) under user identity; since 0.71.0 it may carry an HTML body and attachments. slack.message.post (0.53.0) runs in the mode the app declares: app (the company's Slack app, under the IT-approved per-app name) or user (the signed-in person, after their consent); since 0.55.0 each call names which of the approved modes it runs under. 0.71.0 (ADR 0018) adds slack.message.update and slack.message.delete (declared mode, like post), slack.dm.send (app mode: a direct message to 1..8 workspace members named by email), slack.user.lookup (app mode: email to Slack user id), gmail.thread.read (every message of one thread) and gmail.attachment.read (one attachment's bytes), and lets slack.channel.history run in app mode as well as user mode."
|
|
76
|
+
"description": "Closed operation set. Extending it is a contracts change. 0.76.0 (ADR 0022) adds the eleven Basecamp operations, every one user mode only like gmail.*: basecamp.project.list (the projects of the company's pinned Basecamp account; its resource is the fixed `account` alias), and on one mapped project (the resource is a project alias, a key of the connection's `channels` map) basecamp.todolist.list, basecamp.todo.list, basecamp.todo.create (a receipted write: explicit action, idempotencyKey), basecamp.todo.complete (idempotent at Basecamp, no key), basecamp.message.list, basecamp.message.post, basecamp.comment.list, basecamp.comment.post, basecamp.campfire.post (the three posts are receipted writes) and basecamp.people.list. gmail.message.send (0.50.0) sends one email as the signed-in person: a send like slack.message.post (explicit Send, idempotencyKey, write receipt) under user identity; since 0.71.0 it may carry an HTML body and attachments. slack.message.post (0.53.0) runs in the mode the app declares: app (the company's Slack app, under the IT-approved per-app name) or user (the signed-in person, after their consent); since 0.55.0 each call names which of the approved modes it runs under. 0.71.0 (ADR 0018) adds slack.message.update and slack.message.delete (declared mode, like post), slack.dm.send (app mode: a direct message to 1..8 workspace members named by email), slack.user.lookup (app mode: email to Slack user id), gmail.thread.read (every message of one thread) and gmail.attachment.read (one attachment's bytes), and lets slack.channel.history run in app mode as well as user mode."
|
|
61
77
|
},
|
|
62
78
|
"IntegrationIdentityMode": {
|
|
63
79
|
"type": "string",
|
|
@@ -147,6 +163,7 @@
|
|
|
147
163
|
"identity",
|
|
148
164
|
"resources"
|
|
149
165
|
],
|
|
166
|
+
"description": "Every gmail.* operation (resource: the fixed `inbox` alias) and, since 0.76.0, every basecamp.* operation (resource: a project alias from the connection's `channels` map, or the fixed `account` alias for basecamp.project.list): user mode only — the app acts as the signed-in person after their own consent.",
|
|
150
167
|
"properties": {
|
|
151
168
|
"identity": {
|
|
152
169
|
"type": "string",
|
|
@@ -270,6 +287,39 @@
|
|
|
270
287
|
"gmail.attachment.read": {
|
|
271
288
|
"$ref": "#/definitions/UserModeChannelOperation"
|
|
272
289
|
},
|
|
290
|
+
"basecamp.project.list": {
|
|
291
|
+
"$ref": "#/definitions/UserModeChannelOperation"
|
|
292
|
+
},
|
|
293
|
+
"basecamp.todolist.list": {
|
|
294
|
+
"$ref": "#/definitions/UserModeChannelOperation"
|
|
295
|
+
},
|
|
296
|
+
"basecamp.todo.list": {
|
|
297
|
+
"$ref": "#/definitions/UserModeChannelOperation"
|
|
298
|
+
},
|
|
299
|
+
"basecamp.todo.create": {
|
|
300
|
+
"$ref": "#/definitions/UserModeChannelOperation"
|
|
301
|
+
},
|
|
302
|
+
"basecamp.todo.complete": {
|
|
303
|
+
"$ref": "#/definitions/UserModeChannelOperation"
|
|
304
|
+
},
|
|
305
|
+
"basecamp.message.list": {
|
|
306
|
+
"$ref": "#/definitions/UserModeChannelOperation"
|
|
307
|
+
},
|
|
308
|
+
"basecamp.message.post": {
|
|
309
|
+
"$ref": "#/definitions/UserModeChannelOperation"
|
|
310
|
+
},
|
|
311
|
+
"basecamp.comment.list": {
|
|
312
|
+
"$ref": "#/definitions/UserModeChannelOperation"
|
|
313
|
+
},
|
|
314
|
+
"basecamp.comment.post": {
|
|
315
|
+
"$ref": "#/definitions/UserModeChannelOperation"
|
|
316
|
+
},
|
|
317
|
+
"basecamp.campfire.post": {
|
|
318
|
+
"$ref": "#/definitions/UserModeChannelOperation"
|
|
319
|
+
},
|
|
320
|
+
"basecamp.people.list": {
|
|
321
|
+
"$ref": "#/definitions/UserModeChannelOperation"
|
|
322
|
+
},
|
|
273
323
|
"warehouse.view.read": {
|
|
274
324
|
"$ref": "#/definitions/AppModeViewOperation"
|
|
275
325
|
},
|
|
@@ -377,6 +427,61 @@
|
|
|
377
427
|
"gmail.attachment.read"
|
|
378
428
|
]
|
|
379
429
|
},
|
|
430
|
+
{
|
|
431
|
+
"required": [
|
|
432
|
+
"basecamp.project.list"
|
|
433
|
+
]
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
"required": [
|
|
437
|
+
"basecamp.todolist.list"
|
|
438
|
+
]
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
"required": [
|
|
442
|
+
"basecamp.todo.list"
|
|
443
|
+
]
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
"required": [
|
|
447
|
+
"basecamp.todo.create"
|
|
448
|
+
]
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
"required": [
|
|
452
|
+
"basecamp.todo.complete"
|
|
453
|
+
]
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
"required": [
|
|
457
|
+
"basecamp.message.list"
|
|
458
|
+
]
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
"required": [
|
|
462
|
+
"basecamp.message.post"
|
|
463
|
+
]
|
|
464
|
+
},
|
|
465
|
+
{
|
|
466
|
+
"required": [
|
|
467
|
+
"basecamp.comment.list"
|
|
468
|
+
]
|
|
469
|
+
},
|
|
470
|
+
{
|
|
471
|
+
"required": [
|
|
472
|
+
"basecamp.comment.post"
|
|
473
|
+
]
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
"required": [
|
|
477
|
+
"basecamp.campfire.post"
|
|
478
|
+
]
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
"required": [
|
|
482
|
+
"basecamp.people.list"
|
|
483
|
+
]
|
|
484
|
+
},
|
|
380
485
|
{
|
|
381
486
|
"required": [
|
|
382
487
|
"service.request"
|
|
@@ -461,6 +566,61 @@
|
|
|
461
566
|
"gmail.attachment.read"
|
|
462
567
|
]
|
|
463
568
|
},
|
|
569
|
+
{
|
|
570
|
+
"required": [
|
|
571
|
+
"basecamp.project.list"
|
|
572
|
+
]
|
|
573
|
+
},
|
|
574
|
+
{
|
|
575
|
+
"required": [
|
|
576
|
+
"basecamp.todolist.list"
|
|
577
|
+
]
|
|
578
|
+
},
|
|
579
|
+
{
|
|
580
|
+
"required": [
|
|
581
|
+
"basecamp.todo.list"
|
|
582
|
+
]
|
|
583
|
+
},
|
|
584
|
+
{
|
|
585
|
+
"required": [
|
|
586
|
+
"basecamp.todo.create"
|
|
587
|
+
]
|
|
588
|
+
},
|
|
589
|
+
{
|
|
590
|
+
"required": [
|
|
591
|
+
"basecamp.todo.complete"
|
|
592
|
+
]
|
|
593
|
+
},
|
|
594
|
+
{
|
|
595
|
+
"required": [
|
|
596
|
+
"basecamp.message.list"
|
|
597
|
+
]
|
|
598
|
+
},
|
|
599
|
+
{
|
|
600
|
+
"required": [
|
|
601
|
+
"basecamp.message.post"
|
|
602
|
+
]
|
|
603
|
+
},
|
|
604
|
+
{
|
|
605
|
+
"required": [
|
|
606
|
+
"basecamp.comment.list"
|
|
607
|
+
]
|
|
608
|
+
},
|
|
609
|
+
{
|
|
610
|
+
"required": [
|
|
611
|
+
"basecamp.comment.post"
|
|
612
|
+
]
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
"required": [
|
|
616
|
+
"basecamp.campfire.post"
|
|
617
|
+
]
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
"required": [
|
|
621
|
+
"basecamp.people.list"
|
|
622
|
+
]
|
|
623
|
+
},
|
|
464
624
|
{
|
|
465
625
|
"required": [
|
|
466
626
|
"warehouse.view.read"
|
|
@@ -587,6 +747,77 @@
|
|
|
587
747
|
}
|
|
588
748
|
}
|
|
589
749
|
},
|
|
750
|
+
"company-basecamp": {
|
|
751
|
+
"kind": "saas",
|
|
752
|
+
"operations": {
|
|
753
|
+
"basecamp.project.list": {
|
|
754
|
+
"identity": "user",
|
|
755
|
+
"resources": [
|
|
756
|
+
"account"
|
|
757
|
+
]
|
|
758
|
+
},
|
|
759
|
+
"basecamp.todolist.list": {
|
|
760
|
+
"identity": "user",
|
|
761
|
+
"resources": [
|
|
762
|
+
"launch"
|
|
763
|
+
]
|
|
764
|
+
},
|
|
765
|
+
"basecamp.todo.list": {
|
|
766
|
+
"identity": "user",
|
|
767
|
+
"resources": [
|
|
768
|
+
"launch"
|
|
769
|
+
]
|
|
770
|
+
},
|
|
771
|
+
"basecamp.todo.create": {
|
|
772
|
+
"identity": "user",
|
|
773
|
+
"resources": [
|
|
774
|
+
"launch"
|
|
775
|
+
]
|
|
776
|
+
},
|
|
777
|
+
"basecamp.todo.complete": {
|
|
778
|
+
"identity": "user",
|
|
779
|
+
"resources": [
|
|
780
|
+
"launch"
|
|
781
|
+
]
|
|
782
|
+
},
|
|
783
|
+
"basecamp.message.list": {
|
|
784
|
+
"identity": "user",
|
|
785
|
+
"resources": [
|
|
786
|
+
"launch"
|
|
787
|
+
]
|
|
788
|
+
},
|
|
789
|
+
"basecamp.message.post": {
|
|
790
|
+
"identity": "user",
|
|
791
|
+
"resources": [
|
|
792
|
+
"launch"
|
|
793
|
+
]
|
|
794
|
+
},
|
|
795
|
+
"basecamp.comment.list": {
|
|
796
|
+
"identity": "user",
|
|
797
|
+
"resources": [
|
|
798
|
+
"launch"
|
|
799
|
+
]
|
|
800
|
+
},
|
|
801
|
+
"basecamp.comment.post": {
|
|
802
|
+
"identity": "user",
|
|
803
|
+
"resources": [
|
|
804
|
+
"launch"
|
|
805
|
+
]
|
|
806
|
+
},
|
|
807
|
+
"basecamp.campfire.post": {
|
|
808
|
+
"identity": "user",
|
|
809
|
+
"resources": [
|
|
810
|
+
"launch"
|
|
811
|
+
]
|
|
812
|
+
},
|
|
813
|
+
"basecamp.people.list": {
|
|
814
|
+
"identity": "user",
|
|
815
|
+
"resources": [
|
|
816
|
+
"launch"
|
|
817
|
+
]
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
},
|
|
590
821
|
"sales-warehouse": {
|
|
591
822
|
"kind": "database",
|
|
592
823
|
"operations": {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
3
|
"$id": "https://schemas.harbour.dev/data-grant-v2.schema.json",
|
|
4
4
|
"title": "DataGrantV2",
|
|
5
|
-
"description": "An app's integration grant for one connection, environment and identity mode (control table sk APP#<appId>#IGRANT#<environment>#<sourceId>#<mode>; grantId = base64url(JSON [\"v2\",appId,environment,sourceId,mode])). Additive to the legacy DataGrant (data-grant.schema.json), which is never consulted by v2 paths. A fresh REQUESTED record carries empty `operations`/`resources` until the attached request is approved; approved resources are structured `{name, columns?}` entries (a Slack channel alias, the fixed Gmail `inbox` alias, or a warehouse view alias with its approved columns). Expiry is enforced from UTC time on every call and SDK calls never extend it; `expiredAt` is stamped by the recovery sweep afterwards. Status edges live in x-transitions; DENIED and REVOKED are terminal (a regrant after revocation is a new REQUESTED record once cleanup is DONE). Database grants add credentialRef/mintedPrincipal; both hold references only. An app-mode Slack grant may carry `presentation` (0.53.0): the IT-approved display name and icon the app's posts go out under, copied from the approved request and read by every post — never from the call. `identityMode` and `installation` are the deprecated 0.45.0 spellings: the record carries `mode`, and a SaaS grant runs on the connection's single installation.",
|
|
5
|
+
"description": "An app's integration grant for one connection, environment and identity mode (control table sk APP#<appId>#IGRANT#<environment>#<sourceId>#<mode>; grantId = base64url(JSON [\"v2\",appId,environment,sourceId,mode])). Additive to the legacy DataGrant (data-grant.schema.json), which is never consulted by v2 paths. A fresh REQUESTED record carries empty `operations`/`resources` until the attached request is approved; approved resources are structured `{name, columns?}` entries (a Slack channel alias, the fixed Gmail `inbox` alias, a Basecamp project alias or the fixed Basecamp `account` alias, or a warehouse view alias with its approved columns). Expiry is enforced from UTC time on every call and SDK calls never extend it; `expiredAt` is stamped by the recovery sweep afterwards. Status edges live in x-transitions; DENIED and REVOKED are terminal (a regrant after revocation is a new REQUESTED record once cleanup is DONE). Database grants add credentialRef/mintedPrincipal; both hold references only. An app-mode Slack grant may carry `presentation` (0.53.0): the IT-approved display name and icon the app's posts go out under, copied from the approved request and read by every post — never from the call. `identityMode` and `installation` are the deprecated 0.45.0 spellings: the record carries `mode`, and a SaaS grant runs on the connection's single installation.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"additionalProperties": false,
|
|
8
8
|
"required": ["schema", "tenantId", "appId", "environment", "sourceId", "mode", "kind", "status", "operations", "resources", "version", "provisioning", "createdAt", "updatedAt"],
|
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
"status": { "$ref": "#/definitions/DataGrantV2Status" },
|
|
18
18
|
"operations": {
|
|
19
19
|
"type": "array",
|
|
20
|
-
"maxItems":
|
|
20
|
+
"maxItems": 22,
|
|
21
21
|
"uniqueItems": true,
|
|
22
22
|
"items": { "$ref": "app-integrations-declaration.schema.json#/definitions/IntegrationOperation" },
|
|
23
|
-
"description": "Approved operations; each must match this grant's mode. Empty until the first approval. At most the
|
|
23
|
+
"description": "Approved operations; each must match this grant's mode. Empty until the first approval. At most the twenty-two SaaS operations (0.76.0: eleven Slack and Gmail, eleven Basecamp); a database grant holds one."
|
|
24
24
|
},
|
|
25
25
|
"resources": {
|
|
26
26
|
"type": "array",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"type": "object",
|
|
63
63
|
"additionalProperties": false,
|
|
64
64
|
"required": ["name"],
|
|
65
|
-
"description": "One approved logical resource: a channel alias, the fixed Gmail `inbox` alias, or a warehouse view alias with the approved columns.",
|
|
65
|
+
"description": "One approved logical resource: a Slack channel alias, the fixed Gmail `inbox` alias, a Basecamp project alias or the fixed Basecamp `account` alias (0.76.0), or a warehouse view alias with the approved columns.",
|
|
66
66
|
"properties": {
|
|
67
67
|
"name": { "$ref": "app-integrations-declaration.schema.json#/definitions/IntegrationAlias" },
|
|
68
68
|
"columns": {
|
|
@@ -77,13 +77,42 @@
|
|
|
77
77
|
},
|
|
78
78
|
"status": {
|
|
79
79
|
"$ref": "#/definitions/DataSourceStatus"
|
|
80
|
+
},
|
|
81
|
+
"environments": {
|
|
82
|
+
"type": "object",
|
|
83
|
+
"additionalProperties": false,
|
|
84
|
+
"properties": {
|
|
85
|
+
"development": {
|
|
86
|
+
"$ref": "#/definitions/DataSourceEnvironmentCopy"
|
|
87
|
+
},
|
|
88
|
+
"preview": {
|
|
89
|
+
"$ref": "#/definitions/DataSourceEnvironmentCopy"
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"description": "0.74.0: per-environment copies of the source. A read for an environment that has a copy here uses that copy's endpoint and credentialRef; production always uses the top-level endpoint and credentialRef. A development read with no development copy is answered from the app's sample rows (integration-execute-request.sampleRows), never from the source; a preview read with no preview copy uses the production endpoint. A laptop never reads the production endpoint."
|
|
80
93
|
}
|
|
81
94
|
},
|
|
82
95
|
"definitions": {
|
|
83
96
|
"DataSourceConnector": {
|
|
84
97
|
"type": "string",
|
|
85
|
-
"enum": ["postgres", "redshift", "bigquery", "databricks", "mysql"],
|
|
86
|
-
"description": "Closed connector set for the Data-Access MVP."
|
|
98
|
+
"enum": ["postgres", "redshift", "bigquery", "databricks", "mysql", "trino"],
|
|
99
|
+
"description": "Closed connector set for the Data-Access MVP. trino (0.74.0): Trino/Presto-compatible engines (Trino, Presto, Starburst, Galaxy) over the Trino HTTP statement protocol; the endpoint reuses host, port and database (as the Trino catalog) with no connector-specific fields."
|
|
100
|
+
},
|
|
101
|
+
"DataSourceEnvironmentCopy": {
|
|
102
|
+
"type": "object",
|
|
103
|
+
"additionalProperties": false,
|
|
104
|
+
"required": ["endpoint", "credentialRef"],
|
|
105
|
+
"properties": {
|
|
106
|
+
"endpoint": {
|
|
107
|
+
"$ref": "#/definitions/DataSourceEndpoint"
|
|
108
|
+
},
|
|
109
|
+
"credentialRef": {
|
|
110
|
+
"type": "string",
|
|
111
|
+
"pattern": "^secretref://[A-Za-z0-9][A-Za-z0-9/_.:-]*$",
|
|
112
|
+
"description": "secretref URI naming the platform-held credential for this copy. The referenced value never crosses this boundary."
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"description": "One environment's copy of a source: the same endpoint and credentialRef shapes as the top-level fields, for the same connector."
|
|
87
116
|
},
|
|
88
117
|
"DataSourceEndpoint": {
|
|
89
118
|
"type": "object",
|
|
@@ -152,6 +181,32 @@
|
|
|
152
181
|
"requestableByBuilders": true,
|
|
153
182
|
"allowValidation": false,
|
|
154
183
|
"status": "ACTIVE"
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"tenantId": "pocketfm",
|
|
187
|
+
"sourceId": "lakehouse",
|
|
188
|
+
"connector": "trino",
|
|
189
|
+
"displayName": "Lakehouse (Trino)",
|
|
190
|
+
"endpoint": {
|
|
191
|
+
"host": "trino.internal.example.com",
|
|
192
|
+
"port": 8443,
|
|
193
|
+
"database": "hive"
|
|
194
|
+
},
|
|
195
|
+
"credentialRef": "secretref://tenants/pocketfm/sources/lakehouse/reader",
|
|
196
|
+
"environments": {
|
|
197
|
+
"development": {
|
|
198
|
+
"endpoint": {
|
|
199
|
+
"host": "trino-dev.internal.example.com",
|
|
200
|
+
"port": 8443,
|
|
201
|
+
"database": "hive_dev"
|
|
202
|
+
},
|
|
203
|
+
"credentialRef": "secretref://tenants/pocketfm/sources/lakehouse/reader-dev"
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
"provisioningMode": "byo",
|
|
207
|
+
"allowedScope": ["analytics.episode_plays"],
|
|
208
|
+
"requestableByBuilders": true,
|
|
209
|
+
"status": "ACTIVE"
|
|
155
210
|
}
|
|
156
211
|
]
|
|
157
212
|
}
|
|
@@ -62,9 +62,10 @@
|
|
|
62
62
|
"AUTH_REQUIRED",
|
|
63
63
|
"UNAVAILABLE",
|
|
64
64
|
"MODE_NOT_GRANTED",
|
|
65
|
-
"MODE_REQUIRED"
|
|
65
|
+
"MODE_REQUIRED",
|
|
66
|
+
"SAMPLE_ROWS_NOT_ALLOWED"
|
|
66
67
|
],
|
|
67
|
-
"description": "Stable reason codes. SEND_OUTCOME_UNKNOWN: dispatch happened but the outcome is unknown; never re-post automatically. SEND_KEY_REUSED: the idempotency key was seen with a different payload or subject. GRANT_DENIED: IT denied the request. TOKEN_REFRESH_PENDING: another call holds the refresh lease; retry shortly. REQUEST_PENDING: a different request for this grant is still open. INPUT_INVALID: the operation input failed its bounds. IDEMPOTENCY_KEY_REQUIRED: a send without a UUID idempotencyKey. SEND_IN_PROGRESS: a retry arrived while the first send of that key is still running. CONNECTION_NOT_FOUND / APP_NOT_FOUND / GRANT_NOT_FOUND: the named record does not exist. AUTH_REQUIRED: no verified caller. UNAVAILABLE: the governance dependency (store, provider seam) is unreachable. MODE_NOT_GRANTED (403 FORBIDDEN, 0.55.0): a slack.message.post named a mode (app or user) IT has not approved for this app; the post is never served under the other mode. MODE_REQUIRED (400 VALIDATION_FAILED, 0.55.0): the app holds approved grants for both modes and the post named neither."
|
|
68
|
+
"description": "Stable reason codes. SEND_OUTCOME_UNKNOWN: dispatch happened but the outcome is unknown; never re-post automatically. SEND_KEY_REUSED: the idempotency key was seen with a different payload or subject. GRANT_DENIED: IT denied the request. TOKEN_REFRESH_PENDING: another call holds the refresh lease; retry shortly. REQUEST_PENDING: a different request for this grant is still open. INPUT_INVALID: the operation input failed its bounds. IDEMPOTENCY_KEY_REQUIRED: a send without a UUID idempotencyKey. SEND_IN_PROGRESS: a retry arrived while the first send of that key is still running. CONNECTION_NOT_FOUND / APP_NOT_FOUND / GRANT_NOT_FOUND: the named record does not exist. AUTH_REQUIRED: no verified caller. UNAVAILABLE: the governance dependency (store, provider seam) is unreachable. MODE_NOT_GRANTED (403 FORBIDDEN, 0.55.0): a slack.message.post named a mode (app or user) IT has not approved for this app; the post is never served under the other mode. MODE_REQUIRED (400 VALIDATION_FAILED, 0.55.0): the app holds approved grants for both modes and the post named neither. SAMPLE_ROWS_NOT_ALLOWED (400 VALIDATION_FAILED, 0.74.0): an execute request carried sampleRows on any route but the development one. A sample value that does not parse as the column's recorded type is INPUT_INVALID, naming the column and the row."
|
|
68
69
|
}
|
|
69
70
|
},
|
|
70
71
|
"examples": [
|