fix(pier): widen returning identities, warm the Redis store, end stateless listen streams, refuse personal tokens without a TokenID
- Identity.fingerprint covers scopes, both subjects, the ceiling and the token kind; a stateful lookup or stateless hit whose fingerprint changed re-filters the server with the event diff under its own mutex (A-WR-04) - Mount warms a Redis store in the background with a 1 s to 30 s backoff and every request kicks a pending open without waiting, so stateless-only instances subscribe to fan-out (A-WR-05) - a stateless subscriptions/listen POST re-verifies its bearer every recheck interval; an LRU-evicted stateless server closes its sessions (A-WR-06) - resolvePersonalToken refuses a subject with TokenID 0, and the pact.MCPPersonalTokenResolver contract says one resolver per application, false means unauthorized and TokenID keys the binding (A-WR-09, A-IN-03)
This commit is contained in:
@@ -79,6 +79,7 @@ func (p *Pier) recomputeSession(ctx context.Context, ls *localSession, relink bo
|
||||
}
|
||||
tools, prompts := p.catalog.allowed(ctx, id)
|
||||
applyDiff(ls.server, p, id, tools, prompts, ls.tools, ls.prompts)
|
||||
ls.fingerprint = id.fingerprint()
|
||||
ls.mu.Unlock()
|
||||
}
|
||||
|
||||
@@ -92,9 +93,28 @@ func (p *Pier) recomputeStateless(ctx context.Context, e *statelessEntry, relink
|
||||
}
|
||||
tools, prompts := p.catalog.allowed(ctx, id)
|
||||
applyDiff(e.server, p, id, tools, prompts, e.tools, e.prompts)
|
||||
e.fingerprint = id.fingerprint()
|
||||
e.mu.Unlock()
|
||||
}
|
||||
|
||||
// widen re-filters a cached server for the identity of the request that
|
||||
// reached it when that identity's fingerprint differs from the one the
|
||||
// server was last filtered for (A-WR-04): a binding that returns with more
|
||||
// scope, or with a backend subject added, gains the newly allowed tools and
|
||||
// prompts at once, and one that returns with less loses them. The caller
|
||||
// holds the session's or entry's own mutex, never a router-wide one.
|
||||
func (p *Pier) widen(ctx context.Context, srv serverFeatures, id Identity, fp *string, haveTools, havePrompts map[string]bool) {
|
||||
next := id.fingerprint()
|
||||
if *fp == next {
|
||||
return
|
||||
}
|
||||
// A client that hangs up mid-check must not leave the server filtered
|
||||
// by cancelled guard checks (an error hides the item).
|
||||
tools, prompts := p.catalog.allowed(context.WithoutCancel(ctx), id)
|
||||
applyDiff(srv, p, id, tools, prompts, haveTools, havePrompts)
|
||||
*fp = next
|
||||
}
|
||||
|
||||
// applyDiff brings a server's tool and prompt sets to the allowed ones,
|
||||
// updating the tracking maps in place.
|
||||
func applyDiff(srv serverFeatures, p *Pier, id Identity, tools []*tool, prompts []*prompt, haveTools, havePrompts map[string]bool) {
|
||||
|
||||
Reference in New Issue
Block a user