Skip to content

feat: me policies / me api-keys oauth-clients update / XACML docs (v0.8.0)#87

Merged
miya0001 merged 5 commits into
mainfrom
issues/83-84-85-86
Mar 22, 2026
Merged

feat: me policies / me api-keys oauth-clients update / XACML docs (v0.8.0)#87
miya0001 merged 5 commits into
mainfrom
issues/83-84-85-86

Conversation

@miya0001

@miya0001 miya0001 commented Mar 22, 2026

Copy link
Copy Markdown
Member

Summary

Test plan

  • npm test — 653 tests passed
  • npm run lint — clean
  • npm run typecheck — clean

Summary by CodeRabbit

  • 新機能

    • me policies を追加:個人ポリシーの一覧/取得/作成/更新/削除をCLIで操作可能に
    • me api-keys update を追加:名前/ポリシー/発信元/レート制限/DPoP/有効化を更新可能に
    • me oauth-clients updateme oauth-clients regenerate-secret を追加:クライアント更新とシークレット再生成をCLIで実行可能に
  • ドキュメント

    • README 更新:各コマンドのフラグ、ポリシーの制約、認可モデルの優先度説明を追加
  • テスト

    • 追加した各コマンド向けの包括的なテストを追加
  • その他

    • CHANGELOG に v0.8.0 のリリース記載を追加

@coderabbitai

coderabbitai Bot commented Mar 22, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: deb85d1b-55a1-4554-981d-ede590cf928c

📥 Commits

Reviewing files that changed from the base of the PR and between 87bf84d and d949871.

📒 Files selected for processing (5)
  • README.md
  • src/commands/me-api-keys.ts
  • src/commands/me-policies.ts
  • tests/me-api-keys.test.ts
  • tests/me-policies.test.ts
✅ Files skipped from review due to trivial changes (2)
  • tests/me-policies.test.ts
  • README.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • tests/me-api-keys.test.ts
  • src/commands/me-api-keys.ts
  • src/commands/me-policies.ts

📝 Walkthrough

Walkthrough

me policies の自己サービスコマンド群を追加し、me api-keys updateme oauth-clients update/regenerate-secret を実装、README と CHANGLEOG を更新してポリシー優先度体系と利用制約を明記しました。

Changes

Cohort / File(s) Summary
リリース情報
CHANGELOG.md
## [0.8.0] - 2026-03-23 を追加し、新コマンド群と README 更新を記載。[Unreleased] 比較範囲を v0.8.0...HEAD に更新し、[0.8.0] 比較リンクを追加。
ドキュメント
README.md
認可モデルを「小さい値 = 高優先度」に修正、tenant_admin と user デフォルトの説明を更新。me policiesme api-keys update / me oauth-clients update / regenerate-secret のフラグ・挙動(--policy-id の null/unbind、DPoP、rate-limit、active/inactive 等)を追記。
ヘルプ更新
src/commands/admin/policies.ts
admin policies create ヘルプ文言を「優先度は小さい値が高優先」に修正し、デフォルトポリシー群の説明を更新。
コマンド登録
src/commands/auth.ts
addMePoliciesSubcommand(me) を呼び出し、me policies サブコマンド群を CLI に登録。
API キー - 実装
src/commands/me-api-keys.ts
me api-keys update <keyId> [json] を追加。JSON またはフラグ入力を PATCH /me/api-keys/:keyId に変換(--policy-id "null"policyId:null--origins→配列、--rate-limitrateLimit.perMinute--dpop-required/--no-dpop-required--active/--inactive)、入力検証とエラーメッセージを実装。
OAuth クライアント - 実装
src/commands/me-oauth-clients.ts
me oauth-clients update <clientId> [json] を追加(JSON またはフラグ→PATCH /me/oauth-clients/{clientId})。me oauth-clients regenerate-secret <clientId> を追加(POST /me/oauth-clients/{clientId}/regenerate-secret)。成功/警告メッセージ出力を追加。
ポリシー自己サービス
src/commands/me-policies.ts
新規モジュールで me policies list/get/create/update/delete を実装。/me/policies エンドポイントと連携、URI エンコード、JSON 入力(引数/STDIN)、成功メッセージを含む。
テスト — API キー
tests/me-api-keys.test.ts
me api-keys update の JSON/フラグ由来ボディ、--policy-id null--rate-limit 検証、--origins 空文字検出、URI エンコード、出力動作をカバー。
テスト — OAuth クライアント
tests/me-oauth-clients.test.ts
me oauth-clients updateregenerate-secret の PATCH/POST、フラグ解析、--policy-id null、URI エンコード、出力(警告・成功)をカバー。
テスト — ポリシー
tests/me-policies.test.ts
me policies の list/get/create/update/delete を網羅。HTTP 呼び出し、JSON パース、URI エンコード、成功メッセージを検証。

Sequence Diagram

sequenceDiagram
    participant User as User (CLI)
    participant CLI as geonic CLI
    participant Client as HTTP Client
    participant API as Geonic API (/me/*)

    User->>CLI: geonic me policies create [json]
    CLI->>CLI: parseJsonInput / assemble body
    CLI->>Client: POST /me/policies (body)
    Client->>API: POST /me/policies
    API-->>Client: 201 + Policy JSON
    Client-->>CLI: response
    CLI->>User: outputResponse + "Policy created."

    User->>CLI: geonic me api-keys update keyId --policy-id p --rate-limit 60
    CLI->>CLI: validate flags / assemble body
    CLI->>Client: PATCH /me/api-keys/{keyId} (body)
    Client->>API: PATCH /me/api-keys/{keyId}
    API-->>Client: 200 + Updated ApiKey
    Client-->>CLI: response
    CLI->>User: outputResponse + "API key updated."

    User->>CLI: geonic me oauth-clients regenerate-secret clientId
    CLI->>Client: POST /me/oauth-clients/{clientId}/regenerate-secret
    Client->>API: POST /me/oauth-clients/{clientId}/regenerate-secret
    API-->>Client: 200 + Secret JSON
    Client-->>CLI: response
    CLI->>User: printWarning + outputResponse + "OAuth client secret regenerated."
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰✨ ポリシーを作ってぴょんと跳ねる
キーもクライアントも自分で変えるよ
/me で管理、自由に結び直す
小さな数字が強いんだってさ、へへん
新しいリリースに耳をすますよ 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately reflects the main changes: new me policies commands, me api-keys update and me oauth-clients update/regenerate-secret functionality, and XACML documentation updates with version bump to v0.8.0.
Linked Issues check ✅ Passed All linked issues (#83, #85, #84) are fully addressed: me policies CRUD commands implemented [#83], PATCH endpoints for api-keys and oauth-clients with policy binding support added [#85], and XACML documentation updated with corrected priority semantics [#84].
Out of Scope Changes check ✅ Passed All changes are within scope of linked issues. PR includes new CLI commands, API integrations, documentation updates, test coverage, and dependency version bump—all directly aligned with #83, #85, and #84 objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issues/83-84-85-86

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
tests/me-api-keys.test.ts (1)

454-470: --rate-limit 0 の境界値テストも追加した方が安全です。

非整数は検証されていますが、0 も「正の整数」違反として落とす期待値を固定しておくと、実装との不整合を防げます。

テスト追加例
+    it("rejects zero --rate-limit", async () => {
+      const isTTY = process.stdin.isTTY;
+      process.stdin.isTTY = true;
+      try {
+        const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
+          throw new Error("process.exit");
+        });
+        const program = makeProgram();
+        await expect(
+          runCommand(program, ["me", "api-keys", "update", "k1", "--rate-limit", "0"])
+        ).rejects.toThrow("process.exit");
+        expect(printError).toHaveBeenCalledWith("--rate-limit must be a positive integer.");
+        exitSpy.mockRestore();
+      } finally {
+        process.stdin.isTTY = isTTY;
+      }
+    });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/me-api-keys.test.ts` around lines 454 - 470, Add a new test mirroring
the existing "rejects non-integer --rate-limit" case that asserts "--rate-limit
0" is rejected as not a positive integer: create an it block (e.g., it("rejects
zero --rate-limit", ...)) that temporarily sets process.stdin.isTTY to true,
spies process.exit to throw (via vi.spyOn(process, "exit").mockImplementation(()
=> { throw new Error("process.exit"); })), calls runCommand(makeProgram(),
["me","api-keys","update","k1","--rate-limit","0"]) and expects it to reject
with "process.exit", and checks printError was called with "--rate-limit must be
a positive integer."; ensure you restore the exit spy and reset
process.stdin.isTTY in a finally block similar to the existing test.
src/commands/me-oauth-clients.ts (1)

139-140: --active--inactive の同時指定は明示的に拒否した方がよいです。

現在は両方指定すると isActive: false で静かに上書きされます。入力ミスを早期検知できるよう、同時指定時にエラー終了する分岐を入れることを推奨します。

修正案
         const opts = cmd.opts() as {
           name?: string;
           description?: string;
           policyId?: string;
           active?: boolean;
           inactive?: boolean;
         };

+        if (opts.active && opts.inactive) {
+          printError("--active and --inactive cannot be used together.");
+          process.exit(1);
+        }
+
         let body: unknown;

Also applies to: 159-160

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/me-oauth-clients.ts` around lines 139 - 140, Add an explicit
check that prevents simultaneous use of the --active and --inactive options:
after parsing options in the command's action/handler (the code that consumes
the option declarations for "--active" and "--inactive" in
src/commands/me-oauth-clients.ts), detect if both opts.active and opts.inactive
are true and exit with an error (throw an Error or call process.exit(1) after
printing a clear message via the CLI logger). This check should be placed before
you compute or set isActive so the conflicting inputs are rejected early; apply
the same logic to the other command block that defines the same options.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@CHANGELOG.md`:
- Around line 10-13: The changelog entry for "## [0.8.0] - 2026-03-23" is using
a future fixed release date; either move the entire "0.8.0" section under the
"Unreleased" heading or change the date to the actual release date only when
publishing (do not hardcode 2026-03-23 now). Locate the heading "## [0.8.0] -
2026-03-23" and update it to "## [0.8.0] - Unreleased" (or remove the date
entirely) until you are ready to tag the release, or set the date to 2026-03-22
only at release time. Ensure the rest of the list (the `me policies` bullet)
stays under that adjusted heading.

In `@README.md`:
- Line 273: The README contains a contradiction between the statement that
`priority` is fixed at 100 and the `/me/policies` section that says `101+`; pick
the correct rule and make both places consistent: either change the "priority is
fixed at 100" wording to explain the user-role minimum and that `/me/policies`
requires 101+ (or vice versa), and update both occurrences (the `priority`
description and the `/me/policies` policy text) so they state the same numeric
requirement and a short clarifying sentence about precedence.

In `@src/commands/me-api-keys.ts`:
- Around line 182-187: Change the truthy check of opts.origins to an explicit
undefined check and reject empty input: replace conditions using "opts.origins"
with "opts.origins !== undefined" and when building payload.allowedOrigins guard
for empty-string input (e.g. if opts.origins === "" or the split yields an empty
array) and raise/emit an explicit error instead of falling through to
parseJsonInput(); update the same pattern around the other occurrences (the
block referenced at lines ~199-201) so both the update branch and any similar
branches treat "--origins \"\"" as invalid and do not defer to parseJsonInput().
- Around line 188-195: The rate-limit parsing allows "0" even though the message
says "positive integer"; update the block that handles opts.rateLimit so after
trimming and numeric check you parse Number(raw) into a variable (e.g., const
perMinute = Number(raw)) and reject it if perMinute <= 0 by calling
printError("--rate-limit must be a positive integer.") and process.exit(1); then
assign payload.rateLimit = { perMinute } only when perMinute > 0. Reference:
opts.rateLimit, payload.rateLimit, perMinute.

In `@src/commands/me-policies.ts`:
- Around line 56-58: The create subcommand currently tied to the CLI command
builder (policies.command("create [json]") and related handlers around the
create flow) only accepts a JSON payload and lacks flag-based inputs required by
Issue `#83`; update the command registration and handler to accept explicit flags
(e.g., --policy-id, --description, --rules, --overwrite) alongside or instead of
the single [json] positional, parse those flags in the create handler (the
function that processes the "create" command) and build the policy object from
flags when JSON is not provided, add validation and precedence rules (flags
override or are used when json is absent), and apply the same change to the
similar create/update code paths referenced around the other block (the code
near lines 109-111) so users can create/update policies via flags without
needing raw JSON.

---

Nitpick comments:
In `@src/commands/me-oauth-clients.ts`:
- Around line 139-140: Add an explicit check that prevents simultaneous use of
the --active and --inactive options: after parsing options in the command's
action/handler (the code that consumes the option declarations for "--active"
and "--inactive" in src/commands/me-oauth-clients.ts), detect if both
opts.active and opts.inactive are true and exit with an error (throw an Error or
call process.exit(1) after printing a clear message via the CLI logger). This
check should be placed before you compute or set isActive so the conflicting
inputs are rejected early; apply the same logic to the other command block that
defines the same options.

In `@tests/me-api-keys.test.ts`:
- Around line 454-470: Add a new test mirroring the existing "rejects
non-integer --rate-limit" case that asserts "--rate-limit 0" is rejected as not
a positive integer: create an it block (e.g., it("rejects zero --rate-limit",
...)) that temporarily sets process.stdin.isTTY to true, spies process.exit to
throw (via vi.spyOn(process, "exit").mockImplementation(() => { throw new
Error("process.exit"); })), calls runCommand(makeProgram(),
["me","api-keys","update","k1","--rate-limit","0"]) and expects it to reject
with "process.exit", and checks printError was called with "--rate-limit must be
a positive integer."; ensure you restore the exit spy and reset
process.stdin.isTTY in a finally block similar to the existing test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 41f84fd1-0273-4f81-845b-6af414c0a42d

📥 Commits

Reviewing files that changed from the base of the PR and between b9f6da6 and 87bf84d.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (10)
  • CHANGELOG.md
  • README.md
  • src/commands/admin/policies.ts
  • src/commands/auth.ts
  • src/commands/me-api-keys.ts
  • src/commands/me-oauth-clients.ts
  • src/commands/me-policies.ts
  • tests/me-api-keys.test.ts
  • tests/me-oauth-clients.test.ts
  • tests/me-policies.test.ts

Comment thread CHANGELOG.md
Comment on lines +10 to +13
## [0.8.0] - 2026-03-23

### 2026-03-23
- **Feat**: `me policies` コマンド群を新設 — `list`, `get`, `create`, `update`, `delete` で `/me/policies` セルフサービスポリシー管理に対応 (GeonicDB #764) (#83, #86)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

リリース日が未来日付で固定されています。

このPR時点(2026-03-22)で 0.8.02026-03-23 と確定すると、未リリース状態との整合が崩れやすいです。リリース当日確定にするか、Unreleased 側で保持する運用が安全です。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CHANGELOG.md` around lines 10 - 13, The changelog entry for "## [0.8.0] -
2026-03-23" is using a future fixed release date; either move the entire "0.8.0"
section under the "Unreleased" heading or change the date to the actual release
date only when publishing (do not hardcode 2026-03-23 now). Locate the heading
"## [0.8.0] - 2026-03-23" and update it to "## [0.8.0] - Unreleased" (or remove
the date entirely) until you are ready to tag the release, or set the date to
2026-03-22 only at release time. Ensure the rest of the list (the `me policies`
bullet) stays under that adjusted heading.

Comment thread README.md
Comment thread src/commands/me-api-keys.ts Outdated
Comment thread src/commands/me-api-keys.ts
Comment thread src/commands/me-policies.ts

@miya0001 miya0001 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

coderabbit のレビューに対応しました(d949871)。

CHANGELOG 日付について
今日 2026-03-23 にリリース予定なので据え置きます。

README priority 矛盾(100固定 vs 101+
サーバー実装(createPolicyForUser)を確認し、/me/policies で作成されるポリシーの priority は 100 固定であることを確認。priority テーブルの 101+ 行を 100 に統合しました。

--origins "" が空チェックをすり抜けるバグ
opts.origins !== undefined で判定するよう修正し、空文字の場合は早期にエラーを出すよう対応しました。

--rate-limit 0 が通ってしまうバグ
perMinute <= 0 のチェックを追加しました。

me policies create/update のフラグ不足
me policies create--policy-id--description フラグを追加、me policies update--description フラグを追加しました。rules/target はネスト構造が複雑なため JSON 入力のみとしています。

@miya0001
miya0001 merged commit 2474c4b into main Mar 22, 2026
7 checks passed
@miya0001
miya0001 deleted the issues/83-84-85-86 branch March 22, 2026 17:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant