Skip to content

feat(security): token-issuance UI + served agent-skill (server-verified step-up; anon agent skill)#1619

Merged
JasonWildMe merged 10 commits into
mainfrom
token-ui-agent-skill
Jun 19, 2026
Merged

feat(security): token-issuance UI + served agent-skill (server-verified step-up; anon agent skill)#1619
JasonWildMe merged 10 commits into
mainfrom
token-ui-agent-skill

Conversation

@JasonWildMe

Copy link
Copy Markdown
Collaborator

Summary

Builds on the token-scoped read API (merged in #1613) with two user-facing pieces:

A — Token-issuance UI. A logged-in user can mint a short-lived bearer token from a new API Access page (avatar menu → API Access). A password step-up is required and enforced server-side: AuthToken now requires and verifies a fresh HTTP Basic credential (User.checkPassword, constant-time, mirroring login) and rejects session-only mints — a stolen/unlocked session or same-origin script can no longer mint without the password. The React mint call uses a cookie-less fetch(credentials:"omit"); the token is shown once and held only in component state. Cache-Control: no-store on the response.

B — Served agent skill. GET /api/v3/agent-skill (anonymous) serves a curated markdown that teaches a user's AI agent the token-scoped API, the OpenSearch schema/fields, how to obtain a token, and — importantly — to never accept the user's username/password, only a short-lived token. A SearchApi.TOKEN_ALLOWED_INDICES constant was extracted so a drift-guard test pins the skill's index claims to the real allowlist; another test forbids leaking internal ACL field names.

What changed

  • User.checkPassword(clearText) — constant-time verify against the stored salted hash.
  • AuthToken — server-side step-up (fresh Basic required; session-only → 401; wrong password → 401), no-store, audit logging (no secrets).
  • AgentSkill servlet + src/main/resources/agent-skill.md + web.xml (anon rule, exact mapping).
  • SearchApi.TOKEN_ALLOWED_INDICES constant (behavior-preserving refactor of the inline allowlist).
  • Frontend: useMintToken (cookie-less, UTF-8 Basic), ApiAccessPage (step-up modal + one-time token display), /api-access route, avatar menu item.

Testing

  • Backend: 48 tests green (UserCheckPasswordTest, AuthTokenTest updated, AuthTokenStepUpTest, AgentSkillTest, EndpointAuthWiringTest, plus SearchApiTokenAuthTest/SearchApiChildIndexTest confirm the allowlist refactor didn't regress).
  • Frontend: useMintToken, ApiAccessPage, avatar-link tests green.
  • No package.json / package-lock.json changes.

Process

Brainstormed → spec → plan → subagent-driven implementation with per-task spec + code-quality review. Codex reviewed the design, the plan, and the final code (verdict: READY TO MERGE; the step-up bypass it flagged in the design was closed, and a UTF-8 Basic-encoding bug it caught in code review is fixed + tested).

Design spec + plan are included under docs/superpowers/.

🤖 Generated with Claude Code

JasonWildMe and others added 9 commits June 11, 2026 15:29
…eviewed)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ession-only

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…SearchApi allowlist constant + drift-guard

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Also adds missing @testing-library/dom peer dependency (required by
@testing-library/react@16; was absent, breaking all RTL-based tests).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…d username, copy fix

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@codecov-commenter

codecov-commenter commented Jun 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 74.19355% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 51.63%. Comparing base (cd55bfc) to head (367ea0f).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
frontend/src/pages/ApiAccess/ApiAccessPage.jsx 78.04% 8 Missing and 1 partial ⚠️
frontend/src/models/auth/useMintToken.js 65.00% 7 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1619      +/-   ##
==========================================
+ Coverage   51.50%   51.63%   +0.13%     
==========================================
  Files         308      310       +2     
  Lines       12100    12162      +62     
  Branches     3920     3933      +13     
==========================================
+ Hits         6232     6280      +48     
- Misses       5578     5598      +20     
+ Partials      290      284       -6     
Flag Coverage Δ
backend 51.63% <74.19%> (+0.13%) ⬆️
frontend 51.63% <74.19%> (+0.13%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…ces section

The served skill said "See the field reference for full descriptions" but no
such document or endpoint exists. Reword to own the inline field list, and add
a References section linking the general Wildbook docs (wildbook.docs.wildme.org)
while marking this skill authoritative for the token API where the two differ.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@erinz2020

erinz2020 commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

I tried on QA and tested curl -i "https://qa.wildme.org/api/v3/agent-skill", it successfully responded with instructions for AI, but when I opened the generate token page and tried to enter password and confirm, it always shows incorrect password, which is weird because i used the same password to login. I also tried to generate token thru command line: curl -i -X POST
-u 'USERNAME:PASSWORD'
https://qa.wildme.org/api/v3/auth/token using the same password, it did not work either. not sure what this means "Incorrect password. If your account uses single sign-on, API tokens aren't available yet."

image image

@naknomum naknomum left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

focused on code review of backend/java, and looks good.
only cursory examination of frontend/react additions, however.

@erinz2020 erinz2020 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

looks good to me

@JasonWildMe JasonWildMe merged commit 420e4f8 into main Jun 19, 2026
3 checks passed
@JasonWildMe JasonWildMe deleted the token-ui-agent-skill branch June 19, 2026 16:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants