- migration 0012: workers.owner_id + trust_level (trusted/untrusted) - verifier/authctx read the JWT verified claim; IsTrusted() = admin||verified - /workers/register resolves trust from auth: service token or verified/admin JWT -> trusted; plain user JWT -> untrusted, tagged with owner_id - claim quarantines untrusted workers (no tasks) until quorum (C2) lands - unit tests for trust resolution, quarantine, and the verified claim Additive and backward compatible: shared-token workers stay trusted, so the existing worker flow and team tests are unchanged. Quorum verification (C2) is deferred.
44 lines
1.5 KiB
Go
44 lines
1.5 KiB
Go
// Package authctx carries the authenticated requester across the transport and
|
|
// use-case layers without either one importing the other. The HTTP middleware
|
|
// stamps a Requester after verifying a user's JWT; the job use cases read it to
|
|
// record ownership and to enforce that a non-admin only touches their own jobs.
|
|
package authctx
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// Requester is the identity behind a request, derived from a verified JWT.
|
|
// A request authenticated only by the shared worker/service token carries no
|
|
// Requester at all (From returns ok=false), which is how worker traffic and
|
|
// legacy unauthenticated-user traffic stay owner-less.
|
|
type Requester struct {
|
|
UserID uuid.UUID
|
|
Role string
|
|
Verified bool
|
|
}
|
|
|
|
// IsAdmin reports whether the requester may act on any user's jobs.
|
|
func (r Requester) IsAdmin() bool { return r.Role == "admin" }
|
|
|
|
// IsTrusted reports whether workers this requester registers produce results
|
|
// the coordinator accepts without quorum. Admins and verified contributors are
|
|
// trusted; a plain unverified user is not.
|
|
func (r Requester) IsTrusted() bool { return r.IsAdmin() || r.Verified }
|
|
|
|
type ctxKey struct{}
|
|
|
|
// With returns a copy of ctx carrying r.
|
|
func With(ctx context.Context, r Requester) context.Context {
|
|
return context.WithValue(ctx, ctxKey{}, r)
|
|
}
|
|
|
|
// From returns the requester stamped by the middleware, or ok=false when the
|
|
// request was not authenticated as a user.
|
|
func From(ctx context.Context) (Requester, bool) {
|
|
r, ok := ctx.Value(ctxKey{}).(Requester)
|
|
return r, ok
|
|
}
|