feat(auth): runtime hub token override with no-restart Lua push#350
Open
skhaz wants to merge 2 commits into
Open
feat(auth): runtime hub token override with no-restart Lua push#350skhaz wants to merge 2 commits into
skhaz wants to merge 2 commits into
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Remote instances could only authenticate to the module registry/hub by running
wippy auth loginand restarting the process — the credential is read throughStore.Getwith no runtime path to set it. There was also no way for a UI to know auth state / org access.What
Store.Get(precedence override > env > file). Every hub consumer already reads throughStore.Get, so a pushed token takes effect live, no restart, with no call-site changes.hub.auth.set_token/hub.auth.clear_tokenLua bindings, permission-gated viasecurity.IsAllowedand validated withValidateTokenFormat.hub.auth.status([registry])for UI: live validate returning{ authenticated, registry, orgs = [{id,name,display_name,role}] }, plususername/user_id/scope/expires_at/expiredonly when authenticated (never leaked on a rejected token). Invalid/expired token →authenticated=false; transport failure → error.ResolutionErrorcarries 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
statuscome from a login/file credential; theWIPPY_TOKEN/runtime-push path carries only the token, so on that pathstatusreturnsauthenticated=truewithorgsbut without the optional identity fields.Testing
go test -racegreen:boot/deps/auth,boot/deps/hub,runtime/lua/modules/hub(override precedence/concurrency, the Lua bindings incl. permission-denied,statushappy/not-authed/invalid-token-identity-suppression, and the 401 hint).golangci-lint v2.8.0 ... ./...→ 0 issues.make build-wippy→ binary runs.gremlins,boot/deps/auth): all mutants in the new code killed.Draft.