Skip to content

Commit 84ac111

Browse files
committed
fix(docs): keep the shipped workspaces members anchor and classify the member update
- Pin the CLI reference heading for `sim workspaces members list` to the `#sim-workspaces-members` anchor it shipped under, through a reference-page counterpart of the existing legacy anchor map, and restore that heading in the docs compatibility baseline. - Classify `updateWorkspaceMember` as non-destructive alongside `updateOrganizationMember`. - Cover an inherited organization admin with no grant row: PATCH answers the documented 400 for every requested role and writes nothing.
1 parent 1b62796 commit 84ac111

5 files changed

Lines changed: 36 additions & 7 deletions

File tree

‎apps/docs/content/docs/cli/reference.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8849,7 +8849,7 @@ sim workspaces fork-resources [options]
88498849

88508850
API request and response schemas: [listWorkspaceForkResources](/api-reference/workspace-sync/listWorkspaceForkResources).
88518851

8852-
### sim workspaces members list
8852+
### sim workspaces members list [#sim-workspaces-members]
88538853

88548854
List workspace members
88558855

‎apps/docs/scripts/fixtures/content-baseline.json‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8555,8 +8555,8 @@
85558555
"depth": 3
85568556
},
85578557
{
8558-
"title": "sim workspaces members list",
8559-
"url": "#sim-workspaces-members-list",
8558+
"title": "sim workspaces members",
8559+
"url": "#sim-workspaces-members",
85608560
"depth": 3
85618561
},
85628562
{

‎apps/sim/lib/workspaces/__integration__/members.integration.ts‎

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -480,16 +480,33 @@ describe('v2 workspace member management against PostgreSQL', () => {
480480
const refusals = await Promise.all([
481481
call(admin, 'PATCH', f.users.wsOwner, { body: { role: 'read' } }),
482482
call(admin, 'PATCH', f.users.billing, { body: { role: 'read' } }),
483-
call(admin, 'PATCH', f.users.orgOwner, { body: { role: 'write' } }),
484-
call(admin, 'PATCH', f.users.orgOwner, { body: { role: 'admin' } }),
485483
call(admin, 'DELETE', f.users.orgOwner),
486484
call(admin, 'DELETE', f.users.billing),
487485
])
488-
expect(refusals.map((response) => response.status)).toEqual([400, 400, 400, 400, 400, 400])
486+
expect(refusals.map((response) => response.status)).toEqual([400, 400, 400, 400])
489487
expect(await roleOf(f.users.wsOwner)).toBe('admin')
490488
expect(await roleOf(f.users.billing)).toBe('admin')
491489
})
492490

491+
it('refuses an inherited organization admin, who holds no grant row, whatever role is requested', async () => {
492+
expect(await roleOf(f.users.orgOwner)).toBeNull()
493+
for (const role of ['admin', 'write', 'read'] as const) {
494+
const response = await call(key('admin'), 'PATCH', f.users.orgOwner, { body: { role } })
495+
expect(response).toEqual({
496+
status: 400,
497+
retryAfter: null,
498+
body: {
499+
error: {
500+
code: 'BAD_REQUEST',
501+
message: 'Organization admins are workspace admins and their role cannot be changed',
502+
},
503+
},
504+
})
505+
}
506+
expect(await roleOf(f.users.orgOwner)).toBeNull()
507+
expect(await auditRows('member.role_changed')).toHaveLength(0)
508+
})
509+
493510
it('returns the roster member and audits the key owner as actor', async () => {
494511
const response = await call(key('admin'), 'PATCH', f.users.reader, { body: { role: 'write' } })
495512
expect(response.status).toBe(200)

‎packages/sim-cli/src/http/client.test.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,7 @@ describe('destructive operations are gated', () => {
447447
'createOrganizationInvitation',
448448
'resendOrganizationInvitation',
449449
'updateOrganizationMember',
450+
'updateWorkspaceMember',
450451
'createPermissionGroup',
451452
'updatePermissionGroup',
452453
'addPermissionGroupMember',

‎scripts/generate-cli-docs.ts‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,15 @@ const LEGACY_COMMAND_ANCHORS: Record<string, string> = {
466466
'wait-for-copy-and-deployment-readiness-exit-3-for-configuration-1-for-failure-or-4-for-timeout',
467467
}
468468

469+
/**
470+
* Reference-page anchors a renamed command keeps, so links to the spelling it
471+
* shipped under still land on it. `workspaces members` became a group whose
472+
* default subcommand is `list`.
473+
*/
474+
const LEGACY_REFERENCE_ANCHORS: Record<string, string> = {
475+
'workspaces members list': 'sim-workspaces-members',
476+
}
477+
469478
const VERB_ORDER = [
470479
'list',
471480
'ls',
@@ -913,7 +922,9 @@ function renderCommand(entry: DocumentedCommand, options: RenderOptions = {}): s
913922
const description = entry.command.description()
914923
const operation = operationOf(entry.command)
915924
const spec = operation ? CLI_CONTRACT[operation] : undefined
916-
const anchor = commandHeadings ? undefined : LEGACY_COMMAND_ANCHORS[entry.path.join(' ')]
925+
const anchor = (commandHeadings ? LEGACY_REFERENCE_ANCHORS : LEGACY_COMMAND_ANCHORS)[
926+
entry.path.join(' ')
927+
]
917928
const lines = [`${'#'.repeat(level)} ${escapeProse(heading)}${anchor ? ` [#${anchor}]` : ''}`, '']
918929
if (commandHeadings && description) lines.push(escapeProse(sentenceCase(description)), '')
919930
if (!commandHeadings) {

0 commit comments

Comments
 (0)