@fourier-labs/harbour-contracts 0.47.0 → 0.50.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 +29 -3
- package/contract-release.json +21 -21
- package/dist/gen-ts/app-integrations-declaration.d.ts +1 -0
- 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 +1 -1
- package/dist/gen-ts/integration-execute-request.d.ts +40 -4
- package/dist/gen-ts/integration-execute-result.d.ts +1 -1
- package/dist/gen-ts/saas-connection.d.ts +3 -3
- package/dist/gen-ts/transform-report.d.ts +2 -0
- package/dist/gen-ts/well-defined-app-manifest.d.ts +31 -0
- package/gen-ts/app-integrations-declaration.ts +1 -0
- package/gen-ts/contract-release.ts +6 -6
- package/gen-ts/data-grant-v2.ts +6 -1
- package/gen-ts/integration-execute-request.ts +45 -4
- package/gen-ts/integration-execute-result.ts +1 -1
- package/gen-ts/saas-connection.ts +8 -3
- package/gen-ts/transform-report.ts +2 -0
- package/gen-ts/well-defined-app-manifest.ts +31 -0
- package/package.json +1 -1
- package/schema/app-integrations-declaration.schema.json +6 -4
- package/schema/integration-execute-request.schema.json +33 -8
- package/schema/integration-execute-result.schema.json +3 -1
- package/schema/saas-connection.schema.json +3 -3
- package/schema/transform-report.schema.json +2 -1
- package/schema/well-defined-app-manifest.schema.json +61 -0
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ exist here first.
|
|
|
25
25
|
| `error-envelope.schema.json` | The failure envelope emitted once per FAILED transition | §2.1 |
|
|
26
26
|
| `error-category.enum.json` | Closed failure-category enum + per-category `retryable` registry | §2.2 |
|
|
27
27
|
| `artifact-contract.schema.json` | Build output contract (the provider-portability seam), including the digest-pinned well-defined app manifest reference | §3 |
|
|
28
|
-
| `well-defined-app-manifest.schema.json` | Versioned runtime wiring for static, full-stack, and browser-first apps: workloads, schedules, queues,
|
|
28
|
+
| `well-defined-app-manifest.schema.json` | Versioned runtime wiring for static, full-stack, and browser-first apps: workloads, schedules, queues, service bindings, language runtime, browser capabilities, and route authentication | Well-defined apps P0 |
|
|
29
29
|
| `version-state.schema.json` | State machine T1a — states, legal transitions, versionId format | §1 |
|
|
30
30
|
| `env-bindings.schema.json` | `EnvBindings` / `Target` / `Binding` (BYOC-complete) | §4.2.2 |
|
|
31
31
|
| `kvs-routing-entry.schema.json` | CloudFront KVS routing value (`{static, api}`) | §8 |
|
|
@@ -42,6 +42,32 @@ exist here first.
|
|
|
42
42
|
| `integration-execute-request`, `integration-execute-result`, `integration-connect-result`, `integration-error-details` | App SDK integrations wire contract on `/_harbour/integrations/*`: per-operation input bounds, the five result shapes, consent states and the closed `details.code` reason set | Dev kit §4, §8 |
|
|
43
43
|
| `saas-connection.schema.json`, `data-grant-v2.schema.json` | Tenant SaaS connection record (one installation and channel map per tenant and provider) and the additive `harbour.data-grant/2.0` grant record with structured resources and provisioning lease/cleanup (status machine generated; legacy `data-grant` untouched) | Dev kit §5 |
|
|
44
44
|
| `kit-bundle-manifest.schema.json`, `kit-lock.schema.json` | Published kit bundle identity (SDK tarball digest plus optional `sdk.version` and https `sdk.url` download location) and the committed `.harbour/kit.lock.json` the CodeBuild SDK-vendoring gate compares against | Dev kit §3 |
|
|
45
|
+
| `deploy-response.schema.json` | 202 Accepted body for `POST /v1/tenants/{tenant}/apps/{app}/deployments`, returned only after the authoritative QUEUED version exists and its SQS message is accepted | — |
|
|
46
|
+
| `deployment-source.schema.json` | Credential-free GitHub source in the `DeployRequest` body; credentials are resolved internally by MaterializeSource | — |
|
|
47
|
+
| `deployment-environment.schema.json` | Public environment accepted by the preview APIs (`preview` only; production is reachable only through promotion) | — |
|
|
48
|
+
| `api-error-response.schema.json` | Safe JSON error body for Deploy/Status Lambda 4xx/5xx responses; distinct from the internal `ErrorEnvelope` | — |
|
|
49
|
+
| `deployment-status-request.schema.json` | Validated path parameters for `GET /v1/tenants/{tenant}/apps/{app}/deployments/{versionId}` | — |
|
|
50
|
+
| `deployment-status-response.schema.json` | 200 OK body for GET status: that exact immutable version, with the `progress` trail, `deployTarget` and `diagnosticRef` | — |
|
|
51
|
+
| `deployment-status-failure.schema.json` | Frontend-safe failure projection nested in a failed status response; a digest-bound `diagnosticRef` locates the redacted diagnostic | — |
|
|
52
|
+
| `promotion-request.schema.json` | Body for `POST /v1/tenants/{tenant}/apps/{app}/promotions`; repository identity comes from stored records, not the caller | ADR 0003 |
|
|
53
|
+
| `promotion-response.schema.json` | 202 Accepted body returned once the production version and its durable idempotency binding exist | ADR 0003 |
|
|
54
|
+
| `transform-report.schema.json` | Structured output an agent must return from one transformation attempt; handed to the agent as its output schema and re-validated by the control plane | — |
|
|
55
|
+
| `transform-parked-result.schema.json` | Sequential-preview result after a durable checkpoint when builder input is required; not a successful report | — |
|
|
56
|
+
| `builder-input-proposal.schema.json` | Value-free proposal emitted when sequential preview cannot continue without builder-owned input | — |
|
|
57
|
+
| `deployment-continuation.schema.json` | Immutable reference admitting one child deployment from a parked input request; never credential values | — |
|
|
58
|
+
| `security-scan-input.schema.json` | Input to the Security Assurance machine: SOURCE (M1) scans an ingested commit, ARTIFACT (M2) scans built outputs | Security Assurance §2 |
|
|
59
|
+
| `security-verdict.schema.json` | Security Assurance decision; `BLOCKED` surfaces as the non-retryable `gate.security-scan` category | Security Assurance §2 |
|
|
60
|
+
| `data-source.schema.json` | Admin-registered external data source; `credentialRef` is a secretref URI and the credential never crosses this boundary | Data-Access MVP |
|
|
61
|
+
| `data-dependency.schema.json` | One external data dependency of an app, declared or detected, classified against the tenant's data-source inventory | Data-Access MVP |
|
|
62
|
+
| `secret-reference.schema.json` | Named secret slot an app depends on; only the reference and its lifecycle cross, never the value | Secret-Manager MVP |
|
|
63
|
+
| `ai-callsite-inventory.schema.json` | Immutable, sanitized AI call-site discovery for one exact deployment version (detection only) | AI governance |
|
|
64
|
+
| `ai-runtime-contract.schema.json` | Immutable runtime contract derived by an AI Governance PLAN decision; scoped configuration plus a Secrets Manager reference | AI governance |
|
|
65
|
+
| `ai-policy-snapshot.schema.json` | Immutable, content-addressed AI policy snapshot consumed by the AI Gateway | AI governance |
|
|
66
|
+
| `ai-gateway-key-lookup.schema.json` | Value-free Gateway authentication metadata for one version-scoped Harbour key | AI governance |
|
|
67
|
+
| `ai-trace-event.schema.json` | Value-free asynchronous AI Gateway trace metadata (v1); raw prompts and responses never enter the queue | AI governance |
|
|
68
|
+
| `ai-transform-event.schema.json` | Checksum-bound deterministic AI interception task input carrying the ordered PLAN interception plan | AI governance |
|
|
69
|
+
| `ai-transform-result.schema.json` | Bounded deterministic interception result: descriptors and digest evidence only | AI governance |
|
|
70
|
+
| `ai-verification-evidence.schema.json` | Bounded, value-free evidence submitted by deployment verification for one governed version | AI governance |
|
|
45
71
|
|
|
46
72
|
Runtime resource profiles are a closed contract shared by transformation, artifacts, and
|
|
47
73
|
well-defined application manifests. The supported profiles are `standard`, `memory-1g`, and
|
|
@@ -111,7 +137,7 @@ consumer cutover evidence.
|
|
|
111
137
|
|
|
112
138
|
## Consuming
|
|
113
139
|
|
|
114
|
-
- **Go:** `go get github.com/Fourier-Labs-AI/harbour-contracts/gen-go@v0.
|
|
140
|
+
- **Go:** `go get github.com/Fourier-Labs-AI/harbour-contracts/gen-go@v0.50.0`
|
|
115
141
|
|
|
116
142
|
Two things make this work, and the second is not the obvious one.
|
|
117
143
|
|
|
@@ -148,7 +174,7 @@ consumer cutover evidence.
|
|
|
148
174
|
Without the above, `go get` fails with `Repository not found` — which reads as a
|
|
149
175
|
missing tag, not as missing access.
|
|
150
176
|
|
|
151
|
-
- **TS:** `npm i @fourier-labs/harbour-contracts` — published from the tag by CI.
|
|
177
|
+
- **TS:** `npm i @fourier-labs/harbour-contracts` — published from the tag by CI. The hand-written AI policy resolver (`resolver/index.ts`) ships in the same package as the `@fourier-labs/harbour-contracts/resolver` subpath export (`package.json` `exports`).
|
|
152
178
|
|
|
153
179
|
## Notes
|
|
154
180
|
|
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.50.0.0",
|
|
4
|
+
"publishVersion": "0.50.0",
|
|
5
|
+
"publishTag": "v0.50.0",
|
|
6
|
+
"schemasDigest": "sha256:c77dcbf9daad9c66141e9cb8215760a098afd1bf3e665e247f6a4df8db2bcd4f",
|
|
7
7
|
"aiFixturesDigest": "sha256:edac31c92e146ca1c40130f2fb5649db82e24b8cd1ac758153b90612052fddb6",
|
|
8
|
-
"generatedGoDigest": "sha256:
|
|
9
|
-
"generatedTypeScriptDigest": "sha256:
|
|
8
|
+
"generatedGoDigest": "sha256:545d8b23ab712e75285ea962851bcf8f08f5baeb018bea6f7ba4e1ca2fe80ed0",
|
|
9
|
+
"generatedTypeScriptDigest": "sha256:1e47c3956a3468531690693ff50ff7947a798af01e01d25659401f727cb934c4",
|
|
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)"
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"schema/ai-transform-result.schema.json": "sha256:244e380a36957ab2dcb526ea22aaecb56b53664ce1fda6934d0021c084c99133",
|
|
32
32
|
"schema/ai-verification-evidence.schema.json": "sha256:bdbc762df256d2a8dd0bdda60d4d13915ce40034cd756af9515871d145f10ad9",
|
|
33
33
|
"schema/api-error-response.schema.json": "sha256:3d43d5bdf0b59c944e20509d832e6776c3ecdba4d6c245a9118bbe52062a8304",
|
|
34
|
-
"schema/app-integrations-declaration.schema.json": "sha256:
|
|
34
|
+
"schema/app-integrations-declaration.schema.json": "sha256:1a6ac2e7d77a4d4dcbce8b937747f125081413f819ffee9e27e8b950a436cb22",
|
|
35
35
|
"schema/artifact-contract.schema.json": "sha256:8047b461a1c6d07bbe867a259c57bdf5cc0fdf282cf842ec7b683a9e93713b10",
|
|
36
36
|
"schema/binding-classification-subject.schema.json": "sha256:a8825ce652e7e00a18759c4249bd5bcd0cae552dd58440513f867e87f685133c",
|
|
37
37
|
"schema/builder-input-proposal.schema.json": "sha256:fe85cffa6d76b1e1effe1f5d75525f8fe0e1eaa3be4a304e491aa23ad72c0e72",
|
|
@@ -52,22 +52,22 @@
|
|
|
52
52
|
"schema/error-envelope.schema.json": "sha256:75dccda7dd16fdf8435deda53fc7dbcdc109b65114617a17f11763010c656f90",
|
|
53
53
|
"schema/integration-connect-result.schema.json": "sha256:3f254b67ef739dc1fa395bdc8c4dc93359b16d481dba2a2d777aa5b6f34b7af8",
|
|
54
54
|
"schema/integration-error-details.schema.json": "sha256:09cebaddb7f88e63cbebaa1cada5f91057ae4dc4370e973ef38f7f11c6323284",
|
|
55
|
-
"schema/integration-execute-request.schema.json": "sha256:
|
|
56
|
-
"schema/integration-execute-result.schema.json": "sha256:
|
|
55
|
+
"schema/integration-execute-request.schema.json": "sha256:658eb66a15bba4fc81eec208c713d5d141d159a6429306909304d5182f728bec",
|
|
56
|
+
"schema/integration-execute-result.schema.json": "sha256:766146779c01ee1dbdd2161c5dc594f43ccaf322762352bb0dc5b80bcb3275b5",
|
|
57
57
|
"schema/kit-bundle-manifest.schema.json": "sha256:c15e28ae028dbd1c262427b9c797142e19b1f38fa36b4ecfe187e32c20a174ec",
|
|
58
58
|
"schema/kit-lock.schema.json": "sha256:5e24b76660f83990af7a6c037af350c3850ee439ef956f65a0360facbdcdd997",
|
|
59
59
|
"schema/kvs-routing-entry.schema.json": "sha256:b75f3a5dfa93a428b2764e03222b66b6ef2bed980f8bac8ffac54afdf3526bc5",
|
|
60
60
|
"schema/promotion-request.schema.json": "sha256:00e96dfd8ddbdba88ea222941d43f3609ff6c815a79e34f6705cab458101c969",
|
|
61
61
|
"schema/promotion-response.schema.json": "sha256:4129712d2e29d6ef21d93d4bd0bacfd60ada3f2ee0ade852824e64346b817634",
|
|
62
|
-
"schema/saas-connection.schema.json": "sha256:
|
|
62
|
+
"schema/saas-connection.schema.json": "sha256:fa62fc6e28124120c71ebc36e257263ba8820d48b7d505d54ac53bd812fdd9ee",
|
|
63
63
|
"schema/sanitized-binding-evidence.schema.json": "sha256:1191ab88e2764df927e5f17837674cebebe068d480da2b2fdb390e589f96b51f",
|
|
64
64
|
"schema/secret-reference.schema.json": "sha256:db4e3c2c6a2dbd72d7ea0f9c91cb3b2343a7e67b601996c6818b2ef08e440895",
|
|
65
65
|
"schema/security-scan-input.schema.json": "sha256:83502dffb3c07ac2e0698928e6dc123f454fc667d4aacd336bcad6944ef2ac3d",
|
|
66
66
|
"schema/security-verdict.schema.json": "sha256:ec3c2d5c9df3601aeed0909b36c7f427469c7f0eeb3295c5809b96d09bf3fc26",
|
|
67
67
|
"schema/transform-parked-result.schema.json": "sha256:11729980d4c89d4a9e18f5f213232cd3359739c85626b36c20c2a37ba794c9af",
|
|
68
|
-
"schema/transform-report.schema.json": "sha256:
|
|
68
|
+
"schema/transform-report.schema.json": "sha256:858da48fa7fe97d8d06267bb3435d71ba307133b246cb020f5b473bb488c445a",
|
|
69
69
|
"schema/version-state.schema.json": "sha256:3b190007e2f8e3821c41ef11c6f5b226da7d5a18d34d4077f4618004846fd444",
|
|
70
|
-
"schema/well-defined-app-manifest.schema.json": "sha256:
|
|
70
|
+
"schema/well-defined-app-manifest.schema.json": "sha256:40f1bfea912dd85a05a0a3be2f6becadaf8ae3c5de9d5782ff1c8dd1bd83485f"
|
|
71
71
|
},
|
|
72
72
|
"aiFixtures": {
|
|
73
73
|
"fixtures/ai/adversarial-binding-classification-value.json": "sha256:ca009f3f6162a9d93b4ab416d52c1fba12a8a15aca5aed956c5fdcf2171b1e28",
|
|
@@ -105,8 +105,8 @@
|
|
|
105
105
|
"gen-go/contracts_test.go": "sha256:56376287cb1548be1b35ab4c65d6f0b558c5d34885f7a47cb3d9e8d786607bf5",
|
|
106
106
|
"gen-go/doc.go": "sha256:c17bc2d39ed175ce7105c68305f8ae7152f659eb7cd187ecceee7698eb3a65dd",
|
|
107
107
|
"gen-go/error_category.go": "sha256:b2ddea22dcfa030f1a45e721e635485b0bd816cf1f38e7654628a653f5ed4583",
|
|
108
|
-
"gen-go/schema_documents.go": "sha256:
|
|
109
|
-
"gen-go/types.go": "sha256:
|
|
108
|
+
"gen-go/schema_documents.go": "sha256:66055e0d4354f73d922ee17984de8df065db665f93182b87fcd8a6a94ae94300",
|
|
109
|
+
"gen-go/types.go": "sha256:07429b30905aacfdb95ca9ddea5ae04e3cc7fcc89e69b84f05f2833f4b8339be",
|
|
110
110
|
"gen-go/version_state.go": "sha256:4ef8abb126414c0025cf2c59bc9c79a74ef4a2ff89e8f316cbf05acc872371c1"
|
|
111
111
|
},
|
|
112
112
|
"generatedTypeScript": {
|
|
@@ -131,13 +131,13 @@
|
|
|
131
131
|
"gen-ts/ai-transform-result.ts": "sha256:208c66b2aeb425c0cbcc18b7191f6e8989443f2b2c1690648e0e06cc1448ce25",
|
|
132
132
|
"gen-ts/ai-verification-evidence.ts": "sha256:979439d77f8b47631d1eb3b6c3c54ea6fec41089d2a51dc815fd370b1c4917fc",
|
|
133
133
|
"gen-ts/api-error-response.ts": "sha256:0fd73be282e7a5d72d6c343a4e64d09c232556b16161167f0cffd6278ed7e3d3",
|
|
134
|
-
"gen-ts/app-integrations-declaration.ts": "sha256:
|
|
134
|
+
"gen-ts/app-integrations-declaration.ts": "sha256:aabebdbffc70dd87017f1c72e0b8713f9cef506ba5258279b3a1405185875141",
|
|
135
135
|
"gen-ts/artifact-contract.ts": "sha256:4a6dc6d2caaeed4bb2066cc8a333e6e09e5a0d4745e0b1038293d54ab9403aeb",
|
|
136
136
|
"gen-ts/binding-classification-digest-helper.ts": "sha256:40fc7d85b4c3f3ffc5caf7d7950c62d013c83ee42058c7453b2100d95817f167",
|
|
137
137
|
"gen-ts/binding-classification-subject.ts": "sha256:c409a3fd7b942b50419632c51d9a79474fb30d6374bdc79c0e25c73618e800c3",
|
|
138
138
|
"gen-ts/builder-input-proposal.ts": "sha256:b0108c3787873d3cf1a39f00967379418a6766275d3474cfa55f5a9d93ead174",
|
|
139
139
|
"gen-ts/data-dependency.ts": "sha256:0572c31d7ae9088eccc104eee1a205bf176d1d6dacfaf0f290d666024e284966",
|
|
140
|
-
"gen-ts/data-grant-v2.ts": "sha256:
|
|
140
|
+
"gen-ts/data-grant-v2.ts": "sha256:d55491e8d1a73d8999a43904344760de9c6eb2ce500b1e942d49261a9c67808f",
|
|
141
141
|
"gen-ts/data-grant.ts": "sha256:2358579d8aa1e57b01a6f2b0eacce5531e7f21ef226404c9809925365e0d6155",
|
|
142
142
|
"gen-ts/data-source.ts": "sha256:77d6bb3b0eaa355789c5d97dd1f548734add6950329dc69549350b8d17c8d582",
|
|
143
143
|
"gen-ts/deploy-request.ts": "sha256:0214faa8be6680f0bfc117d5ce67c1a59fcc18bd0ea4bc840e03e7d051fa9ab6",
|
|
@@ -155,23 +155,23 @@
|
|
|
155
155
|
"gen-ts/index.ts": "sha256:982599819309370072af19f1c248a033c13b17a6ee9006272d3436ab87b0db21",
|
|
156
156
|
"gen-ts/integration-connect-result.ts": "sha256:4b10f169b6e1af364e9b418de21caa9fadbfb77b43cbff77d741cfae0b52180c",
|
|
157
157
|
"gen-ts/integration-error-details.ts": "sha256:8243f5871f376d1cab4d90e07f3151d148fb03c704168dbccdfe6c9fe76bce83",
|
|
158
|
-
"gen-ts/integration-execute-request.ts": "sha256:
|
|
159
|
-
"gen-ts/integration-execute-result.ts": "sha256:
|
|
158
|
+
"gen-ts/integration-execute-request.ts": "sha256:d884e8368a5c4b8495312733fac3d28870a2cd48453c8f69e92a5d50273df516",
|
|
159
|
+
"gen-ts/integration-execute-result.ts": "sha256:4aaf6a9688f9dfdbc87a408556b62f822518acf5b76548076adb55393c0863b4",
|
|
160
160
|
"gen-ts/kit-bundle-manifest.ts": "sha256:9041b32af3df781ca6800bc14c3719e5e54c81dff370633454ac3ad27432eb58",
|
|
161
161
|
"gen-ts/kit-lock.ts": "sha256:de4ae82bac7bd234a3230ae671962e80eed6542d695a032a442673659dc6be5e",
|
|
162
162
|
"gen-ts/kvs-routing-entry.ts": "sha256:d92e85ee9f257d77850d1d3aac9438e2055f38084ff84a48fcedae239d47d4ca",
|
|
163
163
|
"gen-ts/promotion-request.ts": "sha256:9db88cef67f777a16bac628039ec3f582acb9e8cfff6fb592b30d0a0e55abc68",
|
|
164
164
|
"gen-ts/promotion-response.ts": "sha256:f1c9cafac96faeb02a443a31786f67714e818f38d90108e7af41958396524d6f",
|
|
165
|
-
"gen-ts/saas-connection.ts": "sha256:
|
|
165
|
+
"gen-ts/saas-connection.ts": "sha256:62b5c5ffd125099bae46142013461c9ac3f75c2d27ab72cd4842a937f3e2f308",
|
|
166
166
|
"gen-ts/sanitized-binding-digest-helper.ts": "sha256:c47d7fdc20500e2e72c23fe39ecdd610fc397c47fcba51335ebec3c380fe6872",
|
|
167
167
|
"gen-ts/sanitized-binding-evidence.ts": "sha256:f3fb7b1d7d2e0929eb0ea981eaf32db3104010647185f6ae59f67167d42538a9",
|
|
168
168
|
"gen-ts/secret-reference.ts": "sha256:731fbcde7315cb4128d5b01bdbe6e6f248f13c7ad8dea04a3a4e927ac4890198",
|
|
169
169
|
"gen-ts/security-scan-input.ts": "sha256:b31f048be04c34b40f49d3b3ba53277e473cd435ae9216ba3a3b4dac69fb5685",
|
|
170
170
|
"gen-ts/security-verdict.ts": "sha256:fea950cddbd12fe0218e2573c9a29c6748d56612a464559f1e6d688fa97f68c7",
|
|
171
171
|
"gen-ts/transform-parked-result.ts": "sha256:6279e27cee8d75c29f3ede45580fef1daa0ca300867a78e43ead8a7689ec613f",
|
|
172
|
-
"gen-ts/transform-report.ts": "sha256:
|
|
172
|
+
"gen-ts/transform-report.ts": "sha256:005a10b34b89f055c3aae4bf54c095bbca7a9e15bd9b406b61a9eaafffc37a61",
|
|
173
173
|
"gen-ts/version-state-machine.ts": "sha256:c67af3e86ac306743345b850dfd3ae5201c19d10c40e2c149cf8c38258320d5f",
|
|
174
174
|
"gen-ts/version-state.ts": "sha256:a835112930299e7b593a1b8810b7414f6c9e809da2092306c743128170a3b702",
|
|
175
|
-
"gen-ts/well-defined-app-manifest.ts": "sha256:
|
|
175
|
+
"gen-ts/well-defined-app-manifest.ts": "sha256:2b72a39c2fa8e76239634d0478dc0da05446e74e944950eacf999b78876455c6"
|
|
176
176
|
}
|
|
177
177
|
}
|
|
@@ -28,6 +28,7 @@ export interface DeclaredConnection {
|
|
|
28
28
|
'slack.message.post'?: AppModeChannelOperation;
|
|
29
29
|
'gmail.thread.list'?: UserModeChannelOperation;
|
|
30
30
|
'gmail.message.read'?: UserModeChannelOperation;
|
|
31
|
+
'gmail.message.send'?: UserModeChannelOperation;
|
|
31
32
|
'warehouse.view.read'?: AppModeViewOperation;
|
|
32
33
|
};
|
|
33
34
|
}
|
|
@@ -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.50.0.0";
|
|
2
|
+
export declare const ContractPublishVersion: "0.50.0";
|
|
3
|
+
export declare const ContractPublishTag: "v0.50.0";
|
|
4
|
+
export declare const ContractSchemasDigest: "sha256:c77dcbf9daad9c66141e9cb8215760a098afd1bf3e665e247f6a4df8db2bcd4f";
|
|
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:545d8b23ab712e75285ea962851bcf8f08f5baeb018bea6f7ba4e1ca2fe80ed0";
|
|
7
|
+
export declare const ContractGeneratedTypeScriptDigest: "sha256:1e47c3956a3468531690693ff50ff7947a798af01e01d25659401f727cb934c4";
|
|
@@ -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.50.0.0";
|
|
4
|
+
export const ContractPublishVersion = "0.50.0";
|
|
5
|
+
export const ContractPublishTag = "v0.50.0";
|
|
6
|
+
export const ContractSchemasDigest = "sha256:c77dcbf9daad9c66141e9cb8215760a098afd1bf3e665e247f6a4df8db2bcd4f";
|
|
7
7
|
export const ContractAiFixturesDigest = "sha256:edac31c92e146ca1c40130f2fb5649db82e24b8cd1ac758153b90612052fddb6";
|
|
8
|
-
export const ContractGeneratedGoDigest = "sha256:
|
|
9
|
-
export const ContractGeneratedTypeScriptDigest = "sha256:
|
|
8
|
+
export const ContractGeneratedGoDigest = "sha256:545d8b23ab712e75285ea962851bcf8f08f5baeb018bea6f7ba4e1ca2fe80ed0";
|
|
9
|
+
export const ContractGeneratedTypeScriptDigest = "sha256:1e47c3956a3468531690693ff50ff7947a798af01e01d25659401f727cb934c4";
|
|
@@ -33,7 +33,7 @@ export interface DataGrantV2 {
|
|
|
33
33
|
*
|
|
34
34
|
* @maxItems 5
|
|
35
35
|
*/
|
|
36
|
-
operations: ('slack.channel.history' | 'slack.message.post' | 'gmail.thread.list' | 'gmail.message.read' | 'warehouse.view.read')[];
|
|
36
|
+
operations: ('slack.channel.history' | 'slack.message.post' | 'gmail.thread.list' | 'gmail.message.read' | 'gmail.message.send' | 'warehouse.view.read')[];
|
|
37
37
|
/**
|
|
38
38
|
* Approved logical resources. Never inherited by wildcard. Empty until the first approval.
|
|
39
39
|
*
|
|
@@ -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 NOT a caller field: it is fixed by the operation and enforced from the approved grant; any identity/userId/scope field is rejected by additionalProperties. Per-operation input bounds: slack.channel.history {limit? 1..15, default 15}; slack.message.post {text 1..4000 chars} and a required idempotencyKey retained across retries of one explicit Send; gmail.thread.list {limit? 1..15, default 15}; gmail.message.read {messageId}; warehouse.view.read {columns 1..32, limit? 1..1000, default 100}. Transport limits (not expressible here): request <= 16 KiB, 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 NOT a caller field: it is fixed by the operation and enforced from the approved grant; any identity/userId/scope field is rejected by additionalProperties. Per-operation input bounds: slack.channel.history {limit? 1..15, default 15}; slack.message.post {text 1..4000 chars} and a required idempotencyKey retained across retries of one explicit Send; gmail.thread.list {limit? 1..15, default 15}; gmail.message.read {messageId}; gmail.message.send {to 1..50 addresses (to+cc+bcc <= 50 in total), cc?, bcc?, subject 1..256 chars, text 1..4000 chars, replyToMessageId?} and a required idempotencyKey like slack.message.post (plain text only, no attachments); warehouse.view.read {columns 1..32, limit? 1..1000, default 100}. Transport limits (not expressible here): request <= 16 KiB, total deadline 10 s.
|
|
3
3
|
*/
|
|
4
4
|
export type IntegrationExecuteRequest = {
|
|
5
5
|
/**
|
|
@@ -7,9 +7,9 @@ export type IntegrationExecuteRequest = {
|
|
|
7
7
|
*/
|
|
8
8
|
connection: string;
|
|
9
9
|
/**
|
|
10
|
-
* Closed operation set. Extending it is a contracts change.
|
|
10
|
+
* Closed operation set. Extending it is a contracts change. gmail.message.send (0.50.0) sends one plain-text email as the signed-in person: a send like slack.message.post (explicit Send, idempotencyKey, write receipt) under user identity.
|
|
11
11
|
*/
|
|
12
|
-
operation: 'slack.channel.history' | 'slack.message.post' | 'gmail.thread.list' | 'gmail.message.read' | 'warehouse.view.read';
|
|
12
|
+
operation: 'slack.channel.history' | 'slack.message.post' | 'gmail.thread.list' | 'gmail.message.read' | 'gmail.message.send' | 'warehouse.view.read';
|
|
13
13
|
/**
|
|
14
14
|
* Tenant-wide logical alias of a connection (governance sourceId) or of a resource under it.
|
|
15
15
|
*/
|
|
@@ -21,6 +21,17 @@ export type IntegrationExecuteRequest = {
|
|
|
21
21
|
* gmail.message.read: the Gmail message id a gmail.thread.list result named.
|
|
22
22
|
*/
|
|
23
23
|
messageId?: string;
|
|
24
|
+
to?: EmailAddressList;
|
|
25
|
+
cc?: EmailAddressList1;
|
|
26
|
+
bcc?: EmailAddressList2;
|
|
27
|
+
/**
|
|
28
|
+
* gmail.message.send: one-line subject (no line breaks).
|
|
29
|
+
*/
|
|
30
|
+
subject?: string;
|
|
31
|
+
/**
|
|
32
|
+
* gmail.message.send: a Gmail message id (from gmail.thread.list / gmail.message.read) the email replies to; the send joins that thread.
|
|
33
|
+
*/
|
|
34
|
+
replyToMessageId?: string;
|
|
24
35
|
/**
|
|
25
36
|
* @minItems 1
|
|
26
37
|
* @maxItems 32
|
|
@@ -28,7 +39,32 @@ export type IntegrationExecuteRequest = {
|
|
|
28
39
|
columns?: string[];
|
|
29
40
|
};
|
|
30
41
|
/**
|
|
31
|
-
* UUID of one explicit Send action; required for slack.message.post only. The same key with the same payload and subject returns the recorded outcome for seven days.
|
|
42
|
+
* 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.
|
|
32
43
|
*/
|
|
33
44
|
idempotencyKey?: string;
|
|
34
45
|
};
|
|
46
|
+
/**
|
|
47
|
+
* One bare email address (no display name).
|
|
48
|
+
*/
|
|
49
|
+
export type EmailAddress = string;
|
|
50
|
+
/**
|
|
51
|
+
* gmail.message.send: primary recipients.
|
|
52
|
+
*
|
|
53
|
+
* @minItems 1
|
|
54
|
+
* @maxItems 50
|
|
55
|
+
*/
|
|
56
|
+
export type EmailAddressList = EmailAddress[];
|
|
57
|
+
/**
|
|
58
|
+
* gmail.message.send: carbon-copy recipients.
|
|
59
|
+
*
|
|
60
|
+
* @minItems 1
|
|
61
|
+
* @maxItems 50
|
|
62
|
+
*/
|
|
63
|
+
export type EmailAddressList1 = EmailAddress[];
|
|
64
|
+
/**
|
|
65
|
+
* gmail.message.send: blind-copy recipients.
|
|
66
|
+
*
|
|
67
|
+
* @minItems 1
|
|
68
|
+
* @maxItems 50
|
|
69
|
+
*/
|
|
70
|
+
export type EmailAddressList2 = EmailAddress[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The `data` member of a successful execute response `{data, requestId}`; the SDK unwraps `data`. Exactly one of the
|
|
2
|
+
* The `data` member of a successful execute response `{data, requestId}`; the SDK unwraps `data`. Exactly one of the six operation results: slack.channel.history -> {messages, hasMore} (plain text/IDs/time only, never the provider payload); slack.message.post -> {messageId}; gmail.thread.list -> {threads, hasMore} (newest inbox threads; each `messageId` is the thread's newest message, what gmail.message.read takes); gmail.message.read -> {id, threadId, subject, from, to, date, text, truncated} (headers plus the plain text with html stripped, cut at 16 KiB with `truncated` set); gmail.message.send -> {messageId, threadId} (the Gmail ids of the sent message and its thread); warehouse.view.read -> {rows} (decimal/64-bit values as strings, dates as ISO strings). An unknown send outcome is never a result; it is an error with details.code SEND_OUTCOME_UNKNOWN. Results over 1 MiB are rejected, not truncated.
|
|
3
3
|
*/
|
|
4
4
|
export type IntegrationExecuteResult = {
|
|
5
5
|
/**
|
|
@@ -39,12 +39,12 @@ export interface SaasConnection {
|
|
|
39
39
|
[k: string]: string;
|
|
40
40
|
};
|
|
41
41
|
/**
|
|
42
|
-
* Operations IT allows apps to request on this connection: the provider's own SaaS operations (Slack: slack.channel.history, slack.message.post; Gmail: gmail.thread.list, gmail.message.read). Never warehouse.view.read.
|
|
42
|
+
* Operations IT allows apps to request on this connection: the provider's own SaaS operations (Slack: slack.channel.history, slack.message.post; Gmail: gmail.thread.list, gmail.message.read, gmail.message.send). Never warehouse.view.read.
|
|
43
43
|
*
|
|
44
44
|
* @minItems 1
|
|
45
|
-
* @maxItems
|
|
45
|
+
* @maxItems 5
|
|
46
46
|
*/
|
|
47
|
-
operations: ('slack.channel.history' | 'slack.message.post' | 'gmail.thread.list' | 'gmail.message.read' | 'warehouse.view.read')[];
|
|
47
|
+
operations: ('slack.channel.history' | 'slack.message.post' | 'gmail.thread.list' | 'gmail.message.read' | 'gmail.message.send' | 'warehouse.view.read')[];
|
|
48
48
|
developmentPreapproval: DevelopmentPreapproval;
|
|
49
49
|
/**
|
|
50
50
|
* Lower-cased builder emails excluded from development preapproval.
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export type TransformReport = {
|
|
5
5
|
/**
|
|
6
|
+
* Optional self-report of the playbooks the agent says it applied. A claim about its own behaviour is not evidence, so nothing validates it; a deployable report may omit it, and one that still carries it stays valid.
|
|
7
|
+
*
|
|
6
8
|
* @minItems 1
|
|
7
9
|
*/
|
|
8
10
|
applied_playbooks?: string[];
|
|
@@ -15,6 +15,7 @@ export type Workload = {
|
|
|
15
15
|
*/
|
|
16
16
|
export type Command = string[];
|
|
17
17
|
export type ResourceProfile = 'standard' | 'memory-1g' | 'memory-2g';
|
|
18
|
+
export type Capability = 'data' | 'files' | 'actions' | 'realtime' | 'telemetry';
|
|
18
19
|
/**
|
|
19
20
|
* Versioned provisioning input emitted by Harbour Transform. It describes runtime wiring and workload lifecycle only; PostgreSQL grants and RLS remain the database authorization authority.
|
|
20
21
|
*/
|
|
@@ -33,6 +34,17 @@ export interface WellDefinedAppManifest {
|
|
|
33
34
|
* @maxItems 128
|
|
34
35
|
*/
|
|
35
36
|
bindings: WorkloadBinding[];
|
|
37
|
+
/**
|
|
38
|
+
* Optional language runtime the application container is built on, spelled exactly as transform-report.application.runtime does (nodejs22, python3.11). Optional so a manifest written before the producer emits it still validates.
|
|
39
|
+
*/
|
|
40
|
+
runtime?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Optional declaration of the Harbour browser capabilities the application uses. Same closed set as the app-capabilities document; this is the declaration, not a source scan.
|
|
43
|
+
*
|
|
44
|
+
* @maxItems 5
|
|
45
|
+
*/
|
|
46
|
+
capabilities?: Capability[];
|
|
47
|
+
routeAuth?: RouteAuth;
|
|
36
48
|
}
|
|
37
49
|
export interface QueueConsumer {
|
|
38
50
|
logicalName: string;
|
|
@@ -64,3 +76,22 @@ export interface WorkloadBinding {
|
|
|
64
76
|
*/
|
|
65
77
|
reference?: string;
|
|
66
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* Optional method/path authentication policy. Omitted means every route requires Harbour SSO, the same default the policy states explicitly.
|
|
81
|
+
*/
|
|
82
|
+
export interface RouteAuth {
|
|
83
|
+
default: 'sso_required';
|
|
84
|
+
/**
|
|
85
|
+
* @maxItems 64
|
|
86
|
+
*/
|
|
87
|
+
public: PublicRoute[];
|
|
88
|
+
}
|
|
89
|
+
export interface PublicRoute {
|
|
90
|
+
path: string;
|
|
91
|
+
/**
|
|
92
|
+
* @minItems 1
|
|
93
|
+
* @maxItems 7
|
|
94
|
+
*/
|
|
95
|
+
methods: ('GET' | 'HEAD' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS')[];
|
|
96
|
+
mode: 'application_authorized';
|
|
97
|
+
}
|
|
@@ -32,6 +32,7 @@ export interface DeclaredConnection {
|
|
|
32
32
|
'slack.message.post'?: AppModeChannelOperation;
|
|
33
33
|
'gmail.thread.list'?: UserModeChannelOperation;
|
|
34
34
|
'gmail.message.read'?: UserModeChannelOperation;
|
|
35
|
+
'gmail.message.send'?: UserModeChannelOperation;
|
|
35
36
|
'warehouse.view.read'?: AppModeViewOperation;
|
|
36
37
|
};
|
|
37
38
|
}
|
|
@@ -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.50.0.0" as const;
|
|
5
|
+
export const ContractPublishVersion = "0.50.0" as const;
|
|
6
|
+
export const ContractPublishTag = "v0.50.0" as const;
|
|
7
|
+
export const ContractSchemasDigest = "sha256:c77dcbf9daad9c66141e9cb8215760a098afd1bf3e665e247f6a4df8db2bcd4f" 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:545d8b23ab712e75285ea962851bcf8f08f5baeb018bea6f7ba4e1ca2fe80ed0" as const;
|
|
10
|
+
export const ContractGeneratedTypeScriptDigest = "sha256:1e47c3956a3468531690693ff50ff7947a798af01e01d25659401f727cb934c4" as const;
|
package/gen-ts/data-grant-v2.ts
CHANGED
|
@@ -38,7 +38,12 @@ export interface DataGrantV2 {
|
|
|
38
38
|
* @maxItems 5
|
|
39
39
|
*/
|
|
40
40
|
operations: (
|
|
41
|
-
'slack.channel.history'
|
|
41
|
+
| 'slack.channel.history'
|
|
42
|
+
| 'slack.message.post'
|
|
43
|
+
| 'gmail.thread.list'
|
|
44
|
+
| 'gmail.message.read'
|
|
45
|
+
| 'gmail.message.send'
|
|
46
|
+
| 'warehouse.view.read'
|
|
42
47
|
)[];
|
|
43
48
|
/**
|
|
44
49
|
* 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
|
-
* 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 NOT a caller field: it is fixed by the operation and enforced from the approved grant; any identity/userId/scope field is rejected by additionalProperties. Per-operation input bounds: slack.channel.history {limit? 1..15, default 15}; slack.message.post {text 1..4000 chars} and a required idempotencyKey retained across retries of one explicit Send; gmail.thread.list {limit? 1..15, default 15}; gmail.message.read {messageId}; warehouse.view.read {columns 1..32, limit? 1..1000, default 100}. Transport limits (not expressible here): request <= 16 KiB, 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 NOT a caller field: it is fixed by the operation and enforced from the approved grant; any identity/userId/scope field is rejected by additionalProperties. Per-operation input bounds: slack.channel.history {limit? 1..15, default 15}; slack.message.post {text 1..4000 chars} and a required idempotencyKey retained across retries of one explicit Send; gmail.thread.list {limit? 1..15, default 15}; gmail.message.read {messageId}; gmail.message.send {to 1..50 addresses (to+cc+bcc <= 50 in total), cc?, bcc?, subject 1..256 chars, text 1..4000 chars, replyToMessageId?} and a required idempotencyKey like slack.message.post (plain text only, no attachments); warehouse.view.read {columns 1..32, limit? 1..1000, default 100}. Transport limits (not expressible here): request <= 16 KiB, total deadline 10 s.
|
|
6
6
|
*/
|
|
7
7
|
export type IntegrationExecuteRequest = {
|
|
8
8
|
/**
|
|
@@ -10,10 +10,15 @@ export type IntegrationExecuteRequest = {
|
|
|
10
10
|
*/
|
|
11
11
|
connection: string;
|
|
12
12
|
/**
|
|
13
|
-
* Closed operation set. Extending it is a contracts change.
|
|
13
|
+
* Closed operation set. Extending it is a contracts change. gmail.message.send (0.50.0) sends one plain-text email as the signed-in person: a send like slack.message.post (explicit Send, idempotencyKey, write receipt) under user identity.
|
|
14
14
|
*/
|
|
15
15
|
operation:
|
|
16
|
-
'slack.channel.history'
|
|
16
|
+
| 'slack.channel.history'
|
|
17
|
+
| 'slack.message.post'
|
|
18
|
+
| 'gmail.thread.list'
|
|
19
|
+
| 'gmail.message.read'
|
|
20
|
+
| 'gmail.message.send'
|
|
21
|
+
| 'warehouse.view.read';
|
|
17
22
|
/**
|
|
18
23
|
* Tenant-wide logical alias of a connection (governance sourceId) or of a resource under it.
|
|
19
24
|
*/
|
|
@@ -25,6 +30,17 @@ export type IntegrationExecuteRequest = {
|
|
|
25
30
|
* gmail.message.read: the Gmail message id a gmail.thread.list result named.
|
|
26
31
|
*/
|
|
27
32
|
messageId?: string;
|
|
33
|
+
to?: EmailAddressList;
|
|
34
|
+
cc?: EmailAddressList1;
|
|
35
|
+
bcc?: EmailAddressList2;
|
|
36
|
+
/**
|
|
37
|
+
* gmail.message.send: one-line subject (no line breaks).
|
|
38
|
+
*/
|
|
39
|
+
subject?: string;
|
|
40
|
+
/**
|
|
41
|
+
* gmail.message.send: a Gmail message id (from gmail.thread.list / gmail.message.read) the email replies to; the send joins that thread.
|
|
42
|
+
*/
|
|
43
|
+
replyToMessageId?: string;
|
|
28
44
|
/**
|
|
29
45
|
* @minItems 1
|
|
30
46
|
* @maxItems 32
|
|
@@ -32,7 +48,32 @@ export type IntegrationExecuteRequest = {
|
|
|
32
48
|
columns?: string[];
|
|
33
49
|
};
|
|
34
50
|
/**
|
|
35
|
-
* UUID of one explicit Send action; required for slack.message.post only. The same key with the same payload and subject returns the recorded outcome for seven days.
|
|
51
|
+
* 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.
|
|
36
52
|
*/
|
|
37
53
|
idempotencyKey?: string;
|
|
38
54
|
};
|
|
55
|
+
/**
|
|
56
|
+
* One bare email address (no display name).
|
|
57
|
+
*/
|
|
58
|
+
export type EmailAddress = string;
|
|
59
|
+
/**
|
|
60
|
+
* gmail.message.send: primary recipients.
|
|
61
|
+
*
|
|
62
|
+
* @minItems 1
|
|
63
|
+
* @maxItems 50
|
|
64
|
+
*/
|
|
65
|
+
export type EmailAddressList = EmailAddress[];
|
|
66
|
+
/**
|
|
67
|
+
* gmail.message.send: carbon-copy recipients.
|
|
68
|
+
*
|
|
69
|
+
* @minItems 1
|
|
70
|
+
* @maxItems 50
|
|
71
|
+
*/
|
|
72
|
+
export type EmailAddressList1 = EmailAddress[];
|
|
73
|
+
/**
|
|
74
|
+
* gmail.message.send: blind-copy recipients.
|
|
75
|
+
*
|
|
76
|
+
* @minItems 1
|
|
77
|
+
* @maxItems 50
|
|
78
|
+
*/
|
|
79
|
+
export type EmailAddressList2 = EmailAddress[];
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Code generated by tools/gen/gen.mjs from schema/*.json. DO NOT EDIT.
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* The `data` member of a successful execute response `{data, requestId}`; the SDK unwraps `data`. Exactly one of the
|
|
5
|
+
* The `data` member of a successful execute response `{data, requestId}`; the SDK unwraps `data`. Exactly one of the six operation results: slack.channel.history -> {messages, hasMore} (plain text/IDs/time only, never the provider payload); slack.message.post -> {messageId}; gmail.thread.list -> {threads, hasMore} (newest inbox threads; each `messageId` is the thread's newest message, what gmail.message.read takes); gmail.message.read -> {id, threadId, subject, from, to, date, text, truncated} (headers plus the plain text with html stripped, cut at 16 KiB with `truncated` set); gmail.message.send -> {messageId, threadId} (the Gmail ids of the sent message and its thread); warehouse.view.read -> {rows} (decimal/64-bit values as strings, dates as ISO strings). An unknown send outcome is never a result; it is an error with details.code SEND_OUTCOME_UNKNOWN. Results over 1 MiB are rejected, not truncated.
|
|
6
6
|
*/
|
|
7
7
|
export type IntegrationExecuteResult = {
|
|
8
8
|
/**
|
|
@@ -43,13 +43,18 @@ export interface SaasConnection {
|
|
|
43
43
|
[k: string]: string;
|
|
44
44
|
};
|
|
45
45
|
/**
|
|
46
|
-
* Operations IT allows apps to request on this connection: the provider's own SaaS operations (Slack: slack.channel.history, slack.message.post; Gmail: gmail.thread.list, gmail.message.read). Never warehouse.view.read.
|
|
46
|
+
* Operations IT allows apps to request on this connection: the provider's own SaaS operations (Slack: slack.channel.history, slack.message.post; Gmail: gmail.thread.list, gmail.message.read, gmail.message.send). Never warehouse.view.read.
|
|
47
47
|
*
|
|
48
48
|
* @minItems 1
|
|
49
|
-
* @maxItems
|
|
49
|
+
* @maxItems 5
|
|
50
50
|
*/
|
|
51
51
|
operations: (
|
|
52
|
-
'slack.channel.history'
|
|
52
|
+
| 'slack.channel.history'
|
|
53
|
+
| 'slack.message.post'
|
|
54
|
+
| 'gmail.thread.list'
|
|
55
|
+
| 'gmail.message.read'
|
|
56
|
+
| 'gmail.message.send'
|
|
57
|
+
| 'warehouse.view.read'
|
|
53
58
|
)[];
|
|
54
59
|
developmentPreapproval: DevelopmentPreapproval;
|
|
55
60
|
/**
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export type TransformReport = {
|
|
8
8
|
/**
|
|
9
|
+
* Optional self-report of the playbooks the agent says it applied. A claim about its own behaviour is not evidence, so nothing validates it; a deployable report may omit it, and one that still carries it stays valid.
|
|
10
|
+
*
|
|
9
11
|
* @minItems 1
|
|
10
12
|
*/
|
|
11
13
|
applied_playbooks?: string[];
|
|
@@ -18,6 +18,7 @@ export type Workload = {
|
|
|
18
18
|
*/
|
|
19
19
|
export type Command = string[];
|
|
20
20
|
export type ResourceProfile = 'standard' | 'memory-1g' | 'memory-2g';
|
|
21
|
+
export type Capability = 'data' | 'files' | 'actions' | 'realtime' | 'telemetry';
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
24
|
* Versioned provisioning input emitted by Harbour Transform. It describes runtime wiring and workload lifecycle only; PostgreSQL grants and RLS remain the database authorization authority.
|
|
@@ -37,6 +38,17 @@ export interface WellDefinedAppManifest {
|
|
|
37
38
|
* @maxItems 128
|
|
38
39
|
*/
|
|
39
40
|
bindings: WorkloadBinding[];
|
|
41
|
+
/**
|
|
42
|
+
* Optional language runtime the application container is built on, spelled exactly as transform-report.application.runtime does (nodejs22, python3.11). Optional so a manifest written before the producer emits it still validates.
|
|
43
|
+
*/
|
|
44
|
+
runtime?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Optional declaration of the Harbour browser capabilities the application uses. Same closed set as the app-capabilities document; this is the declaration, not a source scan.
|
|
47
|
+
*
|
|
48
|
+
* @maxItems 5
|
|
49
|
+
*/
|
|
50
|
+
capabilities?: Capability[];
|
|
51
|
+
routeAuth?: RouteAuth;
|
|
40
52
|
}
|
|
41
53
|
export interface QueueConsumer {
|
|
42
54
|
logicalName: string;
|
|
@@ -68,3 +80,22 @@ export interface WorkloadBinding {
|
|
|
68
80
|
*/
|
|
69
81
|
reference?: string;
|
|
70
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Optional method/path authentication policy. Omitted means every route requires Harbour SSO, the same default the policy states explicitly.
|
|
85
|
+
*/
|
|
86
|
+
export interface RouteAuth {
|
|
87
|
+
default: 'sso_required';
|
|
88
|
+
/**
|
|
89
|
+
* @maxItems 64
|
|
90
|
+
*/
|
|
91
|
+
public: PublicRoute[];
|
|
92
|
+
}
|
|
93
|
+
export interface PublicRoute {
|
|
94
|
+
path: string;
|
|
95
|
+
/**
|
|
96
|
+
* @minItems 1
|
|
97
|
+
* @maxItems 7
|
|
98
|
+
*/
|
|
99
|
+
methods: ('GET' | 'HEAD' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS')[];
|
|
100
|
+
mode: 'application_authorized';
|
|
101
|
+
}
|
package/package.json
CHANGED
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"IntegrationConnectionKind": { "type": "string", "enum": ["saas", "database"] },
|
|
26
26
|
"IntegrationOperation": {
|
|
27
27
|
"type": "string",
|
|
28
|
-
"enum": ["slack.channel.history", "slack.message.post", "gmail.thread.list", "gmail.message.read", "warehouse.view.read"],
|
|
29
|
-
"description": "Closed operation set. Extending it is a contracts change."
|
|
28
|
+
"enum": ["slack.channel.history", "slack.message.post", "gmail.thread.list", "gmail.message.read", "gmail.message.send", "warehouse.view.read"],
|
|
29
|
+
"description": "Closed operation set. Extending it is a contracts change. gmail.message.send (0.50.0) sends one plain-text email as the signed-in person: a send like slack.message.post (explicit Send, idempotencyKey, write receipt) under user identity."
|
|
30
30
|
},
|
|
31
31
|
"IntegrationIdentityMode": {
|
|
32
32
|
"type": "string",
|
|
@@ -110,6 +110,7 @@
|
|
|
110
110
|
"slack.message.post": { "$ref": "#/definitions/AppModeChannelOperation" },
|
|
111
111
|
"gmail.thread.list": { "$ref": "#/definitions/UserModeChannelOperation" },
|
|
112
112
|
"gmail.message.read": { "$ref": "#/definitions/UserModeChannelOperation" },
|
|
113
|
+
"gmail.message.send": { "$ref": "#/definitions/UserModeChannelOperation" },
|
|
113
114
|
"warehouse.view.read": { "$ref": "#/definitions/AppModeViewOperation" }
|
|
114
115
|
}
|
|
115
116
|
}
|
|
@@ -119,7 +120,7 @@
|
|
|
119
120
|
"else": {
|
|
120
121
|
"properties": {
|
|
121
122
|
"operations": {
|
|
122
|
-
"not": { "anyOf": [{ "required": ["slack.channel.history"] }, { "required": ["slack.message.post"] }, { "required": ["gmail.thread.list"] }, { "required": ["gmail.message.read"] }] }
|
|
123
|
+
"not": { "anyOf": [{ "required": ["slack.channel.history"] }, { "required": ["slack.message.post"] }, { "required": ["gmail.thread.list"] }, { "required": ["gmail.message.read"] }, { "required": ["gmail.message.send"] }] }
|
|
123
124
|
}
|
|
124
125
|
}
|
|
125
126
|
}
|
|
@@ -140,7 +141,8 @@
|
|
|
140
141
|
"kind": "saas",
|
|
141
142
|
"operations": {
|
|
142
143
|
"gmail.thread.list": { "identity": "user", "resources": ["inbox"] },
|
|
143
|
-
"gmail.message.read": { "identity": "user", "resources": ["inbox"] }
|
|
144
|
+
"gmail.message.read": { "identity": "user", "resources": ["inbox"] },
|
|
145
|
+
"gmail.message.send": { "identity": "user", "resources": ["inbox"] }
|
|
144
146
|
}
|
|
145
147
|
},
|
|
146
148
|
"sales-warehouse": {
|
|
@@ -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 NOT a caller field: it is fixed by the operation and enforced from the approved grant; any identity/userId/scope field is rejected by additionalProperties. Per-operation input bounds: slack.channel.history {limit? 1..15, default 15}; slack.message.post {text 1..4000 chars} and a required idempotencyKey retained across retries of one explicit Send; gmail.thread.list {limit? 1..15, default 15}; gmail.message.read {messageId}; warehouse.view.read {columns 1..32, limit? 1..1000, default 100}. Transport limits (not expressible here): request <= 16 KiB, 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 NOT a caller field: it is fixed by the operation and enforced from the approved grant; any identity/userId/scope field is rejected by additionalProperties. Per-operation input bounds: slack.channel.history {limit? 1..15, default 15}; slack.message.post {text 1..4000 chars} and a required idempotencyKey retained across retries of one explicit Send; gmail.thread.list {limit? 1..15, default 15}; gmail.message.read {messageId}; gmail.message.send {to 1..50 addresses (to+cc+bcc <= 50 in total), cc?, bcc?, subject 1..256 chars, text 1..4000 chars, replyToMessageId?} and a required idempotencyKey like slack.message.post (plain text only, no attachments); warehouse.view.read {columns 1..32, limit? 1..1000, default 100}. Transport limits (not expressible here): request <= 16 KiB, total deadline 10 s.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"additionalProperties": false,
|
|
8
8
|
"required": ["connection", "operation", "resource", "input"],
|
|
@@ -17,6 +17,11 @@
|
|
|
17
17
|
"limit": { "type": "integer", "minimum": 1, "maximum": 1000 },
|
|
18
18
|
"text": { "type": "string", "minLength": 1, "maxLength": 4000 },
|
|
19
19
|
"messageId": { "type": "string", "pattern": "^[A-Za-z0-9_-]{1,64}$", "description": "gmail.message.read: the Gmail message id a gmail.thread.list result named." },
|
|
20
|
+
"to": { "$ref": "#/definitions/EmailAddressList", "description": "gmail.message.send: primary recipients." },
|
|
21
|
+
"cc": { "$ref": "#/definitions/EmailAddressList", "description": "gmail.message.send: carbon-copy recipients." },
|
|
22
|
+
"bcc": { "$ref": "#/definitions/EmailAddressList", "description": "gmail.message.send: blind-copy recipients." },
|
|
23
|
+
"subject": { "type": "string", "minLength": 1, "maxLength": 256, "description": "gmail.message.send: one-line subject (no line breaks)." },
|
|
24
|
+
"replyToMessageId": { "type": "string", "pattern": "^[A-Za-z0-9_-]{1,64}$", "description": "gmail.message.send: a Gmail message id (from gmail.thread.list / gmail.message.read) the email replies to; the send joins that thread." },
|
|
20
25
|
"columns": {
|
|
21
26
|
"type": "array",
|
|
22
27
|
"minItems": 1,
|
|
@@ -28,7 +33,7 @@
|
|
|
28
33
|
"idempotencyKey": {
|
|
29
34
|
"type": "string",
|
|
30
35
|
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
|
|
31
|
-
"description": "UUID of one explicit Send action; required for slack.message.post only. The same key with the same payload and subject returns the recorded outcome for seven days."
|
|
36
|
+
"description": "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."
|
|
32
37
|
}
|
|
33
38
|
},
|
|
34
39
|
"allOf": [
|
|
@@ -37,7 +42,7 @@
|
|
|
37
42
|
"then": {
|
|
38
43
|
"not": { "required": ["idempotencyKey"] },
|
|
39
44
|
"properties": {
|
|
40
|
-
"input": { "properties": { "limit": { "maximum": 15 } }, "not": { "anyOf": [{ "required": ["text"] }, { "required": ["columns"] }, { "required": ["messageId"] }] } }
|
|
45
|
+
"input": { "properties": { "limit": { "maximum": 15 } }, "not": { "anyOf": [{ "required": ["text"] }, { "required": ["columns"] }, { "required": ["messageId"] }, { "required": ["to"] }, { "required": ["subject"] }] } }
|
|
41
46
|
}
|
|
42
47
|
}
|
|
43
48
|
},
|
|
@@ -46,7 +51,7 @@
|
|
|
46
51
|
"then": {
|
|
47
52
|
"required": ["idempotencyKey"],
|
|
48
53
|
"properties": {
|
|
49
|
-
"input": { "required": ["text"], "not": { "anyOf": [{ "required": ["limit"] }, { "required": ["columns"] }, { "required": ["messageId"] }] } }
|
|
54
|
+
"input": { "required": ["text"], "not": { "anyOf": [{ "required": ["limit"] }, { "required": ["columns"] }, { "required": ["messageId"] }, { "required": ["to"] }, { "required": ["subject"] }] } }
|
|
50
55
|
}
|
|
51
56
|
}
|
|
52
57
|
},
|
|
@@ -55,7 +60,7 @@
|
|
|
55
60
|
"then": {
|
|
56
61
|
"not": { "required": ["idempotencyKey"] },
|
|
57
62
|
"properties": {
|
|
58
|
-
"input": { "required": ["columns"], "not": { "anyOf": [{ "required": ["text"] }, { "required": ["messageId"] }] } }
|
|
63
|
+
"input": { "required": ["columns"], "not": { "anyOf": [{ "required": ["text"] }, { "required": ["messageId"] }, { "required": ["to"] }, { "required": ["subject"] }] } }
|
|
59
64
|
}
|
|
60
65
|
}
|
|
61
66
|
},
|
|
@@ -64,7 +69,7 @@
|
|
|
64
69
|
"then": {
|
|
65
70
|
"not": { "required": ["idempotencyKey"] },
|
|
66
71
|
"properties": {
|
|
67
|
-
"input": { "properties": { "limit": { "maximum": 15 } }, "not": { "anyOf": [{ "required": ["text"] }, { "required": ["columns"] }, { "required": ["messageId"] }] } }
|
|
72
|
+
"input": { "properties": { "limit": { "maximum": 15 } }, "not": { "anyOf": [{ "required": ["text"] }, { "required": ["columns"] }, { "required": ["messageId"] }, { "required": ["to"] }, { "required": ["subject"] }] } }
|
|
68
73
|
}
|
|
69
74
|
}
|
|
70
75
|
},
|
|
@@ -73,11 +78,24 @@
|
|
|
73
78
|
"then": {
|
|
74
79
|
"not": { "required": ["idempotencyKey"] },
|
|
75
80
|
"properties": {
|
|
76
|
-
"input": { "required": ["messageId"], "not": { "anyOf": [{ "required": ["text"] }, { "required": ["columns"] }, { "required": ["limit"] }] } }
|
|
81
|
+
"input": { "required": ["messageId"], "not": { "anyOf": [{ "required": ["text"] }, { "required": ["columns"] }, { "required": ["limit"] }, { "required": ["to"] }, { "required": ["subject"] }] } }
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"if": { "properties": { "operation": { "const": "gmail.message.send" } } },
|
|
87
|
+
"then": {
|
|
88
|
+
"required": ["idempotencyKey"],
|
|
89
|
+
"properties": {
|
|
90
|
+
"input": { "required": ["to", "subject", "text"], "not": { "anyOf": [{ "required": ["limit"] }, { "required": ["columns"] }, { "required": ["messageId"] }] } }
|
|
77
91
|
}
|
|
78
92
|
}
|
|
79
93
|
}
|
|
80
94
|
],
|
|
95
|
+
"definitions": {
|
|
96
|
+
"EmailAddress": { "type": "string", "minLength": 3, "maxLength": 254, "pattern": "^[^\\s@<>,;\"]+@[^\\s@<>,;\"]+\\.[^\\s@<>,;\"]+$", "description": "One bare email address (no display name)." },
|
|
97
|
+
"EmailAddressList": { "type": "array", "minItems": 1, "maxItems": 50, "uniqueItems": true, "items": { "$ref": "#/definitions/EmailAddress" } }
|
|
98
|
+
},
|
|
81
99
|
"examples": [
|
|
82
100
|
{ "connection": "company-slack", "operation": "slack.channel.history", "resource": "team-updates", "input": { "limit": 15 } },
|
|
83
101
|
{
|
|
@@ -89,6 +107,13 @@
|
|
|
89
107
|
},
|
|
90
108
|
{ "connection": "sales-warehouse", "operation": "warehouse.view.read", "resource": "weekly_sales", "input": { "columns": ["week", "total"], "limit": 100 } },
|
|
91
109
|
{ "connection": "gmail", "operation": "gmail.thread.list", "resource": "inbox", "input": { "limit": 15 } },
|
|
92
|
-
{ "connection": "gmail", "operation": "gmail.message.read", "resource": "inbox", "input": { "messageId": "18f2c3a4b5d6e7f8" } }
|
|
110
|
+
{ "connection": "gmail", "operation": "gmail.message.read", "resource": "inbox", "input": { "messageId": "18f2c3a4b5d6e7f8" } },
|
|
111
|
+
{
|
|
112
|
+
"connection": "gmail",
|
|
113
|
+
"operation": "gmail.message.send",
|
|
114
|
+
"resource": "inbox",
|
|
115
|
+
"input": { "to": ["jane@example.com"], "subject": "Weekly report", "text": "Shipped the weekly report.", "replyToMessageId": "18f2c3a4b5d6e7f8" },
|
|
116
|
+
"idempotencyKey": "6f1c2c1e-3a1c-4c3e-9f0e-2b6f7d8a9c11"
|
|
117
|
+
}
|
|
93
118
|
]
|
|
94
119
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
3
|
"$id": "https://schemas.harbour.dev/integration-execute-result.schema.json",
|
|
4
4
|
"title": "IntegrationExecuteResult",
|
|
5
|
-
"description": "The `data` member of a successful execute response `{data, requestId}`; the SDK unwraps `data`. Exactly one of the
|
|
5
|
+
"description": "The `data` member of a successful execute response `{data, requestId}`; the SDK unwraps `data`. Exactly one of the six operation results: slack.channel.history -> {messages, hasMore} (plain text/IDs/time only, never the provider payload); slack.message.post -> {messageId}; gmail.thread.list -> {threads, hasMore} (newest inbox threads; each `messageId` is the thread's newest message, what gmail.message.read takes); gmail.message.read -> {id, threadId, subject, from, to, date, text, truncated} (headers plus the plain text with html stripped, cut at 16 KiB with `truncated` set); gmail.message.send -> {messageId, threadId} (the Gmail ids of the sent message and its thread); warehouse.view.read -> {rows} (decimal/64-bit values as strings, dates as ISO strings). An unknown send outcome is never a result; it is an error with details.code SEND_OUTCOME_UNKNOWN. Results over 1 MiB are rejected, not truncated.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"additionalProperties": false,
|
|
8
8
|
"properties": {
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"oneOf": [
|
|
36
36
|
{ "required": ["messages", "hasMore"], "maxProperties": 2 },
|
|
37
37
|
{ "required": ["messageId"], "maxProperties": 1 },
|
|
38
|
+
{ "required": ["messageId", "threadId"], "maxProperties": 2 },
|
|
38
39
|
{ "required": ["threads", "hasMore"], "maxProperties": 2 },
|
|
39
40
|
{ "required": ["id", "threadId", "subject", "from", "to", "date", "text", "truncated"], "maxProperties": 8 },
|
|
40
41
|
{ "required": ["rows"], "maxProperties": 1 }
|
|
@@ -71,6 +72,7 @@
|
|
|
71
72
|
"hasMore": false
|
|
72
73
|
},
|
|
73
74
|
{ "messageId": "1725840100.000200" },
|
|
75
|
+
{ "messageId": "18f2c3a4b5d6e7f9", "threadId": "18f2c3a4b5d6e7f0" },
|
|
74
76
|
{
|
|
75
77
|
"threads": [{ "id": "18f2c3a4b5d6e7f0", "messageId": "18f2c3a4b5d6e7f8", "subject": "Weekly report", "from": "Jane <jane@example.com>", "date": "2026-09-11T08:00:00Z", "snippet": "Shipped the weekly report." }],
|
|
76
78
|
"hasMore": false
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
"operations": {
|
|
27
27
|
"type": "array",
|
|
28
28
|
"minItems": 1,
|
|
29
|
-
"maxItems":
|
|
29
|
+
"maxItems": 5,
|
|
30
30
|
"uniqueItems": true,
|
|
31
31
|
"items": { "$ref": "app-integrations-declaration.schema.json#/definitions/IntegrationOperation" },
|
|
32
32
|
"not": { "contains": { "const": "warehouse.view.read" } },
|
|
33
|
-
"description": "Operations IT allows apps to request on this connection: the provider's own SaaS operations (Slack: slack.channel.history, slack.message.post; Gmail: gmail.thread.list, gmail.message.read). Never warehouse.view.read."
|
|
33
|
+
"description": "Operations IT allows apps to request on this connection: the provider's own SaaS operations (Slack: slack.channel.history, slack.message.post; Gmail: gmail.thread.list, gmail.message.read, gmail.message.send). Never warehouse.view.read."
|
|
34
34
|
},
|
|
35
35
|
"developmentPreapproval": { "$ref": "#/definitions/DevelopmentPreapproval" },
|
|
36
36
|
"blockedDevelopmentBuilders": {
|
|
@@ -161,7 +161,7 @@
|
|
|
161
161
|
"status": "ACTIVE",
|
|
162
162
|
"version": 1,
|
|
163
163
|
"channels": {},
|
|
164
|
-
"operations": ["gmail.thread.list", "gmail.message.read"],
|
|
164
|
+
"operations": ["gmail.thread.list", "gmail.message.read", "gmail.message.send"],
|
|
165
165
|
"developmentPreapproval": { "enabled": false, "hours": 24 },
|
|
166
166
|
"blockedDevelopmentBuilders": ["contractor@example.com"],
|
|
167
167
|
"createdAt": "2026-09-11T08:00:00Z",
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"required": ["application"],
|
|
10
10
|
"properties": {
|
|
11
11
|
"applied_playbooks": {
|
|
12
|
+
"description": "Optional self-report of the playbooks the agent says it applied. A claim about its own behaviour is not evidence, so nothing validates it; a deployable report may omit it, and one that still carries it stays valid.",
|
|
12
13
|
"type": "array",
|
|
13
14
|
"minItems": 1,
|
|
14
15
|
"items": { "type": "string", "minLength": 1 }
|
|
@@ -666,7 +667,7 @@
|
|
|
666
667
|
],
|
|
667
668
|
"oneOf": [
|
|
668
669
|
{
|
|
669
|
-
"required": ["
|
|
670
|
+
"required": ["static_rebuild_required", "analysis", "database", "preservation_plan", "validation_fixtures", "application"],
|
|
670
671
|
"properties": {
|
|
671
672
|
"application": {
|
|
672
673
|
"required": ["runtime", "buildKind", "topology", "entrypoint", "build", "basePath", "evidence", "unsupportedFeatures"],
|
|
@@ -26,9 +26,70 @@
|
|
|
26
26
|
"type": "array",
|
|
27
27
|
"maxItems": 128,
|
|
28
28
|
"items": { "$ref": "#/definitions/WorkloadBinding" }
|
|
29
|
+
},
|
|
30
|
+
"runtime": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"pattern": "^(?:nodejs|python)[0-9]+(?:\\.[0-9]+)?$",
|
|
33
|
+
"description": "Optional language runtime the application container is built on, spelled exactly as transform-report.application.runtime does (nodejs22, python3.11). Optional so a manifest written before the producer emits it still validates."
|
|
34
|
+
},
|
|
35
|
+
"capabilities": {
|
|
36
|
+
"type": "array",
|
|
37
|
+
"maxItems": 5,
|
|
38
|
+
"uniqueItems": true,
|
|
39
|
+
"items": { "$ref": "#/definitions/Capability" },
|
|
40
|
+
"description": "Optional declaration of the Harbour browser capabilities the application uses. Same closed set as the app-capabilities document; this is the declaration, not a source scan."
|
|
41
|
+
},
|
|
42
|
+
"routeAuth": {
|
|
43
|
+
"$ref": "#/definitions/RouteAuth",
|
|
44
|
+
"description": "Optional method/path authentication policy. Omitted means every route requires Harbour SSO, the same default the policy states explicitly."
|
|
29
45
|
}
|
|
30
46
|
},
|
|
31
47
|
"definitions": {
|
|
48
|
+
"Capability": {
|
|
49
|
+
"type": "string",
|
|
50
|
+
"enum": ["data", "files", "actions", "realtime", "telemetry"]
|
|
51
|
+
},
|
|
52
|
+
"RouteAuth": {
|
|
53
|
+
"type": "object",
|
|
54
|
+
"additionalProperties": false,
|
|
55
|
+
"required": ["default", "public"],
|
|
56
|
+
"description": "Harbour SSO is required by default; the public list is the only way a route escapes it, and each entry names the methods and the application-authorized mode so the artifact contract's route_auth can be built from this document alone.",
|
|
57
|
+
"properties": {
|
|
58
|
+
"default": {
|
|
59
|
+
"type": "string",
|
|
60
|
+
"const": "sso_required",
|
|
61
|
+
"default": "sso_required"
|
|
62
|
+
},
|
|
63
|
+
"public": {
|
|
64
|
+
"type": "array",
|
|
65
|
+
"maxItems": 64,
|
|
66
|
+
"default": [],
|
|
67
|
+
"items": { "$ref": "#/definitions/PublicRoute" }
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"PublicRoute": {
|
|
72
|
+
"type": "object",
|
|
73
|
+
"additionalProperties": false,
|
|
74
|
+
"required": ["path", "methods", "mode"],
|
|
75
|
+
"properties": {
|
|
76
|
+
"path": {
|
|
77
|
+
"type": "string",
|
|
78
|
+
"pattern": "^/(?:[A-Za-z0-9._~-]+/)*(?:[A-Za-z0-9._~-]+|\\*)$"
|
|
79
|
+
},
|
|
80
|
+
"methods": {
|
|
81
|
+
"type": "array",
|
|
82
|
+
"minItems": 1,
|
|
83
|
+
"maxItems": 7,
|
|
84
|
+
"uniqueItems": true,
|
|
85
|
+
"items": {
|
|
86
|
+
"type": "string",
|
|
87
|
+
"enum": ["GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"mode": { "type": "string", "const": "application_authorized" }
|
|
91
|
+
}
|
|
92
|
+
},
|
|
32
93
|
"ResourceProfile": {
|
|
33
94
|
"type": "string",
|
|
34
95
|
"enum": ["standard", "memory-1g", "memory-2g"]
|