Skip to content

Commit 649cffe

Browse files
authored
feat: --scopes オプションのヘルプに有効なスコープ一覧を追加 (#73)
* feat: --scopes オプションのヘルプに有効なスコープ一覧を追加 help.ts に addNotes() 機能を追加し、--scopes を持つコマンド (me oauth-clients create, me api-keys create, admin api-keys create/update) の NOTES セクションに全16リソーススコープと包含関係を表示。 * fix: E2E テストの config を v2 フォーマットで統一し認証フレーキーテストを修正 writeConfig() に v1→v2 自動ラップを追加し、CLI プロセスでの auto-migration(ファイル再書き込み)を不要にした。 これにより別プロセス間のファイル I/O タイミング問題を解消。 * docs: CHANGELOG に E2E フレーキーテスト修正を追記
1 parent f148d69 commit 649cffe

26 files changed

Lines changed: 107 additions & 17 deletions

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77

88
## [Unreleased]
99

10+
### 2026-03-17
11+
- **Feat**: `--scopes` オプションを持つコマンドのヘルプに有効なスコープ一覧を NOTES セクションとして追加 (#73)
12+
- **Docs**: README の Valid Scopes セクションを全18スコープに更新、包含関係と特殊スコープの説明を追加 (#73)
13+
- **Fix**: `admin api-keys create` の例で誤ったスコープ形式 (`entities:read`) を正しい形式 (`read:entities`) に修正 (#73)
14+
- **Fix**: E2E テストの config を v2 フォーマットで統一し、CLI プロセスでの auto-migration による認証フレーキーテストを修正 (#73)
15+
1016
## [0.6.2] - 2026-03-17
1117

1218
### 2026-03-17

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,11 @@ When both a Bearer token and an API key are configured, both headers are sent (t
564564

565565
### Valid Scopes
566566

567-
`read:entities`, `write:entities`, `read:subscriptions`, `write:subscriptions`, `read:registrations`, `write:registrations`
567+
`read:entities`, `write:entities`, `read:subscriptions`, `write:subscriptions`, `read:registrations`, `write:registrations`, `read:rules`, `write:rules`, `read:custom-data-models`, `write:custom-data-models`, `admin:users`, `admin:tenants`, `admin:policies`, `admin:oauth-clients`, `admin:api-keys`, `admin:metrics`
568+
569+
`write:X` implies `read:X`. `admin:X` implies both `read:X` and `write:X`.
570+
571+
Special scopes: `permanent` (no token expiry), `jwt` (JWT format token).
568572

569573
### Entity Type Restrictions
570574

src/commands/admin/api-keys.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { withErrorHandler, createClient, resolveOptions, getFormat, outputRespon
33
import { loadConfig, saveConfig } from "../../config.js";
44
import { parseJsonInput } from "../../input.js";
55
import { printError, printWarning } from "../../output.js";
6-
import { addExamples } from "../help.js";
6+
import { addExamples, addNotes } from "../help.js";
7+
import { SCOPES_HELP_NOTES } from "../../helpers.js";
78

89
function validateOrigins(body: unknown, opts: Record<string, unknown>): void {
910
// Validate origins if provided via flags
@@ -173,10 +174,12 @@ export function registerApiKeysCommand(parent: Command): void {
173174
}),
174175
);
175176

177+
addNotes(create, SCOPES_HELP_NOTES);
178+
176179
addExamples(create, [
177180
{
178181
description: "Create an API key with flags",
179-
command: "geonic admin api-keys create --name my-key --scopes entities:read,entities:write --origins '*'",
182+
command: "geonic admin api-keys create --name my-key --scopes read:entities,write:entities --origins '*'",
180183
},
181184
{
182185
description: "Create an API key with DPoP required",
@@ -237,6 +240,8 @@ export function registerApiKeysCommand(parent: Command): void {
237240
),
238241
);
239242

243+
addNotes(update, SCOPES_HELP_NOTES);
244+
240245
addExamples(update, [
241246
{
242247
description: "Update an API key name",

src/commands/help.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,16 @@ interface Example {
77
}
88

99
const examplesMap = new WeakMap<Command, Example[]>();
10+
const notesMap = new WeakMap<Command, string[]>();
1011

1112
export function addExamples(cmd: Command, examples: Example[]): void {
1213
examplesMap.set(cmd, examples);
1314
}
1415

16+
export function addNotes(cmd: Command, notes: string[]): void {
17+
notesMap.set(cmd, notes);
18+
}
19+
1520
function header(title: string): string {
1621
return chalk.yellow.bold(title);
1722
}
@@ -197,6 +202,17 @@ export function formatCommandDetails(
197202
}
198203
}
199204

205+
// NOTES
206+
const notes = notesMap.get(cmd);
207+
if (notes && notes.length > 0) {
208+
lines.push("");
209+
lines.push(header("NOTES"));
210+
lines.push("");
211+
for (const note of notes) {
212+
lines.push(` ${note}`);
213+
}
214+
}
215+
200216
// GLOBAL PARAMETERS
201217
lines.push("");
202218
lines.push(formatGlobalParameters(program));

src/commands/me-api-keys.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { withErrorHandler, createClient, resolveOptions, getFormat, outputRespon
33
import { loadConfig, saveConfig } from "../config.js";
44
import { parseJsonInput } from "../input.js";
55
import { printError, printWarning } from "../output.js";
6-
import { addExamples } from "./help.js";
6+
import { addExamples, addNotes } from "./help.js";
7+
import { SCOPES_HELP_NOTES } from "../helpers.js";
78

89
export function addMeApiKeysSubcommand(me: Command): void {
910
const apiKeys = me
@@ -127,6 +128,8 @@ export function addMeApiKeysSubcommand(me: Command): void {
127128
}),
128129
);
129130

131+
addNotes(create, SCOPES_HELP_NOTES);
132+
130133
addExamples(create, [
131134
{
132135
description: "Create an API key with flags",

src/commands/me-oauth-clients.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import { loadConfig, saveConfig, validateUrl } from "../config.js";
44
import { parseJsonInput } from "../input.js";
55
import { printSuccess, printError, printInfo, printWarning } from "../output.js";
66
import { clientCredentialsGrant } from "../oauth.js";
7-
import { addExamples } from "./help.js";
7+
import { addExamples, addNotes } from "./help.js";
8+
import { SCOPES_HELP_NOTES } from "../helpers.js";
89

910
export function addMeOAuthClientsSubcommand(me: Command): void {
1011
const oauthClients = me
@@ -106,6 +107,8 @@ export function addMeOAuthClientsSubcommand(me: Command): void {
106107
}),
107108
);
108109

110+
addNotes(create, SCOPES_HELP_NOTES);
111+
109112
addExamples(create, [
110113
{
111114
description: "Create an OAuth client with flags",

src/helpers.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@ import { DryRunSignal, GdbClient, GdbClientError } from "./client.js";
44
import { printError, printOutput, printCount } from "./output.js";
55
import type { ClientResponse, GlobalOptions, OutputFormat } from "./types.js";
66

7+
/**
8+
* Valid scope values for --scopes option help text.
9+
*/
10+
export const SCOPES_HELP_NOTES = [
11+
"Valid scopes:",
12+
" read:entities, write:entities, read:subscriptions, write:subscriptions,",
13+
" read:registrations, write:registrations, read:rules, write:rules,",
14+
" read:custom-data-models, write:custom-data-models,",
15+
" admin:users, admin:tenants, admin:policies, admin:oauth-clients,",
16+
" admin:api-keys, admin:metrics",
17+
"",
18+
"write:X implies read:X. admin:X implies both read:X and write:X.",
19+
];
20+
721
/**
822
* Resolve merged options from config + CLI flags.
923
*/

tests/admin-api-keys.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ vi.mock("../src/helpers.js", () => ({
77
getFormat: vi.fn(),
88
outputResponse: vi.fn(),
99
withErrorHandler: (fn: (...args: unknown[]) => unknown) => fn,
10+
SCOPES_HELP_NOTES: [],
1011
resolveOptions: vi.fn().mockReturnValue({ profile: "default" }),
1112
}));
1213

@@ -25,6 +26,7 @@ vi.mock("../src/output.js", () => ({
2526

2627
vi.mock("../src/commands/help.js", () => ({
2728
addExamples: vi.fn(),
29+
addNotes: vi.fn(),
2830
}));
2931

3032
vi.mock("../src/config.js", () => ({

tests/admin-oauth-clients.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ vi.mock("../src/helpers.js", () => ({
77
getFormat: vi.fn(),
88
outputResponse: vi.fn(),
99
withErrorHandler: (fn: (...args: unknown[]) => unknown) => fn,
10+
SCOPES_HELP_NOTES: [],
1011
resolveOptions: vi.fn(),
1112
}));
1213

@@ -25,6 +26,7 @@ vi.mock("../src/output.js", () => ({
2526

2627
vi.mock("../src/commands/help.js", () => ({
2728
addExamples: vi.fn(),
29+
addNotes: vi.fn(),
2830
}));
2931

3032
import { createClient, getFormat, outputResponse } from "../src/helpers.js";

tests/admin-policies.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ vi.mock("../src/helpers.js", () => ({
77
getFormat: vi.fn(),
88
outputResponse: vi.fn(),
99
withErrorHandler: (fn: (...args: unknown[]) => unknown) => fn,
10+
SCOPES_HELP_NOTES: [],
1011
resolveOptions: vi.fn(),
1112
}));
1213

@@ -25,6 +26,7 @@ vi.mock("../src/output.js", () => ({
2526

2627
vi.mock("../src/commands/help.js", () => ({
2728
addExamples: vi.fn(),
29+
addNotes: vi.fn(),
2830
}));
2931

3032
import { createClient, getFormat, outputResponse } from "../src/helpers.js";

0 commit comments

Comments
 (0)