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
fix(v2): stop telling callers something the server did not do (#6676)
A works-as-advertised sweep of the v2 surface found one defect class in five
places: input is validated for shape, then its meaning is re-derived
independently by each consumer — so a filter compiles differently than it
validated, or a write commits and the response then reports failure.
Knowledge tag filters were validated once and re-parsed three times. The
document list read `Number()`, search read `parseFloat()`; the list matched
booleans case-insensitively, search compared against the literal `'true'`; the
list escaped LIKE metacharacters, search did not; and the date pattern was
tested against the untrimmed string the validator had already trimmed. Two of
those paths dropped the predicate entirely and answered 200 with the whole
knowledge base — on a billed endpoint. Values are now coerced once, where the
resolved field type is known, and both builders consume the result. A builder
that cannot compile an already-validated filter now raises instead of silently
widening the result set.
`PUT /api/v2/secrets/{name}` with `scope: personal` committed the secret and
then answered 500, because a user-global write was reported through a
workspace-scoped mirror lookup, and an org admin's inherited access has no
`permissions` row for the fan-out to find. The personal path no longer decides
success from a per-workspace mirror. The `workspaceId` descriptions said a
personal secret lives in one workspace; it does not, and they now say so.
A custom tool could be stored with a schema the read path cannot serialize —
`POST /workflows/import` and Copilot both wrote through name-only checks — so
one row made the whole workspace list 500, and a title-only PATCH committed,
audited, then reported failure. Every write now passes the same guard the
response schema is derived from.
`POST /api/v2/tables` accepted `workflowGroupId` on an initial column. Nothing
can populate it legitimately, and it made every later column-add and group-add
fail with no way to clear it. The key is refused at the boundary, and
`createTable` now runs the invariant every later mutation already runs, closing
the internal and v1 ingresses too. Those invariants moved to a leaf module:
reaching them through `workflow-columns` pulled the executable tool registry
into the tables page graph, taking it from 1,767 modules to 6,999.
An out-of-range upload part number answered 500 rather than the 400 its
published contract promises, because the throw happened above the route's
try/catch and was not an `HttpError`.
Copy file name to clipboardExpand all lines: apps/docs/openapi-v2-resources.json
+8-8Lines changed: 8 additions & 8 deletions
Original file line number
Diff line number
Diff line change
@@ -1965,22 +1965,22 @@
1965
1965
"name": "workspaceId",
1966
1966
"in": "query",
1967
1967
"required": true,
1968
-
"description": "Workspace in which the secret is available.",
1968
+
"description": "Workspace the request is authorized against. A workspace secret is deleted from it; a personal secret is deleted for the caller in all of their workspaces.",
1969
1969
"schema": {
1970
1970
"type": "string",
1971
1971
"minLength": 1,
1972
-
"description": "Workspace in which the secret is available."
1972
+
"description": "Workspace the request is authorized against. A workspace secret is deleted from it; a personal secret is deleted for the caller in all of their workspaces."
1973
1973
}
1974
1974
},
1975
1975
{
1976
1976
"name": "scope",
1977
1977
"in": "query",
1978
1978
"required": true,
1979
-
"description": "Whether the secret belongs to the workspace or the caller.",
1979
+
"description": "Whether the secret belongs to the workspace or to the caller. A personal secret belongs to the caller across every workspace, not to one workspace.",
1980
1980
"schema": {
1981
1981
"type": "string",
1982
1982
"enum": ["workspace", "personal"],
1983
-
"description": "Whether the secret belongs to the workspace or the caller."
1983
+
"description": "Whether the secret belongs to the workspace or to the caller. A personal secret belongs to the caller across every workspace, not to one workspace."
1984
1984
}
1985
1985
}
1986
1986
],
@@ -4088,7 +4088,7 @@
4088
4088
"scope": {
4089
4089
"type": "string",
4090
4090
"enum": ["workspace", "personal"],
4091
-
"description": "Whether the secret belongs to the workspace or the caller."
4091
+
"description": "Whether the secret belongs to the workspace or to the caller. A personal secret belongs to the caller across every workspace, not to one workspace."
4092
4092
},
4093
4093
"role": {
4094
4094
"type": "string",
@@ -4184,12 +4184,12 @@
4184
4184
"workspaceId": {
4185
4185
"type": "string",
4186
4186
"minLength": 1,
4187
-
"description": "Workspace in which the secret is available."
4187
+
"description": "Workspace the request is authorized against. A workspace secret is written to it; a personal secret is written to the caller and is available in all of their workspaces."
4188
4188
},
4189
4189
"scope": {
4190
4190
"type": "string",
4191
4191
"enum": ["workspace", "personal"],
4192
-
"description": "Whether the secret belongs to the workspace or the caller."
4192
+
"description": "Whether the secret belongs to the workspace or to the caller. A personal secret belongs to the caller across every workspace, not to one workspace."
4193
4193
},
4194
4194
"value": {
4195
4195
"type": "string",
@@ -4224,7 +4224,7 @@
4224
4224
"scope": {
4225
4225
"type": "string",
4226
4226
"enum": ["workspace", "personal"],
4227
-
"description": "Whether the secret belongs to the workspace or the caller."
4227
+
"description": "Whether the secret belongs to the workspace or to the caller. A personal secret belongs to the caller across every workspace, not to one workspace."
@@ -76,7 +78,9 @@ export type V2SecretParams = z.output<typeof v2SecretParamsSchema>
76
78
77
79
exportconstv2SetSecretBodySchema=z
78
80
.object({
79
-
workspaceId: workspaceIdSchema.describe('Workspace in which the secret is available.'),
81
+
workspaceId: workspaceIdSchema.describe(
82
+
'Workspace the request is authorized against. A workspace secret is written to it; a personal secret is written to the caller and is available in all of their workspaces.'
83
+
),
80
84
scope: v2SecretScopeSchema,
81
85
value: z
82
86
.string()
@@ -90,7 +94,9 @@ export type V2SetSecretBody = z.input<typeof v2SetSecretBodySchema>
90
94
91
95
exportconstv2DeleteSecretQuerySchema=z
92
96
.object({
93
-
workspaceId: workspaceIdSchema.describe('Workspace in which the secret is available.'),
97
+
workspaceId: workspaceIdSchema.describe(
98
+
'Workspace the request is authorized against. A workspace secret is deleted from it; a personal secret is deleted for the caller in all of their workspaces.'
0 commit comments