You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit c5cec7d
Browse filesBrowse the repository at this point in the historyBrowse files
Optional companions: `credentialLabels` (override the picker's section/connect-row copy) and `allowServiceAccounts: true` (trigger-mode only — list service accounts, which triggers otherwise exclude; set only when the trigger's polling path can resolve a service-account token). The connect modal, provider families (Google JSON key, Atlassian token, token-paste, client-credential, Slack bot), and the preview gate are all resolved from `serviceAccountProviderId` — you don't wire them per block.
161
161
162
+
### Credential-only successor (replacing inline secrets)
163
+
164
+
A block that takes a secret inline keeps running for existing workflows; the saved-credential
165
+
version is a new block type that spreads it. Keep the successor an object literal with the picker
166
+
written inline, because the docs generator reads the source text:
167
+
168
+
```typescript
169
+
exportconst ServiceV2Block:BlockConfig= {
170
+
...ServiceBlock,
171
+
type: 'service_v2',
172
+
authMode: AuthMode.OAuth,
173
+
hideFromToolbar: false,
174
+
sunset: undefined,
175
+
...withSavedCredential(ServiceBlock, {
176
+
id: 'credential',
177
+
type: 'oauth-input',
178
+
serviceId: 'service',
179
+
title: 'Service Credential',
180
+
}),
181
+
}
182
+
```
183
+
184
+
- The legacy block changes only by `hideFromToolbar: true` and `sunset: { status: 'legacy',
185
+
replacedBy: 'service_v2' }` (an older `_v2` points at the new `_v3`). Register both types.
186
+
-`withSavedCredential` (`blocks/utils.ts`) swaps exactly the fields its policy in
187
+
`SAVED_CREDENTIAL_OAUTH` supplies for the picker, places it directly under the operation
188
+
dropdown, inherits the replaced fields' `condition` and `required`, and leaves trigger-mode
189
+
fields alone. Pass `required` when the replaced fields disagree (an optional host), and `params`
190
+
only when the legacy params builder validates the secret: extract that builder so the legacy
191
+
block calls it unchanged (`blocks/legacy-builders.test.ts`) and the successor skips the check.
192
+
- Add the pair to `serializer/saved-credentials.test.ts` (`optionalIds` for replaced fields the
193
+
legacy block never required), and grep for code that hard-codes the legacy type (`getBlock`,
194
+
`integration.type ===`, availability lookups), which now resolves to the successor.
195
+
162
196
### OAuth deployment availability (required for integration blocks)
163
197
164
198
A visible tools-category block with OAuth is deployment-gated. Its `oauth-input.serviceId` is
'accessToken' | 'domain' | 'providerWorkspaceId' })`, listed in `SAVED_CREDENTIAL_OAUTH`, and set
91
+
as `oauth` on every tool. Map every param that decides the request host; the executor overwrites
92
+
mapped params after authorizing the credential, and `check-block-registry` probes the tools' real
93
+
URL builders and fails on a host-steering param left unmapped.
94
+
5. A credential-only block (including a successor) uses `authMode: AuthMode.OAuth`, so the
95
+
generated catalog maps the service; a token-only block that keeps `AuthMode.ApiKey`, as Coda
96
+
does, registers in `tokenCredentialIntegrationTypes` instead (see below). The credential picker
97
+
sits directly under the operation dropdown (`add-block` → OAuth/Credentials). An existing block that already takes the secret inline is never edited in
98
+
place: add a credential-only successor (`add-block` → Credential-only successor).
99
+
100
+
Then run `generate-docs`, `generate:block-successors`, `generate:deployment-config`, and
101
+
`generate:tool-metadata`, and `check-block-registry.ts origin/staging`. This pattern does not fit
102
+
hosted-key tools, model-provider keys, two-secret or username/password logins, or a host chosen
103
+
per call.
104
+
69
105
### Pair saved credentials with block and resource selectors
70
106
71
107
`oauth-input` is the shared saved-credential picker, including for service accounts that never
Copy file name to clipboardExpand all lines: .agents/skills/validate-integration/SKILL.md
+11Lines changed: 11 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -218,6 +218,17 @@ For **each tool** in `tools.access`:
218
218
- True/false → `switch` (a Yes/No `dropdown` only when the tool needs a third "unset" state)
219
219
- Credentials → `oauth-input` with correct `serviceId`
220
220
- Every tool with a `credential`/`oauthCredential` param declares `oauth: { required: true, provider }` matching that `serviceId`, plus `credentialKind: 'service-account'` when only service accounts are supported
221
+
-[ ] In a new block or credential-only successor, a pasted key, token, or token + host comes from a
222
+
saved token credential (add-integration → Token credentials), not an inline `password` field
223
+
(legacy blocks keep theirs); a successor changes its legacy block only by `hideFromToolbar`
224
+
and `sunset`, and its picker sits under the operation
225
+
-[ ] For a token-credential integration, every tool in `tools.access` declares the service's
226
+
`tokenCredentialOAuth` policy, every
227
+
param that decides the request host is mapped, and the stored domain is in the form the tools
228
+
build URLs from (`check-block-registry.ts origin/staging` passes)
229
+
-[ ] The `tokenCheckValidator` request uses the tools' host and auth, its normalizers refuse
230
+
anything that could steer the host or path, and a fake key is rejected without a valid
231
+
scoped key being refused
221
232
-[ ] Dropdown `value: () => 'default'` is set for dropdowns with a sensible default
222
233
-[ ] Every `short-input`, `long-input`, `code`, and selector subBlock has a `placeholder` — including
223
234
password fields (`Enter your API key`). Formatted values show the shape
|`blockId`| Yes | Trigger block in the deployed workflow. |
8267
+
8268
+
</CommandTable>
8269
+
8270
+
**Options**
8271
+
8272
+
<CommandTable>
8273
+
8274
+
| Option | Required | Description |
8275
+
| --- | --- | --- |
8276
+
|`--enabled <true\|false>`| Yes | Whether the trigger should fire. A disable lasts until the next deploy or version activation, which re-enables every trigger. Accepted values: `true`, `false`. |
8277
+
8278
+
</CommandTable>
8279
+
8280
+
API request and response schemas: [updateWorkflowTrigger](/api-reference/workflows/updateWorkflowTrigger).
|`blockId`| Yes | Trigger block in the deployed workflow. |
466
+
467
+
</CommandTable>
468
+
469
+
**Options**
470
+
471
+
<CommandTable>
472
+
473
+
| Option | Required | Description |
474
+
| --- | --- | --- |
475
+
|`--enabled <true\|false>`| Yes | Whether the trigger should fire. A disable lasts until the next deploy or version activation, which re-enables every trigger. Accepted values: `true`, `false`. |
476
+
477
+
</CommandTable>
478
+
479
+
API request and response schemas: [updateWorkflowTrigger](/api-reference/workflows/updateWorkflowTrigger).
0 commit comments