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(secrets): let a workspace secret change its metadata without resending the value
Restoring redaction cost more than removing it. The only way to flip a secret
back to redacted was to re-send the plaintext, because the write required a
value and omitting it fell into an interactive prompt that cannot run in CI.
A workspace secret can now change its description or visibility on its own; the
stored value is never re-encrypted or rewritten, a write that names no existing
secret answers not-found rather than creating one, and a personal secret still
requires a value because it has no other writable field.
The path parameter was also one shared schema across the write and the delete,
so a single description had to cover both and the delete documented an argument
that could create and replace. Split, mirroring the credentials pair.
The metadata write is a new update against the credentials table, so its scope
is asserted by composition and by condition count: an unscoped update would let
one workspace flip another workspace's identically-named secret out of
redaction, and the cache invalidation would then carry that flag into the other
workspace's runtime catalog.
Copy file name to clipboardExpand all lines: apps/sim/lib/api/contracts/v2/openapi/resources.ts
+11-3Lines changed: 11 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -1368,11 +1368,14 @@ const declaredRoutes = [
1368
1368
resourceOperation('Secrets',{
1369
1369
operationId: 'setSecret',
1370
1370
summary: 'Set Secret',
1371
-
description: `Create or replace a workspace or caller-owned personal secret. The value is encrypted at rest, is write-only, and is never included in the response. ${WORKSPACE_API_KEY_DENIED}`,
1371
+
description: `Create or replace a workspace or caller-owned personal secret. The value is encrypted at rest, is write-only, and is never included in the response. Omit \`value\` on a workspace secret to update \`description\` and \`unredacted\` alone: the stored value is left untouched and is never re-encrypted, and because a metadata-only write cannot create a secret it answers \`404\` when the named secret does not exist. A personal secret always requires \`value\`, having no other writable field. ${WORKSPACE_API_KEY_DENIED}`,
1372
1372
errors: RESOURCE_ERRORS,
1373
1373
success: {
1374
1374
byStatus: {
1375
-
200: {description: 'The existing secret value was replaced.'},
1375
+
200: {
1376
+
description:
1377
+
'The existing secret value was replaced, or its metadata was updated in place.',
1378
+
},
1376
1379
201: {description: 'The secret was created.'},
1377
1380
},
1378
1381
},
@@ -1389,13 +1392,18 @@ const declaredRoutes = [
1389
1392
v2SetSecretContract.body,
1390
1393
'SetSecretRequest',
1391
1394
'Set secret request',
1392
-
'Ownership scope and write-only value for the secret.',
1395
+
'Ownership scope and write-only value for the secret. A workspace secret may instead send description or unredacted alone, without a value.',
@@ -119,7 +131,10 @@ export const v2SetSecretBodySchema = z
119
131
.string()
120
132
.min(1,'value is required')
121
133
.max(65_536,'value is too long')
122
-
.describe('Write-only secret value. It is never returned.')
134
+
.optional()
135
+
.describe(
136
+
'Write-only secret value. It is never returned. Omit it on a workspace secret to change description or unredacted alone, leaving the stored value untouched; the secret must already exist. Always required for a personal secret, which carries no other writable field.'
137
+
)
123
138
.meta({writeOnly: true}),
124
139
description: z
125
140
.string()
@@ -137,19 +152,49 @@ export const v2SetSecretBodySchema = z
137
152
),
138
153
})
139
154
.strict()
155
+
/**
156
+
* `value` is optional on the schema so a workspace secret's redaction policy can
157
+
* be flipped back without re-transmitting the plaintext — restoring redaction is
158
+
* the safe direction and must not cost more than leaving it off. Two refinements
159
+
* keep that from over-relaxing the request: a personal secret has no metadata
160
+
* field at all, so a value-less personal write would be a silent no-op rather
161
+
* than an update; and a body carrying none of the three writable fields is
162
+
* rejected outright instead of resolving to an empty write.
0 commit comments