Repository navigation
Commit a2e9835
authored
Normalize plugin secret/connection refs + add usages SDK surface (#521)
* Add secret/connection usages SDK surface + UI placeholder
Plugins gain optional `usagesForSecret` / `usagesForConnection` callbacks
that the executor fans out across via `executor.secrets.usages(id)` and
`executor.connections.usages(id)`. Secret/connection removal is now
RESTRICT — refuses with `SecretInUseError` / `ConnectionInUseError` when
any plugin reports the id as in use, surfacing the count to the caller.
API gains GET `/secrets/:id/usages` and `/connections/:id/usages`
endpoints. React atoms and a small "Used by …" footer on each row in
the Secrets and Connections tabs round out the surface.
No plugin implements `usagesForSecret`/`usagesForConnection` yet, so
the footer renders nothing and remove still succeeds for everything.
Plugin migration lands in follow-up commits.
* Normalize graphql plugin secret/connection refs
Move secret/connection references out of the JSON columns on
graphql_source (auth, headers, query_params) into:
- two new flat columns auth_kind + auth_connection_id (indexed)
- two child tables graphql_source_header / graphql_source_query_param,
each with kind/text_value/secret_id/secret_prefix and an indexed
secret_id
This lets usagesForSecret and usagesForConnection answer "where is X
referenced?" with a single indexed SELECT instead of scanning JSON, and
secrets.remove / connections.remove now correctly RESTRICT when a
graphql source still references the id.
Migration 0007 backfills existing JSON via json_each + json_extract,
then drops the old columns. Three tests cover the backfill against a
hand-seeded pre-migration DB; three plugin-level tests cover usage
fan-out and remove RESTRICT.
* Normalize openapi plugin secret/connection refs
Move secret/connection references out of the JSON columns on
openapi_source and openapi_source_binding into:
- openapi_source_binding gains kind/secret_id/connection_id/text_value
columns (replacing the discriminated-union json value)
- openapi_source_query_param: child table for query_params, mirrors
graphql_source_query_param shape
- openapi_source_spec_fetch_header / spec_fetch_query_param: child
tables for invocation_config.specFetchCredentials.{headers,queryParams}
Drops openapi_source.query_params and openapi_source.invocation_config
JSON columns. headers and oauth2 stay JSON because they hold slot
names rather than direct refs — the slots resolve through bindings,
which ARE normalized.
Plugin gains usagesForSecret / usagesForConnection that fan out across
all four locations in one indexed SELECT each. secrets.remove now
correctly RESTRICTs when an openapi binding still uses the secret.
Migration 0008 backfills via json_extract / json_each, then drops the
old columns. Three migration tests cover the backfill from a
hand-seeded pre-migration DB; two plugin-level tests cover usage
fan-out and remove RESTRICT.
* Normalize mcp plugin secret/connection refs
Move secret/connection references out of the JSON `mcp_source.config`
column into:
- Flat columns on mcp_source: auth_kind, auth_header_name,
auth_secret_id, auth_secret_prefix, auth_connection_id,
auth_client_id_secret_id, auth_client_secret_secret_id (each indexed
where it carries a ref). Replaces the McpConnectionAuth json blob.
- mcp_source_header / mcp_source_query_param: child tables for the
remote source's SecretBackedMap entries (same shape as graphql /
openapi child tables).
The remaining structural fields (transport, endpoint, command, args,
etc.) stay as JSON in `config` because they're plugin-private and vary
by transport. mcp_binding.binding stays JSON too — McpToolBinding
carries no refs and inputSchema/outputSchema are arbitrary user JSON.
Plugin gains usagesForSecret / usagesForConnection. Migration 0009
backfills via json_extract / json_each, then strips the extracted
fields with json_remove. Three migration tests cover backfill from a
hand-seeded pre-migration DB; two plugin-level tests cover usage
fan-out across header-auth and oauth2 sources.
* Normalize google-discovery plugin secret/connection refs
Move secret/connection references out of the JSON
google_discovery_source.config column into:
- Flat columns on google_discovery_source: auth_kind,
auth_connection_id, auth_client_id_secret_id,
auth_client_secret_secret_id, auth_scopes (each indexed where it
carries a ref). Replaces the GoogleDiscoveryAuth json.
- google_discovery_source_credential_header /
google_discovery_source_credential_query_param: child tables for the
optional GoogleDiscoveryFetchCredentials SecretBackedMap entries.
The remaining structural fields (discoveryUrl, service, version,
rootUrl, servicePath) stay in `config` as JSON — they're plugin-private
and never carry refs. google_discovery_binding stays JSON too: the
GoogleDiscoveryMethodBinding has no refs, and method input/output
schemas are arbitrary user data.
Plugin gains usagesForSecret / usagesForConnection. Migration 0010
backfills via json_extract / json_each, then strips the extracted
fields with json_remove. Three migration tests cover backfill from a
hand-seeded pre-migration DB; one plugin-level test covers usage
fan-out across auth_*_secret_id and auth_connection_id.
* Consolidate plugin normalization into single migration
Merge graphql/openapi/mcp/google-discovery normalization into one
migration per app: 0007_normalize_plugin_secret_refs (local sqlite)
and 0008_normalize_plugin_secret_refs (cloud pg, mcp-only since cloud
doesn't ship google-discovery).
Each test now imports a shared PRE_0007_SQL helper that seeds all four
plugins' parent tables at the pre-migration shape — needed because the
single consolidated migration touches every plugin in one transaction.
* Address review: legacy openapi OAuth + strict usage gate + shadow-aware delete
Three issues from review:
1. migrateOpenApi was early-returning when invocation_config column
was missing (post-0007). Rows with legacy OAuth in oauth2 column
silently lost their migration to a Connection. Fixed:
- migrate-connections now reads oauth2 column even without
invocation_config, and adapts its UPDATE statement accordingly.
- Both 0007 (sqlite) and 0008 (pg) migrations COALESCE
invocation_config.oauth2 into the oauth2 column before dropping
invocation_config, so legacy data isn't lost mid-migration.
2. secrets.remove / connections.remove gated on a lenient usage helper
that swallowed plugin failures into empty arrays — a transient
plugin error could silently allow a delete that creates dangling
refs. Added secretsUsagesStrict / connectionsUsagesStrict that
propagate plugin failures as StorageFailure and wired them into the
delete RESTRICT path. Display path keeps the lenient variant.
3. The RESTRICT check was global by id, conflicting with the documented
shadowing model: deleting a user-scope override should reveal the
outer fallback, but the global check blocked any delete whose id is
referenced anywhere. Now scoped: only enforce RESTRICT when the
delete would leave no row with that id (i.e., the reference would
actually dangle).1 parent ea306d0 commit a2e9835
41 files changed
Lines changed: 10327 additions & 211 deletions
File tree
- apps
- cloud
- drizzle
- meta
- src/services
- local
- drizzle
- meta
- src/server
- __test-helpers__
- packages
- core
- api/src
- connections
- handlers
- secrets
- execution/src
- sdk/src
- plugins
- google-discovery/src/sdk
- graphql/src/sdk
- mcp/src/sdk
- openapi/src/sdk
- react/src
- api
- pages
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
60 | 67 | | |
61 | 68 | | |
62 | | - | |
| 69 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
122 | 122 | | |
123 | 123 | | |
124 | 124 | | |
125 | | - | |
126 | | - | |
127 | | - | |
| 125 | + | |
128 | 126 | | |
129 | 127 | | |
130 | 128 | | |
| |||
147 | 145 | | |
148 | 146 | | |
149 | 147 | | |
150 | | - | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
151 | 152 | | |
152 | 153 | | |
153 | 154 | | |
154 | 155 | | |
155 | 156 | | |
156 | 157 | | |
157 | 158 | | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
158 | 209 | | |
159 | 210 | | |
160 | 211 | | |
161 | 212 | | |
162 | 213 | | |
163 | 214 | | |
164 | 215 | | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
165 | 223 | | |
166 | 224 | | |
167 | 225 | | |
168 | 226 | | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
169 | 263 | | |
170 | 264 | | |
171 | 265 | | |
| |||
185 | 279 | | |
186 | 280 | | |
187 | 281 | | |
188 | | - | |
189 | | - | |
190 | | - | |
| 282 | + | |
| 283 | + | |
191 | 284 | | |
192 | 285 | | |
193 | 286 | | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
194 | 320 | | |
195 | 321 | | |
196 | 322 | | |
| |||
0 commit comments