Skip to content

fix(web): acquire bearer token in useEntityForm before create/update#82

Merged
christopherhouse merged 1 commit into
mainfrom
fix/registry-entity-form-token
Jun 17, 2026
Merged

fix(web): acquire bearer token in useEntityForm before create/update#82
christopherhouse merged 1 commit into
mainfrom
fix/registry-entity-form-token

Conversation

@christopherhouse

Copy link
Copy Markdown
Contributor

Summary

POST/PUT against /api/registry from the spec-006 registry forms (namespace create, queue/topic/sub/rule create + edit) returned 401 with no Bearer header on the request. useEntityForm accepted an apiOptions prop carrying the access token, but neither namespace-form.tsx nor child-entity-form.tsx ever passed it. The registry api client builds headers without Authorization: Bearer when options.accessToken is undefined, so the backend's RequireAuthorization() gate (FR-037 AuthN-only) returned 401 before any handler ran.

Same pattern as the spec-008 namespace forms which already use useAcquireToken() internally — this fix brings the spec-006 form hook up to the same standard.

Fix

Inside useEntityForm:

const getToken = useAcquireToken();
// ...inside submit:
let resolvedApiOptions = apiOptions;
if (!resolvedApiOptions?.accessToken) {
  const token = await getToken();
  if (token) {
    resolvedApiOptions = { ...(apiOptions ?? {}), accessToken: token };
  }
}
// then pass resolvedApiOptions to createEntity / updateEntity

External callers can still pass apiOptions.accessToken to override (the explicit-token path is documented in web/lib/api-client.ts).

Test plan

  • pnpm typecheck clean
  • After CD-dev rolls forward: open Namespace Create form on /registry, submit, expect 201 (not 401)

Risk

None — additive token acquisition inside the existing submit path, no schema change, no backend change.

🤖 Generated with Claude Code

The registry create + edit forms on the spec-006 polymorphic surface
were sending POST /api/registry and PUT /api/registry/{id} without an
Authorization header, getting a 401 back. Root cause: useEntityForm
accepted an apiOptions prop carrying the access token, but neither
namespace-form.tsx nor child-entity-form.tsx ever passed it. With no
explicit accessToken, the registry api client built headers without
Bearer auth, and the api endpoint group's RequireAuthorization() gate
rejected the request before it reached the handler.

Fix: call useAcquireToken() inside the hook and stamp the token into a
resolvedApiOptions wrapper before invoking createEntity / updateEntity.
External callers can still pass apiOptions with their own accessToken
to override (the explicit-token path the api-client comment documents).

No backend change. No new dependency. Same pattern as the spec-008
namespace forms (use-acquire-token + apiOptions composition).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@christopherhouse christopherhouse merged commit 0b3e5ec into main Jun 17, 2026
6 checks passed
@christopherhouse christopherhouse deleted the fix/registry-entity-form-token branch June 17, 2026 01:21
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.

1 participant