Skip to content

feat(auth): runtime hub token override with no-restart Lua push#350

Open
skhaz wants to merge 2 commits into
mainfrom
feat/hub-runtime-token
Open

feat(auth): runtime hub token override with no-restart Lua push#350
skhaz wants to merge 2 commits into
mainfrom
feat/hub-runtime-token

Conversation

@skhaz

@skhaz skhaz commented Jun 15, 2026

Copy link
Copy Markdown
Member

Why

Remote instances could only authenticate to the module registry/hub by running wippy auth login and restarting the process — the credential is read through Store.Get with no runtime path to set it. There was also no way for a UI to know auth state / org access.

What

  • Process-global token override consulted first by Store.Get (precedence override > env > file). Every hub consumer already reads through Store.Get, so a pushed token takes effect live, no restart, with no call-site changes.
  • hub.auth.set_token / hub.auth.clear_token Lua bindings, permission-gated via security.IsAllowed and validated with ValidateTokenFormat.
  • hub.auth.status([registry]) for UI: live validate returning { authenticated, registry, orgs = [{id,name,display_name,role}] }, plus username/user_id/scope/expires_at/expired only when authenticated (never leaked on a rejected token). Invalid/expired token → authenticated=false; transport failure → error.
  • Actionable 401 hint: ResolutionError carries its cause; dependency resolution surfaces how to authenticate when it fails unauthenticated.

No Keycloak/OAuth: a wpy_ token is sufficient for instance→registry auth. Registry resolution stays at the boundary (Store.Get / the Lua handler), never inside the override store.

Note: identity fields in status come from a login/file credential; the WIPPY_TOKEN/runtime-push path carries only the token, so on that path status returns authenticated=true with orgs but without the optional identity fields.

Testing

  • go test -race green: boot/deps/auth, boot/deps/hub, runtime/lua/modules/hub (override precedence/concurrency, the Lua bindings incl. permission-denied, status happy/not-authed/invalid-token-identity-suppression, and the 401 hint).
  • golangci-lint v2.8.0 ... ./... → 0 issues.
  • make build-wippy → binary runs.
  • Mutation (gremlins, boot/deps/auth): all mutants in the new code killed.

Draft.

skhaz added 2 commits June 15, 2026 14:48
Why:
Remote instances could only authenticate to the module registry/hub by
running `wippy auth login` and restarting the process, because the
credential is read through Store.Get with no way to set it at runtime.

What:
Add a process-global credential override consulted first by Store.Get
(precedence override > env > file), so a token takes effect live on the
next call with no restart. Every hub consumer already reads through
Store.Get, so all inherit it without call-site changes.

How:
- boot/deps/auth/runtime.go: SetRuntimeToken/ClearRuntimeToken/runtimeToken,
  guarded by a RWMutex, keyed by registry. Registry resolution stays at the
  boundary (Store.Get / the Lua handler), never inside the override store.
- runtime/lua/modules/hub: hub.auth.set_token/clear_token, permission-gated
  via security.IsAllowed and validated with ValidateTokenFormat.
- boot/deps/hub: preserve the cause on ResolutionError and surface an
  actionable hint when resolution fails unauthenticated.
Why:
A UI needs to show whether an instance is authenticated to the registry
and which orgs/roles the token grants, without handling the token itself.

What:
Add hub.auth.status([registry]): a permission-gated Lua call that does a
live validate against the registry and returns authentication state plus
org/role access for the current credential.

How:
- runtime/lua/modules/hub: authStatus resolves the registry, gates via
  security.IsAllowed, reads the credential, and calls the registry
  Validate endpoint. Returns {authenticated, registry, orgs=[{id,name,
  display_name,role}]}; identity fields (username/user_id/scope/expires_at)
  are included only when authenticated, never leaked on a rejected token.
- Invalid/expired/insufficient-scope -> authenticated=false; transport
  failures -> error.
@skhaz skhaz marked this pull request as ready for review June 15, 2026 18:08
@skhaz skhaz requested a review from wolfy-j June 15, 2026 18:14
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