Conversation
…t on CA rotation Two teamserver user/cert bugs found while exercising Sliver's multiplayer path: UserCreate inserted a new db.User row on every call (Name has no unique index; Save with a zero PK always inserts), so re-provisioning the same operator name accumulated duplicate identities. Since the authorization model is keyed by Name, duplicates make per-user state (last-seen, online, permissions) ambiguous. UserCreate now deletes any user(s) holding the requested name before inserting, i.e. re-creating a user rotates its credentials in place and collapses any pre-existing duplicates to a single record. The token cache is reset so the old token stops authenticating. UsersTLSConfig only regenerated the server certificate when it was entirely absent (ErrCertDoesNotExist). After a users-CA rotation the server kept presenting an orphaned cert that no longer chained to the live CA, so every remote handshake failed with "tls: bad certificate" while clients (carrying the new CA) rejected it. It now verifies the cached server cert still chains to the current users-CA and is within its validity window (serverCertValidFor), regenerating and reloading it otherwise, so the daemon self-heals on restart. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The users table printed a zero LastSeen (a user that never authenticated)
as the raw zero time.Time, i.e. a confusing "Mon, 01 Jan 0001 ..." date,
and a freshly-seen user as a bare "0s" that reads like "never". Print
"never" for a zero LastSeen and suffix the duration with " ago" ("0s ago")
so the two cases are unambiguous.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The team library authenticates identity; authorization is the application's. Authorizer lets an app plug one authorization policy that can gate any path to a capability (a gRPC interceptor, a detached task, an event handler), closing the gap where authz is bolted onto one transport and bypassed by another.
Promote the gRPC teamserver transport out of example/ into a supported,
importable package based on the production Sliver transport, and add a
run-mode runner so a single binary cleanly separates client and server.
transports/grpc/server (team/server.Handler):
- buffering, panic recovery, audit via AuditLogger(), mTLS, and token
authentication (Server.Authenticate -> *team.User in context)
- PostServe(hook) to register application services; WithAuthorizer(team.Authorizer)
to install an authorization interceptor; exported ServeOn(ln) so custom-listener
transports (e.g. tsnet) reuse the whole stack
- WithCoreServices() registers the built-in Team users/version RPC
transports/grpc/client (team/client.Dialer):
- TLS-if-creds dialing; exposes the *grpc.ClientConn via Conn()/PostDial so apps
register their own service clients on the shared connection
- implements team.Client (Users/VersionServer) against the core Team service
transports/grpc/proto: teamgrpc package (distinct proto pkg/file name to avoid
global-registry collision with the example transport).
client.SystemConfig(): locate the <app>_<user>_default.teamclient.cfg written by
'teamserver user --system' -- the artifact that drives thin-client detection.
boot.Run(Boot{App, ForceServer, Config, Client, Server}): resolve the run mode
with no server/database side effects and invoke exactly one callback, so the
teamserver (and its DB) is only ever constructed in server mode.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
| return nil | ||
| } | ||
|
|
||
| func (h *Handler) ServeOn(ln net.Listener) { |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #28 +/- ##
==========================================
- Coverage 29.59% 26.36% -3.23%
==========================================
Files 61 69 +8
Lines 4017 4600 +583
==========================================
+ Hits 1189 1213 +24
- Misses 2695 3247 +552
- Partials 133 140 +7 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
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.
Summary
Four commits on
dev:example/into a supportedtransports/grpc/{server,client,proto}package (mTLS, token auth, audit, panic recovery,PostServe/PostDialhooks,ServeOnfor custom listeners). Addsboot.Run()so a single binary resolves client/server run mode with no server/DB side effects, andclient.SystemConfig().Authorizerinterface — the library authenticates identity; authorization stays the app's. One policy can gate any path to a capability, instead of being bolted onto a single transport and bypassed by another.LastSeenas "never" and suffix durations with " ago", so a never-authenticated user no longer prints asMon, 01 Jan 0001 ….UserCreate; self-heal server cert on CA rotation — re-creating a user now rotates credentials in place instead of accumulating duplicate rows, andUsersTLSConfigregenerates a server cert that no longer chains to the live CA.Test plan
go build ./...andgo test ./...pass locally on the default (pure-Go WASM SQLite) backend.🤖 Generated with Claude Code