diff --git a/services/wspr/internal/app/app.go b/services/wspr/internal/app/app.go
index 2f592c9..812fcd6 100644
--- a/services/wspr/internal/app/app.go
+++ b/services/wspr/internal/app/app.go
@@ -779,9 +779,9 @@
 	return encKey, handle, err
 }
 
-// PutToBlessingStore puts a blessing with the provided name to the blessing store
-// with the specified blessing pattern.
-func (c *Controller) PutToBlessingStore(_ *context.T, _ rpc.ServerCall, handle principal.BlessingsHandle, pattern security.BlessingPattern) (*principal.JsBlessings, error) {
+// BlessingStoreSet puts the specified blessing in the blessing store under the
+// provided pattern.
+func (c *Controller) BlessingStoreSet(_ *context.T, _ rpc.ServerCall, handle principal.BlessingsHandle, pattern security.BlessingPattern) (*principal.JsBlessings, error) {
 	var inputBlessings security.Blessings
 	if inputBlessings = c.GetBlessings(handle); inputBlessings.IsZero() {
 		return nil, verror.New(invalidBlessingsHandle, nil, handle)
@@ -801,18 +801,33 @@
 	return jsBlessings, nil
 }
 
-// AddToRoots adds the provided blessing as a root.
-func (c *Controller) AddToRoots(_ *context.T, _ rpc.ServerCall, handle principal.BlessingsHandle) error {
+// BlessingStoreForPeer puts the specified blessing in the blessing store under the
+// provided pattern.
+func (c *Controller) BlessingStoreForPeer(_ *context.T, _ rpc.ServerCall, peerBlessings []string) (*principal.JsBlessings, error) {
+	p := v23.GetPrincipal(c.ctx)
+	outBlessings := p.BlessingStore().ForPeer(peerBlessings...)
+
+	if outBlessings.IsZero() {
+		return nil, nil
+	}
+
+	jsBlessings := principal.ConvertBlessingsToHandle(outBlessings, c.blessingsCache.GetOrAddHandle(outBlessings))
+	return jsBlessings, nil
+}
+
+// BlessingStoreSetDefault sets the default blessings in the blessing store.
+func (c *Controller) BlessingStoreSetDefault(_ *context.T, _ rpc.ServerCall, handle principal.BlessingsHandle) error {
 	var inputBlessings security.Blessings
 	if inputBlessings = c.GetBlessings(handle); inputBlessings.IsZero() {
 		return verror.New(invalidBlessingsHandle, nil, handle)
 	}
 
 	p := v23.GetPrincipal(c.ctx)
-	return p.AddToRoots(inputBlessings)
+	return p.BlessingStore().SetDefault(inputBlessings)
 }
 
-func (c *Controller) GetDefaultBlessings(*context.T, rpc.ServerCall) (*principal.JsBlessings, error) {
+// BlessingStoreDefault fetches the default blessings for the principal of the controller.
+func (c *Controller) BlessingStoreDefault(*context.T, rpc.ServerCall) (*principal.JsBlessings, error) {
 	p := v23.GetPrincipal(c.ctx)
 	outBlessings := p.BlessingStore().Default()
 
@@ -824,6 +839,41 @@
 	return jsBlessing, nil
 }
 
+// BlessingStorePublicKey fetches the public key used by the principal associated with the blessing store.
+func (c *Controller) BlessingStorePublicKey(*context.T, rpc.ServerCall) (string, error) {
+	p := v23.GetPrincipal(c.ctx)
+	pk := p.BlessingStore().PublicKey()
+	return principal.EncodePublicKey(pk)
+}
+
+// BlessingStorePeerBlessings returns all the blessings that the BlessingStore holds.
+func (c *Controller) BlessingStorePeerBlessings(*context.T, rpc.ServerCall) (map[security.BlessingPattern]*principal.JsBlessings, error) {
+	p := v23.GetPrincipal(c.ctx)
+	outBlessingsMap := map[security.BlessingPattern]*principal.JsBlessings{}
+	for pattern, blessings := range p.BlessingStore().PeerBlessings() {
+		outBlessingsMap[pattern] = principal.ConvertBlessingsToHandle(blessings, c.blessingsCache.GetOrAddHandle(blessings))
+	}
+	return outBlessingsMap, nil
+}
+
+// BlessingStoreDebugString retrieves a debug string describing the state of the blessing store
+func (c *Controller) BlessingStoreDebugString(*context.T, rpc.ServerCall) (string, error) {
+	p := v23.GetPrincipal(c.ctx)
+	ds := p.BlessingStore().DebugString()
+	return ds, nil
+}
+
+// AddToRoots adds the provided blessing as a root.
+func (c *Controller) AddToRoots(_ *context.T, _ rpc.ServerCall, handle principal.BlessingsHandle) error {
+	var inputBlessings security.Blessings
+	if inputBlessings = c.GetBlessings(handle); inputBlessings.IsZero() {
+		return verror.New(invalidBlessingsHandle, nil, handle)
+	}
+
+	p := v23.GetPrincipal(c.ctx)
+	return p.AddToRoots(inputBlessings)
+}
+
 // UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
 func (c *Controller) UnionOfBlessings(_ *context.T, _ rpc.ServerCall, handles []principal.BlessingsHandle) (*principal.JsBlessings, error) {
 	inputBlessings := make([]security.Blessings, len(handles))
diff --git a/services/wspr/internal/app/app.go.orig b/services/wspr/internal/app/app.go.orig
new file mode 100644
index 0000000..fcefaa8
--- /dev/null
+++ b/services/wspr/internal/app/app.go.orig
@@ -0,0 +1,947 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The app package contains the struct that keeps per javascript app state and handles translating
+// javascript requests to vanadium requests and vice versa.
+package app
+
+import (
+	"bytes"
+	"encoding/hex"
+	"fmt"
+	"io"
+	"reflect"
+	"sync"
+	"time"
+
+	"v.io/v23"
+	"v.io/v23/context"
+	"v.io/v23/i18n"
+	"v.io/v23/naming"
+	"v.io/v23/options"
+	"v.io/v23/rpc"
+	"v.io/v23/security"
+	"v.io/v23/vdl"
+	"v.io/v23/vdlroot/signature"
+	"v.io/v23/verror"
+	"v.io/v23/vom"
+	"v.io/v23/vtrace"
+	"v.io/x/lib/vlog"
+	"v.io/x/ref/services/wspr/internal/lib"
+	"v.io/x/ref/services/wspr/internal/namespace"
+	"v.io/x/ref/services/wspr/internal/principal"
+	"v.io/x/ref/services/wspr/internal/rpc/server"
+)
+
+const (
+	// pkgPath is the prefix os errors in this package.
+	pkgPath = "v.io/x/ref/services/wspr/internal/app"
+)
+
+// Errors
+var (
+	marshallingError       = verror.Register(pkgPath+".marshallingError", verror.NoRetry, "{1} {2} marshalling error {_}")
+	noResults              = verror.Register(pkgPath+".noResults", verror.NoRetry, "{1} {2} no results from call {_}")
+	badCaveatType          = verror.Register(pkgPath+".badCaveatType", verror.NoRetry, "{1} {2} bad caveat type {_}")
+	unknownBlessings       = verror.Register(pkgPath+".unknownBlessings", verror.NoRetry, "{1} {2} unknown public id {_}")
+	invalidBlessingsHandle = verror.Register(pkgPath+".invalidBlessingsHandle", verror.NoRetry, "{1} {2} invalid blessings handle {3} {_}")
+)
+
+type outstandingRequest struct {
+	stream *outstandingStream
+	cancel context.CancelFunc
+}
+
+// Controller represents all the state of a Vanadium Web App.  This is the struct
+// that is in charge performing all the vanadium options.
+type Controller struct {
+	// Protects everything.
+	// TODO(bjornick): We need to split this up.
+	sync.Mutex
+
+	// The context of this controller.
+	ctx *context.T
+
+	// The cleanup function for this controller.
+	cancel context.CancelFunc
+
+	// The rpc.ListenSpec to use with server.Listen
+	listenSpec *rpc.ListenSpec
+
+	// Used to generate unique ids for requests initiated by the proxy.
+	// These ids will be even so they don't collide with the ids generated
+	// by the client.
+	lastGeneratedId int32
+
+	// Used to keep track of data (streams and cancellation functions) for
+	// outstanding requests.
+	outstandingRequests map[int32]*outstandingRequest
+
+	// Maps flowids to the server that owns them.
+	flowMap map[int32]interface{}
+
+	// A manager that Handles fetching and caching signature of remote services
+	signatureManager lib.SignatureManager
+
+	// We maintain multiple Vanadium server per pipe for serving JavaScript
+	// services.
+	servers map[uint32]*server.Server
+
+	// Creates a client writer for a given flow.  This is a member so that tests can override
+	// the default implementation.
+	writerCreator func(id int32) lib.ClientWriter
+
+	// Cache for all the Blessings that javascript has a handle to.
+	blessingsCache *principal.JSBlessingsHandles
+
+	// reservedServices contains a map of reserved service names.  These
+	// are objects that serve requests in wspr without actually making
+	// an outgoing rpc call.
+	reservedServices map[string]rpc.Invoker
+}
+
+// NewController creates a new Controller.  writerCreator will be used to create a new flow for rpcs to
+// javascript server.
+func NewController(ctx *context.T, writerCreator func(id int32) lib.ClientWriter, listenSpec *rpc.ListenSpec, namespaceRoots []string, p security.Principal) (*Controller, error) {
+	ctx, cancel := context.WithCancel(ctx)
+
+	if namespaceRoots != nil {
+		var err error
+		ctx, _, err = v23.WithNewNamespace(ctx, namespaceRoots...)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	ctx, _ = vtrace.WithNewTrace(ctx)
+
+	ctx, err := v23.WithPrincipal(ctx, p)
+	if err != nil {
+		return nil, err
+	}
+
+	controller := &Controller{
+		ctx:            ctx,
+		cancel:         cancel,
+		writerCreator:  writerCreator,
+		listenSpec:     listenSpec,
+		blessingsCache: principal.NewJSBlessingsHandles(),
+	}
+
+	controllerInvoker, err := rpc.ReflectInvoker(ControllerServer(controller))
+	if err != nil {
+		return nil, err
+	}
+	namespaceInvoker, err := rpc.ReflectInvoker(namespace.New(ctx))
+	if err != nil {
+		return nil, err
+	}
+	controller.reservedServices = map[string]rpc.Invoker{
+		"__controller": controllerInvoker,
+		"__namespace":  namespaceInvoker,
+	}
+
+	controller.setup()
+	return controller, nil
+}
+
+// finishCall waits for the call to finish and write out the response to w.
+func (c *Controller) finishCall(ctx *context.T, w lib.ClientWriter, clientCall rpc.ClientCall, msg *RpcRequest, span vtrace.Span) {
+	if msg.IsStreaming {
+		for {
+			var item interface{}
+			if err := clientCall.Recv(&item); err != nil {
+				if err == io.EOF {
+					break
+				}
+				w.Error(err) // Send streaming error as is
+				return
+			}
+			if blessings, ok := item.(security.Blessings); ok {
+				item = principal.ConvertBlessingsToHandle(blessings, c.blessingsCache.GetOrAddHandle(blessings))
+			}
+			vomItem, err := lib.VomEncode(item)
+			if err != nil {
+				w.Error(verror.New(marshallingError, ctx, item, err))
+				continue
+			}
+			if err := w.Send(lib.ResponseStream, vomItem); err != nil {
+				w.Error(verror.New(marshallingError, ctx, item))
+			}
+		}
+		if err := w.Send(lib.ResponseStreamClose, nil); err != nil {
+			w.Error(verror.New(marshallingError, ctx, "ResponseStreamClose"))
+		}
+	}
+	results := make([]*vdl.Value, msg.NumOutArgs)
+	wireBlessingsType := vdl.TypeOf(security.WireBlessings{})
+	// This array will have pointers to the values in results.
+	resultptrs := make([]interface{}, msg.NumOutArgs)
+	for i := range results {
+		resultptrs[i] = &results[i]
+	}
+	if err := clientCall.Finish(resultptrs...); err != nil {
+		// return the call system error as is
+		w.Error(err)
+		return
+	}
+	for i, val := range results {
+		if val.Type() == wireBlessingsType {
+			var blessings security.Blessings
+			if err := vdl.Convert(&blessings, val); err != nil {
+				w.Error(err)
+				return
+			}
+			results[i] = vdl.ValueOf(principal.ConvertBlessingsToHandle(blessings, c.blessingsCache.GetOrAddHandle(blessings)))
+		}
+	}
+	c.sendRPCResponse(ctx, w, span, results)
+}
+
+func (c *Controller) sendRPCResponse(ctx *context.T, w lib.ClientWriter, span vtrace.Span, results []*vdl.Value) {
+	span.Finish()
+	response := RpcResponse{
+		OutArgs:       results,
+		TraceResponse: vtrace.GetResponse(ctx),
+	}
+	encoded, err := lib.VomEncode(response)
+	if err != nil {
+		w.Error(err)
+		return
+	}
+	if err := w.Send(lib.ResponseFinal, encoded); err != nil {
+		w.Error(verror.Convert(marshallingError, ctx, err))
+	}
+}
+
+// callOpts turns a slice of type []RpcCallOption object into an array of rpc.CallOpt.
+func (c *Controller) callOpts(opts []RpcCallOption) ([]rpc.CallOpt, error) {
+	var callOpts []rpc.CallOpt
+
+	for _, opt := range opts {
+		switch v := opt.(type) {
+		case RpcCallOptionAllowedServersPolicy:
+			callOpts = append(callOpts, options.AllowedServersPolicy(v.Value))
+		case RpcCallOptionRetryTimeout:
+			callOpts = append(callOpts, options.RetryTimeout(v.Value))
+		case RpcCallOptionGranter:
+			callOpts = append(callOpts, &jsGranter{c, v.Value})
+		default:
+			return nil, fmt.Errorf("Unknown RpcCallOption type %T", v)
+		}
+	}
+
+	return callOpts, nil
+}
+
+// serverOpts turns a slice of type []RpcServerOptions object into an array of rpc.ServerOpt.
+func (c *Controller) serverOpts(opts []RpcServerOption) ([]rpc.ServerOpt, error) {
+	var serverOpts []rpc.ServerOpt
+
+	for _, opt := range opts {
+		switch v := opt.(type) {
+		case RpcServerOptionIsLeaf:
+			serverOpts = append(serverOpts, options.IsLeaf(v.Value))
+		case RpcServerOptionServesMountTable:
+			serverOpts = append(serverOpts, options.ServesMountTable(v.Value))
+		default:
+			return nil, fmt.Errorf("Unknown RpcServerOption type %T", v)
+		}
+	}
+
+	return serverOpts, nil
+}
+
+func (c *Controller) startCall(ctx *context.T, w lib.ClientWriter, msg *RpcRequest, inArgs []interface{}) (rpc.ClientCall, error) {
+	methodName := lib.UppercaseFirstCharacter(msg.Method)
+	callOpts, err := c.callOpts(msg.CallOptions)
+	if err != nil {
+		return nil, err
+	}
+	clientCall, err := v23.GetClient(ctx).StartCall(ctx, msg.Name, methodName, inArgs, callOpts...)
+	if err != nil {
+		return nil, fmt.Errorf("error starting call (name: %v, method: %v, args: %v): %v", msg.Name, methodName, inArgs, err)
+	}
+
+	return clientCall, nil
+}
+
+// Implements the serverHelper interface
+
+// CreateNewFlow creats a new server flow that will be used to write out
+// streaming messages to Javascript.
+func (c *Controller) CreateNewFlow(s interface{}, stream rpc.Stream) *server.Flow {
+	c.Lock()
+	defer c.Unlock()
+	id := c.lastGeneratedId
+	c.lastGeneratedId += 2
+	c.flowMap[id] = s
+	os := newStream(c.blessingsCache)
+	os.init(stream)
+	c.outstandingRequests[id] = &outstandingRequest{
+		stream: os,
+	}
+	return &server.Flow{ID: id, Writer: c.writerCreator(id)}
+}
+
+// CleanupFlow removes the bookkeeping for a previously created flow.
+func (c *Controller) CleanupFlow(id int32) {
+	c.Lock()
+	request := c.outstandingRequests[id]
+	delete(c.outstandingRequests, id)
+	delete(c.flowMap, id)
+	c.Unlock()
+	if request != nil && request.stream != nil {
+		request.stream.end()
+		request.stream.waitUntilDone()
+	}
+}
+
+// RT returns the runtime of the app.
+func (c *Controller) Context() *context.T {
+	return c.ctx
+}
+
+// GetOrAddBlessingsHandle adds the Blessings to the local blessings store if they
+// don't already existand returns the handle to it.  This function exists
+// because JS only has a handle to the blessings to avoid shipping the
+// certificate forest to JS and back.
+func (c *Controller) GetOrAddBlessingsHandle(blessings security.Blessings) principal.BlessingsHandle {
+	return c.blessingsCache.GetOrAddHandle(blessings)
+}
+
+// GetBlessings gets blessings for a given blessings handle.
+func (c *Controller) GetBlessings(handle principal.BlessingsHandle) security.Blessings {
+	return c.blessingsCache.GetBlessings(handle)
+}
+
+// Cleanup cleans up any outstanding rpcs.
+func (c *Controller) Cleanup() {
+	vlog.VI(0).Info("Cleaning up controller")
+	c.Lock()
+
+	for _, request := range c.outstandingRequests {
+		if request.cancel != nil {
+			request.cancel()
+		}
+		if request.stream != nil {
+			request.stream.end()
+		}
+	}
+
+	servers := []*server.Server{}
+	for _, server := range c.servers {
+		servers = append(servers, server)
+	}
+
+	c.Unlock()
+
+	// We must unlock before calling server.Stop otherwise it can deadlock.
+	for _, server := range servers {
+		server.Stop()
+	}
+
+	c.cancel()
+}
+
+func (c *Controller) setup() {
+	c.signatureManager = lib.NewSignatureManager()
+	c.outstandingRequests = make(map[int32]*outstandingRequest)
+	c.flowMap = make(map[int32]interface{})
+	c.servers = make(map[uint32]*server.Server)
+}
+
+// SendOnStream writes data on id's stream.  The actual network write will be
+// done asynchronously.  If there is an error, it will be sent to w.
+func (c *Controller) SendOnStream(id int32, data string, w lib.ClientWriter) {
+	c.Lock()
+	request := c.outstandingRequests[id]
+	if request == nil || request.stream == nil {
+		vlog.Errorf("unknown stream: %d", id)
+		c.Unlock()
+		return
+	}
+	stream := request.stream
+	c.Unlock()
+	stream.send(data, w)
+}
+
+// SendVeyronRequest makes a vanadium request for the given flowId.  If signal is non-nil, it will receive
+// the call object after it has been constructed.
+func (c *Controller) sendVeyronRequest(ctx *context.T, id int32, msg *RpcRequest, inArgs []interface{}, w lib.ClientWriter, stream *outstandingStream, span vtrace.Span) {
+	sig, err := c.getSignature(ctx, msg.Name)
+	if err != nil {
+		w.Error(err)
+		return
+	}
+	methName := lib.UppercaseFirstCharacter(msg.Method)
+	methSig, ok := signature.FirstMethod(sig, methName)
+	if !ok {
+		w.Error(fmt.Errorf("method %q not found in signature: %#v", methName, sig))
+		return
+	}
+	if len(methSig.InArgs) != len(inArgs) {
+		w.Error(fmt.Errorf("invalid number of arguments, expected: %v, got:%v", methSig, *msg))
+		return
+	}
+
+	for i, arg := range inArgs {
+		if jsBlessings, ok := arg.(principal.JsBlessings); ok {
+			inArgs[i] = c.blessingsCache.GetBlessings(jsBlessings.Handle)
+		}
+	}
+	// We have to make the start call synchronous so we can make sure that we populate
+	// the call map before we can Handle a recieve call.
+	call, err := c.startCall(ctx, w, msg, inArgs)
+	if err != nil {
+		w.Error(verror.Convert(verror.ErrInternal, ctx, err))
+		return
+	}
+
+	if stream != nil {
+		stream.init(call)
+	}
+
+	c.finishCall(ctx, w, call, msg, span)
+	c.Lock()
+	if request, ok := c.outstandingRequests[id]; ok {
+		delete(c.outstandingRequests, id)
+		if request.cancel != nil {
+			request.cancel()
+		}
+	}
+	c.Unlock()
+}
+
+// TODO(mattr): This is a very limited implementation of ServerCall,
+// but currently none of the methods the controller exports require
+// any of this context information.
+type localCall struct {
+	ctx  *context.T
+	vrpc *RpcRequest
+	tags []*vdl.Value
+	w    lib.ClientWriter
+}
+
+var (
+	_ rpc.StreamServerCall = (*localCall)(nil)
+	_ security.Call        = (*localCall)(nil)
+)
+
+func (l *localCall) Send(item interface{}) error {
+	vomItem, err := lib.VomEncode(item)
+	if err != nil {
+		err = verror.New(marshallingError, l.ctx, item, err)
+		l.w.Error(err)
+		return err
+	}
+	if err := l.w.Send(lib.ResponseStream, vomItem); err != nil {
+		err = verror.New(marshallingError, l.ctx, item)
+		l.w.Error(err)
+		return err
+	}
+	return nil
+}
+func (l *localCall) Recv(interface{}) error                          { return nil }
+func (l *localCall) GrantedBlessings() security.Blessings            { return security.Blessings{} }
+func (l *localCall) Server() rpc.Server                              { return nil }
+func (l *localCall) Timestamp() (t time.Time)                        { return }
+func (l *localCall) Method() string                                  { return l.vrpc.Method }
+func (l *localCall) MethodTags() []*vdl.Value                        { return l.tags }
+func (l *localCall) Suffix() string                                  { return l.vrpc.Name }
+func (l *localCall) LocalDischarges() map[string]security.Discharge  { return nil }
+func (l *localCall) RemoteDischarges() map[string]security.Discharge { return nil }
+func (l *localCall) LocalPrincipal() security.Principal              { return nil }
+func (l *localCall) LocalBlessings() security.Blessings              { return security.Blessings{} }
+func (l *localCall) RemoteBlessings() security.Blessings             { return security.Blessings{} }
+func (l *localCall) LocalEndpoint() naming.Endpoint                  { return nil }
+func (l *localCall) RemoteEndpoint() naming.Endpoint                 { return nil }
+func (l *localCall) Security() security.Call                         { return l }
+
+func (c *Controller) handleInternalCall(ctx *context.T, invoker rpc.Invoker, msg *RpcRequest, decoder *vom.Decoder, w lib.ClientWriter, span vtrace.Span) {
+	argptrs, tags, err := invoker.Prepare(msg.Method, int(msg.NumInArgs))
+	if err != nil {
+		w.Error(verror.Convert(verror.ErrInternal, ctx, err))
+		return
+	}
+	for _, argptr := range argptrs {
+		if err := decoder.Decode(argptr); err != nil {
+			w.Error(verror.Convert(verror.ErrInternal, ctx, err))
+			return
+		}
+	}
+	results, err := invoker.Invoke(ctx, &localCall{ctx, msg, tags, w}, msg.Method, argptrs)
+	if err != nil {
+		w.Error(verror.Convert(verror.ErrInternal, ctx, err))
+		return
+	}
+	if msg.IsStreaming {
+		if err := w.Send(lib.ResponseStreamClose, nil); err != nil {
+			w.Error(verror.New(marshallingError, ctx, "ResponseStreamClose"))
+		}
+	}
+
+	// Convert results from []interface{} to []*vdl.Value.
+	vresults := make([]*vdl.Value, len(results))
+	for i, res := range results {
+		vv, err := vdl.ValueFromReflect(reflect.ValueOf(res))
+		if err != nil {
+			w.Error(verror.Convert(verror.ErrInternal, ctx, err))
+			return
+		}
+		vresults[i] = vv
+	}
+	c.sendRPCResponse(ctx, w, span, vresults)
+}
+
+// HandleCaveatValidationResponse handles the response to caveat validation
+// requests.
+func (c *Controller) HandleCaveatValidationResponse(id int32, data string) {
+	c.Lock()
+	server, ok := c.flowMap[id].(*server.Server)
+	c.Unlock()
+	if !ok {
+		vlog.Errorf("unexpected result from JavaScript. No server found matching id %d.", id)
+		return // ignore unknown server
+	}
+	server.HandleCaveatValidationResponse(id, data)
+}
+
+// HandleVeyronRequest starts a vanadium rpc and returns before the rpc has been completed.
+func (c *Controller) HandleVeyronRequest(ctx *context.T, id int32, data string, w lib.ClientWriter) {
+	binbytes, err := hex.DecodeString(data)
+	if err != nil {
+		w.Error(verror.Convert(verror.ErrInternal, ctx, fmt.Errorf("Error decoding hex string %q: %v", data, err)))
+		return
+	}
+	decoder := vom.NewDecoder(bytes.NewReader(binbytes))
+	var msg RpcRequest
+	if err := decoder.Decode(&msg); err != nil {
+		w.Error(verror.Convert(verror.ErrInternal, ctx, err))
+		return
+	}
+	vlog.VI(2).Infof("Rpc: %s.%s(..., streaming=%v)", msg.Name, msg.Method, msg.IsStreaming)
+	spanName := fmt.Sprintf("<wspr>%q.%s", msg.Name, msg.Method)
+	ctx, span := vtrace.WithContinuedTrace(ctx, spanName, msg.TraceRequest)
+	ctx = i18n.WithLangID(ctx, i18n.LangID(msg.Context.Language))
+
+	var cctx *context.T
+	var cancel context.CancelFunc
+
+	// TODO(mattr): To be consistent with go, we should not ignore 0 timeouts.
+	// However as a rollout strategy we must, otherwise there is a circular
+	// dependency between the WSPR change and the JS change that will follow.
+	if msg.Deadline.IsZero() {
+		cctx, cancel = context.WithCancel(ctx)
+	} else {
+		cctx, cancel = context.WithDeadline(ctx, msg.Deadline.Time)
+	}
+
+	// If this message is for an internal service, do a short-circuit dispatch here.
+	if invoker, ok := c.reservedServices[msg.Name]; ok {
+		go c.handleInternalCall(ctx, invoker, &msg, decoder, w, span)
+		return
+	}
+
+	inArgs := make([]interface{}, msg.NumInArgs)
+	for i := range inArgs {
+		var v *vdl.Value
+		if err := decoder.Decode(&v); err != nil {
+			w.Error(err)
+			return
+		}
+		inArgs[i] = v
+	}
+
+	request := &outstandingRequest{
+		cancel: cancel,
+	}
+	if msg.IsStreaming {
+		// If this rpc is streaming, we would expect that the client would try to send
+		// on this stream.  Since the initial handshake is done asynchronously, we have
+		// to put the outstanding stream in the map before we make the async call so that
+		// the future send know which queue to write to, even if the client call isn't
+		// actually ready yet.
+		request.stream = newStream(c.blessingsCache)
+	}
+	c.Lock()
+	c.outstandingRequests[id] = request
+	go c.sendVeyronRequest(cctx, id, &msg, inArgs, w, request.stream, span)
+	c.Unlock()
+}
+
+// HandleVeyronCancellation cancels the request corresponding to the
+// given id if it is still outstanding.
+func (c *Controller) HandleVeyronCancellation(id int32) {
+	c.Lock()
+	defer c.Unlock()
+	if request, ok := c.outstandingRequests[id]; ok && request.cancel != nil {
+		request.cancel()
+	}
+}
+
+// CloseStream closes the stream for a given id.
+func (c *Controller) CloseStream(id int32) {
+	c.Lock()
+	defer c.Unlock()
+	if request, ok := c.outstandingRequests[id]; ok && request.stream != nil {
+		request.stream.end()
+		return
+	}
+	vlog.Errorf("close called on non-existent call: %v", id)
+}
+
+func (c *Controller) maybeCreateServer(serverId uint32, opts ...rpc.ServerOpt) (*server.Server, error) {
+	c.Lock()
+	defer c.Unlock()
+	if server, ok := c.servers[serverId]; ok {
+		return server, nil
+	}
+	server, err := server.NewServer(serverId, c.listenSpec, c, opts...)
+	if err != nil {
+		return nil, err
+	}
+	c.servers[serverId] = server
+	return server, nil
+}
+
+// HandleLookupResponse handles the result of a Dispatcher.Lookup call that was
+// run by the Javascript server.
+func (c *Controller) HandleLookupResponse(id int32, data string) {
+	c.Lock()
+	server, ok := c.flowMap[id].(*server.Server)
+	c.Unlock()
+	if !ok {
+		vlog.Errorf("unexpected result from JavaScript. No channel "+
+			"for MessageId: %d exists. Ignoring the results.", id)
+		//Ignore unknown responses that don't belong to any channel
+		return
+	}
+	server.HandleLookupResponse(id, data)
+}
+
+// HandleAuthResponse handles the result of a Authorizer.Authorize call that was
+// run by the Javascript server.
+func (c *Controller) HandleAuthResponse(id int32, data string) {
+	c.Lock()
+	server, ok := c.flowMap[id].(*server.Server)
+	c.Unlock()
+	if !ok {
+		vlog.Errorf("unexpected result from JavaScript. No channel "+
+			"for MessageId: %d exists. Ignoring the results.", id)
+		//Ignore unknown responses that don't belong to any channel
+		return
+	}
+	server.HandleAuthResponse(id, data)
+}
+
+// Serve instructs WSPR to start listening for calls on behalf
+// of a javascript server.
+func (c *Controller) Serve(_ *context.T, _ rpc.ServerCall, name string, serverId uint32, rpcServerOpts []RpcServerOption) error {
+
+	opts, err := c.serverOpts(rpcServerOpts)
+	if err != nil {
+		return verror.Convert(verror.ErrInternal, nil, err)
+	}
+	server, err := c.maybeCreateServer(serverId, opts...)
+	if err != nil {
+		return verror.Convert(verror.ErrInternal, nil, err)
+	}
+	vlog.VI(2).Infof("serving under name: %q", name)
+	if err := server.Serve(name); err != nil {
+		return verror.Convert(verror.ErrInternal, nil, err)
+	}
+	return nil
+}
+
+// Stop instructs WSPR to stop listening for calls for the
+// given javascript server.
+func (c *Controller) Stop(_ *context.T, _ rpc.ServerCall, serverId uint32) error {
+	c.Lock()
+	server, ok := c.servers[serverId]
+	if !ok {
+		c.Unlock()
+		return nil
+	}
+	delete(c.servers, serverId)
+	c.Unlock()
+
+	server.Stop()
+	return nil
+}
+
+// AddName adds a published name to an existing server.
+func (c *Controller) AddName(_ *context.T, _ rpc.ServerCall, serverId uint32, name string) error {
+	// Create a server for the pipe, if it does not exist already
+	server, err := c.maybeCreateServer(serverId)
+	if err != nil {
+		return verror.Convert(verror.ErrInternal, nil, err)
+	}
+	// Add name
+	if err := server.AddName(name); err != nil {
+		return verror.Convert(verror.ErrInternal, nil, err)
+	}
+	return nil
+}
+
+// RemoveName removes a published name from an existing server.
+func (c *Controller) RemoveName(_ *context.T, _ rpc.ServerCall, serverId uint32, name string) error {
+	// Create a server for the pipe, if it does not exist already
+	server, err := c.maybeCreateServer(serverId)
+	if err != nil {
+		return verror.Convert(verror.ErrInternal, nil, err)
+	}
+	// Remove name
+	server.RemoveName(name)
+	// Remove name from signature cache as well
+	c.signatureManager.FlushCacheEntry(name)
+	return nil
+}
+
+// HandleServerResponse handles the completion of outstanding calls to JavaScript services
+// by filling the corresponding channel with the result from JavaScript.
+func (c *Controller) HandleServerResponse(id int32, data string) {
+	c.Lock()
+	server, ok := c.flowMap[id].(*server.Server)
+	c.Unlock()
+	if !ok {
+		vlog.Errorf("unexpected result from JavaScript. No channel "+
+			"for MessageId: %d exists. Ignoring the results.", id)
+		//Ignore unknown responses that don't belong to any channel
+		return
+	}
+	server.HandleServerResponse(id, data)
+}
+
+// parseVeyronRequest parses a json rpc request into a RpcRequest object.
+func (c *Controller) parseVeyronRequest(data string) (*RpcRequest, error) {
+	var msg RpcRequest
+	if err := lib.VomDecode(data, &msg); err != nil {
+		return nil, err
+	}
+	vlog.VI(2).Infof("RpcRequest: %s.%s(..., streaming=%v)", msg.Name, msg.Method, msg.IsStreaming)
+	return &msg, nil
+}
+
+// getSignature uses the signature manager to get and cache the signature of a remote server.
+func (c *Controller) getSignature(ctx *context.T, name string) ([]signature.Interface, error) {
+	return c.signatureManager.Signature(ctx, name)
+}
+
+// Signature uses the signature manager to get and cache the signature of a remote server.
+func (c *Controller) Signature(ctx *context.T, _ rpc.ServerCall, name string) ([]signature.Interface, error) {
+	return c.getSignature(ctx, name)
+}
+
+// UnlinkBlessings removes the given blessings from the blessings store.
+func (c *Controller) UnlinkBlessings(_ *context.T, _ rpc.ServerCall, handle principal.BlessingsHandle) error {
+	return c.blessingsCache.RemoveReference(handle)
+}
+
+// Bless binds extensions of blessings held by this principal to
+// another principal (represented by its public key).
+func (c *Controller) Bless(_ *context.T, _ rpc.ServerCall, publicKey string, blessingHandle principal.BlessingsHandle, extension string, caveats []security.Caveat) (string, principal.BlessingsHandle, error) {
+	var inputBlessing security.Blessings
+	if inputBlessing = c.GetBlessings(blessingHandle); inputBlessing.IsZero() {
+		return "", principal.ZeroHandle, verror.New(invalidBlessingsHandle, nil, blessingHandle)
+	}
+
+	key, err := principal.DecodePublicKey(publicKey)
+	if err != nil {
+		return "", principal.ZeroHandle, err
+	}
+
+	if len(caveats) == 0 {
+		caveats = append(caveats, security.UnconstrainedUse())
+	}
+
+	p := v23.GetPrincipal(c.ctx)
+	blessings, err := p.Bless(key, inputBlessing, extension, caveats[0], caveats[1:]...)
+	if err != nil {
+		return "", principal.ZeroHandle, err
+	}
+	handle := c.blessingsCache.GetOrAddHandle(blessings)
+	return publicKey, handle, nil
+}
+
+// BlessSelf creates a blessing with the provided name for this principal.
+func (c *Controller) BlessSelf(_ *context.T, _ rpc.ServerCall, extension string, caveats []security.Caveat) (string, principal.BlessingsHandle, error) {
+	p := v23.GetPrincipal(c.ctx)
+	blessings, err := p.BlessSelf(extension)
+	if err != nil {
+		return "", principal.ZeroHandle, verror.Convert(verror.ErrInternal, nil, err)
+	}
+
+	handle := c.blessingsCache.GetOrAddHandle(blessings)
+
+	encKey, err := principal.EncodePublicKey(p.PublicKey())
+	return encKey, handle, err
+}
+
+// BlessingStoreSet puts the specified blessing in the blessing store under the
+// provided pattern.
+func (c *Controller) BlessingStoreSet(_ *context.T, _ rpc.ServerCall, handle principal.BlessingsHandle, pattern security.BlessingPattern) (*principal.JsBlessings, error) {
+	var inputBlessings security.Blessings
+	if inputBlessings = c.GetBlessings(handle); inputBlessings.IsZero() {
+		return nil, verror.New(invalidBlessingsHandle, nil, handle)
+	}
+
+	p := v23.GetPrincipal(c.ctx)
+	outBlessings, err := p.BlessingStore().Set(inputBlessings, security.BlessingPattern(pattern))
+	if err != nil {
+		return nil, err
+	}
+
+	if outBlessings.IsZero() {
+		return nil, nil
+	}
+
+	jsBlessings := principal.ConvertBlessingsToHandle(outBlessings, c.blessingsCache.GetOrAddHandle(outBlessings))
+	return jsBlessings, nil
+}
+
+// BlessingStoreForPeer puts the specified blessing in the blessing store under the
+// provided pattern.
+func (c *Controller) BlessingStoreForPeer(_ *context.T, _ rpc.ServerCall, peerBlessings []string) (*principal.JsBlessings, error) {
+	p := v23.GetPrincipal(c.ctx)
+	outBlessings := p.BlessingStore().ForPeer(peerBlessings...)
+
+	if outBlessings.IsZero() {
+		return nil, nil
+	}
+
+	jsBlessings := principal.ConvertBlessingsToHandle(outBlessings, c.blessingsCache.GetOrAddHandle(outBlessings))
+	return jsBlessings, nil
+}
+
+// BlessingStoreSetDefault sets the default blessings in the blessing store.
+func (c *Controller) BlessingStoreSetDefault(_ *context.T, _ rpc.ServerCall, handle principal.BlessingsHandle) error {
+	var inputBlessings security.Blessings
+	if inputBlessings = c.GetBlessings(handle); inputBlessings.IsZero() {
+		return verror.New(invalidBlessingsHandle, nil, handle)
+	}
+
+	p := v23.GetPrincipal(c.ctx)
+	return p.BlessingStore().SetDefault(inputBlessings)
+}
+
+// BlessingStoreDefault fetches the default blessings for the principal of the controller.
+func (c *Controller) BlessingStoreDefault(*context.T, rpc.ServerCall) (*principal.JsBlessings, error) {
+	p := v23.GetPrincipal(c.ctx)
+	outBlessings := p.BlessingStore().Default()
+
+	if outBlessings.IsZero() {
+		return nil, nil
+	}
+
+	jsBlessing := principal.ConvertBlessingsToHandle(outBlessings, c.blessingsCache.GetOrAddHandle(outBlessings))
+	return jsBlessing, nil
+}
+
+<<<<<<< HEAD
+// BlessingStorePublicKey fetches the public key used by the principal associated with the blessing store.
+func (c *Controller) BlessingStorePublicKey(*context.T, rpc.ServerCall) (string, error) {
+	p := v23.GetPrincipal(c.ctx)
+	pk := p.BlessingStore().PublicKey()
+	return principal.EncodePublicKey(pk)
+}
+
+// BlessingStorePeerBlessings returns all the blessings that the BlessingStore holds.
+func (c *Controller) BlessingStorePeerBlessings(*context.T, rpc.ServerCall) (map[security.BlessingPattern]*principal.JsBlessings, error) {
+	p := v23.GetPrincipal(c.ctx)
+	outBlessingsMap := map[security.BlessingPattern]*principal.JsBlessings{}
+	for pattern, blessings := range p.BlessingStore().PeerBlessings() {
+		outBlessingsMap[pattern] = principal.ConvertBlessingsToHandle(blessings, c.blessingsCache.GetOrAddHandle(blessings))
+	}
+	return outBlessingsMap, nil
+}
+
+// BlessingStoreDebugString retrieves a debug string describing the state of the blessing store
+func (c *Controller) BlessingStoreDebugString(*context.T, rpc.ServerCall) (string, error) {
+	p := v23.GetPrincipal(c.ctx)
+	ds := p.BlessingStore().DebugString()
+	return ds, nil
+}
+
+// AddToRoots adds the provided blessing as a root.
+func (c *Controller) AddToRoots(_ *context.T, _ rpc.ServerCall, handle principal.BlessingsHandle) error {
+	var inputBlessings security.Blessings
+	if inputBlessings = c.GetBlessings(handle); inputBlessings.IsZero() {
+		return verror.New(invalidBlessingsHandle, nil, handle)
+	}
+
+	p := v23.GetPrincipal(c.ctx)
+	return p.AddToRoots(inputBlessings)
+}
+
+=======
+>>>>>>> master
+// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
+func (c *Controller) UnionOfBlessings(_ *context.T, _ rpc.ServerCall, handles []principal.BlessingsHandle) (*principal.JsBlessings, error) {
+	inputBlessings := make([]security.Blessings, len(handles))
+	for i, handle := range handles {
+		bless := c.GetBlessings(handle)
+		if bless.IsZero() {
+			return nil, verror.New(invalidBlessingsHandle, nil, handle)
+		}
+		inputBlessings[i] = bless
+	}
+
+	outBlessings, err := security.UnionOfBlessings(inputBlessings...)
+	if err != nil {
+		return nil, err
+	}
+
+	jsBlessings := principal.ConvertBlessingsToHandle(outBlessings, c.blessingsCache.GetOrAddHandle(outBlessings))
+	return jsBlessings, nil
+}
+
+// HandleGranterResponse handles the result of a Granter request.
+func (c *Controller) HandleGranterResponse(id int32, data string) {
+	c.Lock()
+	granterStr, ok := c.flowMap[id].(*granterStream)
+	c.Unlock()
+	if !ok {
+		vlog.Errorf("unexpected result from JavaScript. Flow was not a granter "+
+			"stream for MessageId: %d exists. Ignoring the results.", id)
+		//Ignore unknown responses that don't belong to any channel
+		return
+	}
+	granterStr.Send(data)
+}
+
+func (c *Controller) BlessingsDebugString(_ *context.T, _ rpc.ServerCall, handle principal.BlessingsHandle) (string, error) {
+	var inputBlessings security.Blessings
+	if inputBlessings = c.GetBlessings(handle); inputBlessings.IsZero() {
+		return "", verror.New(invalidBlessingsHandle, nil, handle)
+	}
+
+	return inputBlessings.String(), nil
+}
+
+func (c *Controller) RemoteBlessings(ctx *context.T, _ rpc.ServerCall, name, method string) ([]string, error) {
+	vlog.VI(2).Infof("requesting remote blessings for %q", name)
+
+	cctx, cancel := context.WithTimeout(ctx, 5*time.Second)
+	defer cancel()
+
+	clientCall, err := v23.GetClient(cctx).StartCall(cctx, name, method, nil)
+	if err != nil {
+		return nil, verror.Convert(verror.ErrInternal, cctx, err)
+	}
+
+	blessings, _ := clientCall.RemoteBlessings()
+	return blessings, nil
+}
+
+func (c *Controller) SendLogMessage(level lib.LogLevel, msg string) error {
+	c.Lock()
+	defer c.Unlock()
+	id := c.lastGeneratedId
+	c.lastGeneratedId += 2
+	return c.writerCreator(id).Send(lib.ResponseLog, lib.LogMessage{
+		Level:   level,
+		Message: msg,
+	})
+}
diff --git a/services/wspr/internal/app/controller.vdl b/services/wspr/internal/app/controller.vdl
index 3f77742..8983e4e 100644
--- a/services/wspr/internal/app/controller.vdl
+++ b/services/wspr/internal/app/controller.vdl
@@ -32,18 +32,30 @@
 	Bless(publicKey string, handle principal.BlessingsHandle, extension string, caveat []security.Caveat) (publicKeyOut string, handleOut principal.BlessingsHandle | error)
 	// BlessSelf creates a blessing with the provided name for this principal.
 	BlessSelf(name string, caveats []security.Caveat) (publicKeyOut string, handleOut principal.BlessingsHandle | error)
-	// PutToBlessingStore puts the specified blessing to the blessing store under the provided pattern.
-	PutToBlessingStore(handle principal.BlessingsHandle, pattern security.BlessingPattern) (?principal.JsBlessings | error)
 	// AddToRoots adds the provided blessing as a root.
 	AddToRoots(handle principal.BlessingsHandle) error
 
+	// BlessingStoreSet puts the specified blessing in the blessing store under the provided pattern.
+	BlessingStoreSet(blessingsHandle principal.BlessingsHandle, pattern security.BlessingPattern) (?principal.JsBlessings | error)
+	// BlessingStoreForPeer retrieves the blessings marked for the given peers.
+	BlessingStoreForPeer(peerBlessings []string) (?principal.JsBlessings | error)
+	// BlessingStoreSetDefault sets the default blessings.
+	BlessingStoreSetDefault(blessingsHandle principal.BlessingsHandle) error
+	// BlessingStoreDefault fetches the default blessings for the principal of the controller.
+	BlessingStoreDefault() (?principal.JsBlessings | error)
+	// BlessingStorePublicKey fetches the public key of the principal for which this store hosts blessings.
+	BlessingStorePublicKey() (string | error)
+	// BlessingStorePeerBlessings returns all the blessings that the BlessingStore holds.
+	BlessingStorePeerBlessings() (map[security.BlessingPattern]?principal.JsBlessings | error)
+	// BlessingStoreDebugString retrieves a debug string describing the state of the blessing store
+	BlessingStoreDebugString() (string | error)
+
+
 	// RemoteBlessings fetches the remote blessings for a given name and method.
 	RemoteBlessings(name, method string) ([]string | error)
 	// Signature fetches the signature for a given name.
 	Signature(name string) ([]signature.Interface | error)
 
-	// GetDefaultBlessings fetches the default blessings for the principal of the controller.
-	GetDefaultBlessings() (?principal.JsBlessings | error)
-	// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
+  // UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
 	UnionOfBlessings(toJoin []principal.BlessingsHandle) (?principal.JsBlessings | error)
 }
diff --git a/services/wspr/internal/app/controller.vdl.go b/services/wspr/internal/app/controller.vdl.go
index 115596f..2731e36 100644
--- a/services/wspr/internal/app/controller.vdl.go
+++ b/services/wspr/internal/app/controller.vdl.go
@@ -41,16 +41,26 @@
 	Bless(ctx *context.T, publicKey string, handle principal.BlessingsHandle, extension string, caveat []security.Caveat, opts ...rpc.CallOpt) (publicKeyOut string, handleOut principal.BlessingsHandle, err error)
 	// BlessSelf creates a blessing with the provided name for this principal.
 	BlessSelf(ctx *context.T, name string, caveats []security.Caveat, opts ...rpc.CallOpt) (publicKeyOut string, handleOut principal.BlessingsHandle, err error)
-	// PutToBlessingStore puts the specified blessing to the blessing store under the provided pattern.
-	PutToBlessingStore(ctx *context.T, handle principal.BlessingsHandle, pattern security.BlessingPattern, opts ...rpc.CallOpt) (*principal.JsBlessings, error)
 	// AddToRoots adds the provided blessing as a root.
 	AddToRoots(ctx *context.T, handle principal.BlessingsHandle, opts ...rpc.CallOpt) error
+	// BlessingStoreSet puts the specified blessing in the blessing store under the provided pattern.
+	BlessingStoreSet(ctx *context.T, blessingsHandle principal.BlessingsHandle, pattern security.BlessingPattern, opts ...rpc.CallOpt) (*principal.JsBlessings, error)
+	// BlessingStoreForPeer retrieves the blessings marked for the given peers.
+	BlessingStoreForPeer(ctx *context.T, peerBlessings []string, opts ...rpc.CallOpt) (*principal.JsBlessings, error)
+	// BlessingStoreSetDefault sets the default blessings.
+	BlessingStoreSetDefault(ctx *context.T, blessingsHandle principal.BlessingsHandle, opts ...rpc.CallOpt) error
+	// BlessingStoreDefault fetches the default blessings for the principal of the controller.
+	BlessingStoreDefault(*context.T, ...rpc.CallOpt) (*principal.JsBlessings, error)
+	// BlessingStorePublicKey fetches the public key of the principal for which this store hosts blessings.
+	BlessingStorePublicKey(*context.T, ...rpc.CallOpt) (string, error)
+	// BlessingStorePeerBlessings returns all the blessings that the BlessingStore holds.
+	BlessingStorePeerBlessings(*context.T, ...rpc.CallOpt) (map[security.BlessingPattern]*principal.JsBlessings, error)
+	// BlessingStoreDebugString retrieves a debug string describing the state of the blessing store
+	BlessingStoreDebugString(*context.T, ...rpc.CallOpt) (string, error)
 	// RemoteBlessings fetches the remote blessings for a given name and method.
 	RemoteBlessings(ctx *context.T, name string, method string, opts ...rpc.CallOpt) ([]string, error)
 	// Signature fetches the signature for a given name.
 	Signature(ctx *context.T, name string, opts ...rpc.CallOpt) ([]signature.Interface, error)
-	// GetDefaultBlessings fetches the default blessings for the principal of the controller.
-	GetDefaultBlessings(*context.T, ...rpc.CallOpt) (*principal.JsBlessings, error)
 	// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
 	UnionOfBlessings(ctx *context.T, toJoin []principal.BlessingsHandle, opts ...rpc.CallOpt) (*principal.JsBlessings, error)
 }
@@ -110,13 +120,43 @@
 	return
 }
 
-func (c implControllerClientStub) PutToBlessingStore(ctx *context.T, i0 principal.BlessingsHandle, i1 security.BlessingPattern, opts ...rpc.CallOpt) (o0 *principal.JsBlessings, err error) {
-	err = v23.GetClient(ctx).Call(ctx, c.name, "PutToBlessingStore", []interface{}{i0, i1}, []interface{}{&o0}, opts...)
+func (c implControllerClientStub) AddToRoots(ctx *context.T, i0 principal.BlessingsHandle, opts ...rpc.CallOpt) (err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "AddToRoots", []interface{}{i0}, nil, opts...)
 	return
 }
 
-func (c implControllerClientStub) AddToRoots(ctx *context.T, i0 principal.BlessingsHandle, opts ...rpc.CallOpt) (err error) {
-	err = v23.GetClient(ctx).Call(ctx, c.name, "AddToRoots", []interface{}{i0}, nil, opts...)
+func (c implControllerClientStub) BlessingStoreSet(ctx *context.T, i0 principal.BlessingsHandle, i1 security.BlessingPattern, opts ...rpc.CallOpt) (o0 *principal.JsBlessings, err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStoreSet", []interface{}{i0, i1}, []interface{}{&o0}, opts...)
+	return
+}
+
+func (c implControllerClientStub) BlessingStoreForPeer(ctx *context.T, i0 []string, opts ...rpc.CallOpt) (o0 *principal.JsBlessings, err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStoreForPeer", []interface{}{i0}, []interface{}{&o0}, opts...)
+	return
+}
+
+func (c implControllerClientStub) BlessingStoreSetDefault(ctx *context.T, i0 principal.BlessingsHandle, opts ...rpc.CallOpt) (err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStoreSetDefault", []interface{}{i0}, nil, opts...)
+	return
+}
+
+func (c implControllerClientStub) BlessingStoreDefault(ctx *context.T, opts ...rpc.CallOpt) (o0 *principal.JsBlessings, err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStoreDefault", nil, []interface{}{&o0}, opts...)
+	return
+}
+
+func (c implControllerClientStub) BlessingStorePublicKey(ctx *context.T, opts ...rpc.CallOpt) (o0 string, err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStorePublicKey", nil, []interface{}{&o0}, opts...)
+	return
+}
+
+func (c implControllerClientStub) BlessingStorePeerBlessings(ctx *context.T, opts ...rpc.CallOpt) (o0 map[security.BlessingPattern]*principal.JsBlessings, err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStorePeerBlessings", nil, []interface{}{&o0}, opts...)
+	return
+}
+
+func (c implControllerClientStub) BlessingStoreDebugString(ctx *context.T, opts ...rpc.CallOpt) (o0 string, err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStoreDebugString", nil, []interface{}{&o0}, opts...)
 	return
 }
 
@@ -130,11 +170,6 @@
 	return
 }
 
-func (c implControllerClientStub) GetDefaultBlessings(ctx *context.T, opts ...rpc.CallOpt) (o0 *principal.JsBlessings, err error) {
-	err = v23.GetClient(ctx).Call(ctx, c.name, "GetDefaultBlessings", nil, []interface{}{&o0}, opts...)
-	return
-}
-
 func (c implControllerClientStub) UnionOfBlessings(ctx *context.T, i0 []principal.BlessingsHandle, opts ...rpc.CallOpt) (o0 *principal.JsBlessings, err error) {
 	err = v23.GetClient(ctx).Call(ctx, c.name, "UnionOfBlessings", []interface{}{i0}, []interface{}{&o0}, opts...)
 	return
@@ -162,16 +197,26 @@
 	Bless(ctx *context.T, call rpc.ServerCall, publicKey string, handle principal.BlessingsHandle, extension string, caveat []security.Caveat) (publicKeyOut string, handleOut principal.BlessingsHandle, err error)
 	// BlessSelf creates a blessing with the provided name for this principal.
 	BlessSelf(ctx *context.T, call rpc.ServerCall, name string, caveats []security.Caveat) (publicKeyOut string, handleOut principal.BlessingsHandle, err error)
-	// PutToBlessingStore puts the specified blessing to the blessing store under the provided pattern.
-	PutToBlessingStore(ctx *context.T, call rpc.ServerCall, handle principal.BlessingsHandle, pattern security.BlessingPattern) (*principal.JsBlessings, error)
 	// AddToRoots adds the provided blessing as a root.
 	AddToRoots(ctx *context.T, call rpc.ServerCall, handle principal.BlessingsHandle) error
+	// BlessingStoreSet puts the specified blessing in the blessing store under the provided pattern.
+	BlessingStoreSet(ctx *context.T, call rpc.ServerCall, blessingsHandle principal.BlessingsHandle, pattern security.BlessingPattern) (*principal.JsBlessings, error)
+	// BlessingStoreForPeer retrieves the blessings marked for the given peers.
+	BlessingStoreForPeer(ctx *context.T, call rpc.ServerCall, peerBlessings []string) (*principal.JsBlessings, error)
+	// BlessingStoreSetDefault sets the default blessings.
+	BlessingStoreSetDefault(ctx *context.T, call rpc.ServerCall, blessingsHandle principal.BlessingsHandle) error
+	// BlessingStoreDefault fetches the default blessings for the principal of the controller.
+	BlessingStoreDefault(*context.T, rpc.ServerCall) (*principal.JsBlessings, error)
+	// BlessingStorePublicKey fetches the public key of the principal for which this store hosts blessings.
+	BlessingStorePublicKey(*context.T, rpc.ServerCall) (string, error)
+	// BlessingStorePeerBlessings returns all the blessings that the BlessingStore holds.
+	BlessingStorePeerBlessings(*context.T, rpc.ServerCall) (map[security.BlessingPattern]*principal.JsBlessings, error)
+	// BlessingStoreDebugString retrieves a debug string describing the state of the blessing store
+	BlessingStoreDebugString(*context.T, rpc.ServerCall) (string, error)
 	// RemoteBlessings fetches the remote blessings for a given name and method.
 	RemoteBlessings(ctx *context.T, call rpc.ServerCall, name string, method string) ([]string, error)
 	// Signature fetches the signature for a given name.
 	Signature(ctx *context.T, call rpc.ServerCall, name string) ([]signature.Interface, error)
-	// GetDefaultBlessings fetches the default blessings for the principal of the controller.
-	GetDefaultBlessings(*context.T, rpc.ServerCall) (*principal.JsBlessings, error)
 	// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
 	UnionOfBlessings(ctx *context.T, call rpc.ServerCall, toJoin []principal.BlessingsHandle) (*principal.JsBlessings, error)
 }
@@ -243,14 +288,38 @@
 	return s.impl.BlessSelf(ctx, call, i0, i1)
 }
 
-func (s implControllerServerStub) PutToBlessingStore(ctx *context.T, call rpc.ServerCall, i0 principal.BlessingsHandle, i1 security.BlessingPattern) (*principal.JsBlessings, error) {
-	return s.impl.PutToBlessingStore(ctx, call, i0, i1)
-}
-
 func (s implControllerServerStub) AddToRoots(ctx *context.T, call rpc.ServerCall, i0 principal.BlessingsHandle) error {
 	return s.impl.AddToRoots(ctx, call, i0)
 }
 
+func (s implControllerServerStub) BlessingStoreSet(ctx *context.T, call rpc.ServerCall, i0 principal.BlessingsHandle, i1 security.BlessingPattern) (*principal.JsBlessings, error) {
+	return s.impl.BlessingStoreSet(ctx, call, i0, i1)
+}
+
+func (s implControllerServerStub) BlessingStoreForPeer(ctx *context.T, call rpc.ServerCall, i0 []string) (*principal.JsBlessings, error) {
+	return s.impl.BlessingStoreForPeer(ctx, call, i0)
+}
+
+func (s implControllerServerStub) BlessingStoreSetDefault(ctx *context.T, call rpc.ServerCall, i0 principal.BlessingsHandle) error {
+	return s.impl.BlessingStoreSetDefault(ctx, call, i0)
+}
+
+func (s implControllerServerStub) BlessingStoreDefault(ctx *context.T, call rpc.ServerCall) (*principal.JsBlessings, error) {
+	return s.impl.BlessingStoreDefault(ctx, call)
+}
+
+func (s implControllerServerStub) BlessingStorePublicKey(ctx *context.T, call rpc.ServerCall) (string, error) {
+	return s.impl.BlessingStorePublicKey(ctx, call)
+}
+
+func (s implControllerServerStub) BlessingStorePeerBlessings(ctx *context.T, call rpc.ServerCall) (map[security.BlessingPattern]*principal.JsBlessings, error) {
+	return s.impl.BlessingStorePeerBlessings(ctx, call)
+}
+
+func (s implControllerServerStub) BlessingStoreDebugString(ctx *context.T, call rpc.ServerCall) (string, error) {
+	return s.impl.BlessingStoreDebugString(ctx, call)
+}
+
 func (s implControllerServerStub) RemoteBlessings(ctx *context.T, call rpc.ServerCall, i0 string, i1 string) ([]string, error) {
 	return s.impl.RemoteBlessings(ctx, call, i0, i1)
 }
@@ -259,10 +328,6 @@
 	return s.impl.Signature(ctx, call, i0)
 }
 
-func (s implControllerServerStub) GetDefaultBlessings(ctx *context.T, call rpc.ServerCall) (*principal.JsBlessings, error) {
-	return s.impl.GetDefaultBlessings(ctx, call)
-}
-
 func (s implControllerServerStub) UnionOfBlessings(ctx *context.T, call rpc.ServerCall, i0 []principal.BlessingsHandle) (*principal.JsBlessings, error) {
 	return s.impl.UnionOfBlessings(ctx, call, i0)
 }
@@ -359,21 +424,66 @@
 			},
 		},
 		{
-			Name: "PutToBlessingStore",
-			Doc:  "// PutToBlessingStore puts the specified blessing to the blessing store under the provided pattern.",
+			Name: "AddToRoots",
+			Doc:  "// AddToRoots adds the provided blessing as a root.",
 			InArgs: []rpc.ArgDesc{
-				{"handle", ``},  // principal.BlessingsHandle
-				{"pattern", ``}, // security.BlessingPattern
+				{"handle", ``}, // principal.BlessingsHandle
+			},
+		},
+		{
+			Name: "BlessingStoreSet",
+			Doc:  "// BlessingStoreSet puts the specified blessing in the blessing store under the provided pattern.",
+			InArgs: []rpc.ArgDesc{
+				{"blessingsHandle", ``}, // principal.BlessingsHandle
+				{"pattern", ``},         // security.BlessingPattern
 			},
 			OutArgs: []rpc.ArgDesc{
 				{"", ``}, // *principal.JsBlessings
 			},
 		},
 		{
-			Name: "AddToRoots",
-			Doc:  "// AddToRoots adds the provided blessing as a root.",
+			Name: "BlessingStoreForPeer",
+			Doc:  "// BlessingStoreForPeer retrieves the blessings marked for the given peers.",
 			InArgs: []rpc.ArgDesc{
-				{"handle", ``}, // principal.BlessingsHandle
+				{"peerBlessings", ``}, // []string
+			},
+			OutArgs: []rpc.ArgDesc{
+				{"", ``}, // *principal.JsBlessings
+			},
+		},
+		{
+			Name: "BlessingStoreSetDefault",
+			Doc:  "// BlessingStoreSetDefault sets the default blessings.",
+			InArgs: []rpc.ArgDesc{
+				{"blessingsHandle", ``}, // principal.BlessingsHandle
+			},
+		},
+		{
+			Name: "BlessingStoreDefault",
+			Doc:  "// BlessingStoreDefault fetches the default blessings for the principal of the controller.",
+			OutArgs: []rpc.ArgDesc{
+				{"", ``}, // *principal.JsBlessings
+			},
+		},
+		{
+			Name: "BlessingStorePublicKey",
+			Doc:  "// BlessingStorePublicKey fetches the public key of the principal for which this store hosts blessings.",
+			OutArgs: []rpc.ArgDesc{
+				{"", ``}, // string
+			},
+		},
+		{
+			Name: "BlessingStorePeerBlessings",
+			Doc:  "// BlessingStorePeerBlessings returns all the blessings that the BlessingStore holds.",
+			OutArgs: []rpc.ArgDesc{
+				{"", ``}, // map[security.BlessingPattern]*principal.JsBlessings
+			},
+		},
+		{
+			Name: "BlessingStoreDebugString",
+			Doc:  "// BlessingStoreDebugString retrieves a debug string describing the state of the blessing store",
+			OutArgs: []rpc.ArgDesc{
+				{"", ``}, // string
 			},
 		},
 		{
@@ -398,13 +508,6 @@
 			},
 		},
 		{
-			Name: "GetDefaultBlessings",
-			Doc:  "// GetDefaultBlessings fetches the default blessings for the principal of the controller.",
-			OutArgs: []rpc.ArgDesc{
-				{"", ``}, // *principal.JsBlessings
-			},
-		},
-		{
 			Name: "UnionOfBlessings",
 			Doc:  "// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.",
 			InArgs: []rpc.ArgDesc{
diff --git a/services/wspr/internal/app/controller.vdl.go.orig b/services/wspr/internal/app/controller.vdl.go.orig
new file mode 100644
index 0000000..b8d730a
--- /dev/null
+++ b/services/wspr/internal/app/controller.vdl.go.orig
@@ -0,0 +1,550 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file was auto-generated by the vanadium vdl tool.
+// Source: controller.vdl
+
+package app
+
+import (
+	// VDL system imports
+	"v.io/v23"
+	"v.io/v23/context"
+	"v.io/v23/rpc"
+
+	// VDL user imports
+	"v.io/v23/security"
+	"v.io/v23/vdlroot/signature"
+	"v.io/x/ref/services/wspr/internal/principal"
+)
+
+// ControllerClientMethods is the client interface
+// containing Controller methods.
+type ControllerClientMethods interface {
+	// Serve instructs WSPR to start listening for calls on behalf
+	// of a javascript server.
+	Serve(ctx *context.T, name string, serverId uint32, serverOpts []RpcServerOption, opts ...rpc.CallOpt) error
+	// Stop instructs WSPR to stop listening for calls for the
+	// given javascript server.
+	Stop(ctx *context.T, serverId uint32, opts ...rpc.CallOpt) error
+	// AddName adds a published name to an existing server.
+	AddName(ctx *context.T, serverId uint32, name string, opts ...rpc.CallOpt) error
+	// RemoveName removes a published name from an existing server.
+	RemoveName(ctx *context.T, serverId uint32, name string, opts ...rpc.CallOpt) error
+	// UnlinkBlessings removes the given blessings from the blessings store.
+	UnlinkBlessings(ctx *context.T, handle principal.BlessingsHandle, opts ...rpc.CallOpt) error
+	// BlessingsDebugString gets a string useful for debugging blessings.
+	BlessingsDebugString(ctx *context.T, handle principal.BlessingsHandle, opts ...rpc.CallOpt) (string, error)
+	// Bless binds extensions of blessings held by this principal to
+	// another principal (represented by its public key).
+	Bless(ctx *context.T, publicKey string, handle principal.BlessingsHandle, extension string, caveat []security.Caveat, opts ...rpc.CallOpt) (publicKeyOut string, handleOut principal.BlessingsHandle, err error)
+	// BlessSelf creates a blessing with the provided name for this principal.
+	BlessSelf(ctx *context.T, name string, caveats []security.Caveat, opts ...rpc.CallOpt) (publicKeyOut string, handleOut principal.BlessingsHandle, err error)
+	// AddToRoots adds the provided blessing as a root.
+	AddToRoots(ctx *context.T, handle principal.BlessingsHandle, opts ...rpc.CallOpt) error
+	// BlessingStoreSet puts the specified blessing in the blessing store under the provided pattern.
+	BlessingStoreSet(ctx *context.T, blessingsHandle principal.BlessingsHandle, pattern security.BlessingPattern, opts ...rpc.CallOpt) (*principal.JsBlessings, error)
+	// BlessingStoreForPeer retrieves the blessings marked for the given peers.
+	BlessingStoreForPeer(ctx *context.T, peerBlessings []string, opts ...rpc.CallOpt) (*principal.JsBlessings, error)
+	// BlessingStoreSetDefault sets the default blessings.
+	BlessingStoreSetDefault(ctx *context.T, blessingsHandle principal.BlessingsHandle, opts ...rpc.CallOpt) error
+	// BlessingStoreDefault fetches the default blessings for the principal of the controller.
+	BlessingStoreDefault(*context.T, ...rpc.CallOpt) (*principal.JsBlessings, error)
+	// BlessingStorePublicKey fetches the public key of the principal for which this store hosts blessings.
+	BlessingStorePublicKey(*context.T, ...rpc.CallOpt) (string, error)
+	// BlessingStorePeerBlessings returns all the blessings that the BlessingStore holds.
+	BlessingStorePeerBlessings(*context.T, ...rpc.CallOpt) (map[security.BlessingPattern]*principal.JsBlessings, error)
+	// BlessingStoreDebugString retrieves a debug string describing the state of the blessing store
+	BlessingStoreDebugString(*context.T, ...rpc.CallOpt) (string, error)
+	// RemoteBlessings fetches the remote blessings for a given name and method.
+	RemoteBlessings(ctx *context.T, name string, method string, opts ...rpc.CallOpt) ([]string, error)
+	// Signature fetches the signature for a given name.
+	Signature(ctx *context.T, name string, opts ...rpc.CallOpt) ([]signature.Interface, error)
+<<<<<<< HEAD
+=======
+	// GetDefaultBlessings fetches the default blessings for the principal of the controller.
+	GetDefaultBlessings(*context.T, ...rpc.CallOpt) (*principal.JsBlessings, error)
+>>>>>>> master
+	// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
+	UnionOfBlessings(ctx *context.T, toJoin []principal.BlessingsHandle, opts ...rpc.CallOpt) (*principal.JsBlessings, error)
+}
+
+// ControllerClientStub adds universal methods to ControllerClientMethods.
+type ControllerClientStub interface {
+	ControllerClientMethods
+	rpc.UniversalServiceMethods
+}
+
+// ControllerClient returns a client stub for Controller.
+func ControllerClient(name string) ControllerClientStub {
+	return implControllerClientStub{name}
+}
+
+type implControllerClientStub struct {
+	name string
+}
+
+func (c implControllerClientStub) Serve(ctx *context.T, i0 string, i1 uint32, i2 []RpcServerOption, opts ...rpc.CallOpt) (err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "Serve", []interface{}{i0, i1, i2}, nil, opts...)
+	return
+}
+
+func (c implControllerClientStub) Stop(ctx *context.T, i0 uint32, opts ...rpc.CallOpt) (err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "Stop", []interface{}{i0}, nil, opts...)
+	return
+}
+
+func (c implControllerClientStub) AddName(ctx *context.T, i0 uint32, i1 string, opts ...rpc.CallOpt) (err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "AddName", []interface{}{i0, i1}, nil, opts...)
+	return
+}
+
+func (c implControllerClientStub) RemoveName(ctx *context.T, i0 uint32, i1 string, opts ...rpc.CallOpt) (err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "RemoveName", []interface{}{i0, i1}, nil, opts...)
+	return
+}
+
+func (c implControllerClientStub) UnlinkBlessings(ctx *context.T, i0 principal.BlessingsHandle, opts ...rpc.CallOpt) (err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "UnlinkBlessings", []interface{}{i0}, nil, opts...)
+	return
+}
+
+func (c implControllerClientStub) BlessingsDebugString(ctx *context.T, i0 principal.BlessingsHandle, opts ...rpc.CallOpt) (o0 string, err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingsDebugString", []interface{}{i0}, []interface{}{&o0}, opts...)
+	return
+}
+
+func (c implControllerClientStub) Bless(ctx *context.T, i0 string, i1 principal.BlessingsHandle, i2 string, i3 []security.Caveat, opts ...rpc.CallOpt) (o0 string, o1 principal.BlessingsHandle, err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "Bless", []interface{}{i0, i1, i2, i3}, []interface{}{&o0, &o1}, opts...)
+	return
+}
+
+func (c implControllerClientStub) BlessSelf(ctx *context.T, i0 string, i1 []security.Caveat, opts ...rpc.CallOpt) (o0 string, o1 principal.BlessingsHandle, err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "BlessSelf", []interface{}{i0, i1}, []interface{}{&o0, &o1}, opts...)
+	return
+}
+
+func (c implControllerClientStub) AddToRoots(ctx *context.T, i0 principal.BlessingsHandle, opts ...rpc.CallOpt) (err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "AddToRoots", []interface{}{i0}, nil, opts...)
+	return
+}
+
+func (c implControllerClientStub) BlessingStoreSet(ctx *context.T, i0 principal.BlessingsHandle, i1 security.BlessingPattern, opts ...rpc.CallOpt) (o0 *principal.JsBlessings, err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStoreSet", []interface{}{i0, i1}, []interface{}{&o0}, opts...)
+	return
+}
+
+func (c implControllerClientStub) BlessingStoreForPeer(ctx *context.T, i0 []string, opts ...rpc.CallOpt) (o0 *principal.JsBlessings, err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStoreForPeer", []interface{}{i0}, []interface{}{&o0}, opts...)
+	return
+}
+
+func (c implControllerClientStub) BlessingStoreSetDefault(ctx *context.T, i0 principal.BlessingsHandle, opts ...rpc.CallOpt) (err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStoreSetDefault", []interface{}{i0}, nil, opts...)
+	return
+}
+
+func (c implControllerClientStub) BlessingStoreDefault(ctx *context.T, opts ...rpc.CallOpt) (o0 *principal.JsBlessings, err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStoreDefault", nil, []interface{}{&o0}, opts...)
+	return
+}
+
+func (c implControllerClientStub) BlessingStorePublicKey(ctx *context.T, opts ...rpc.CallOpt) (o0 string, err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStorePublicKey", nil, []interface{}{&o0}, opts...)
+	return
+}
+
+func (c implControllerClientStub) BlessingStorePeerBlessings(ctx *context.T, opts ...rpc.CallOpt) (o0 map[security.BlessingPattern]*principal.JsBlessings, err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStorePeerBlessings", nil, []interface{}{&o0}, opts...)
+	return
+}
+
+func (c implControllerClientStub) BlessingStoreDebugString(ctx *context.T, opts ...rpc.CallOpt) (o0 string, err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStoreDebugString", nil, []interface{}{&o0}, opts...)
+	return
+}
+
+func (c implControllerClientStub) RemoteBlessings(ctx *context.T, i0 string, i1 string, opts ...rpc.CallOpt) (o0 []string, err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "RemoteBlessings", []interface{}{i0, i1}, []interface{}{&o0}, opts...)
+	return
+}
+
+func (c implControllerClientStub) Signature(ctx *context.T, i0 string, opts ...rpc.CallOpt) (o0 []signature.Interface, err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "Signature", []interface{}{i0}, []interface{}{&o0}, opts...)
+	return
+}
+
+func (c implControllerClientStub) UnionOfBlessings(ctx *context.T, i0 []principal.BlessingsHandle, opts ...rpc.CallOpt) (o0 *principal.JsBlessings, err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "UnionOfBlessings", []interface{}{i0}, []interface{}{&o0}, opts...)
+	return
+}
+
+func (c implControllerClientStub) UnionOfBlessings(ctx *context.T, i0 []principal.BlessingsHandle, opts ...rpc.CallOpt) (o0 *principal.JsBlessings, err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "UnionOfBlessings", []interface{}{i0}, []interface{}{&o0}, opts...)
+	return
+}
+
+// ControllerServerMethods is the interface a server writer
+// implements for Controller.
+type ControllerServerMethods interface {
+	// Serve instructs WSPR to start listening for calls on behalf
+	// of a javascript server.
+	Serve(ctx *context.T, call rpc.ServerCall, name string, serverId uint32, serverOpts []RpcServerOption) error
+	// Stop instructs WSPR to stop listening for calls for the
+	// given javascript server.
+	Stop(ctx *context.T, call rpc.ServerCall, serverId uint32) error
+	// AddName adds a published name to an existing server.
+	AddName(ctx *context.T, call rpc.ServerCall, serverId uint32, name string) error
+	// RemoveName removes a published name from an existing server.
+	RemoveName(ctx *context.T, call rpc.ServerCall, serverId uint32, name string) error
+	// UnlinkBlessings removes the given blessings from the blessings store.
+	UnlinkBlessings(ctx *context.T, call rpc.ServerCall, handle principal.BlessingsHandle) error
+	// BlessingsDebugString gets a string useful for debugging blessings.
+	BlessingsDebugString(ctx *context.T, call rpc.ServerCall, handle principal.BlessingsHandle) (string, error)
+	// Bless binds extensions of blessings held by this principal to
+	// another principal (represented by its public key).
+	Bless(ctx *context.T, call rpc.ServerCall, publicKey string, handle principal.BlessingsHandle, extension string, caveat []security.Caveat) (publicKeyOut string, handleOut principal.BlessingsHandle, err error)
+	// BlessSelf creates a blessing with the provided name for this principal.
+	BlessSelf(ctx *context.T, call rpc.ServerCall, name string, caveats []security.Caveat) (publicKeyOut string, handleOut principal.BlessingsHandle, err error)
+	// AddToRoots adds the provided blessing as a root.
+	AddToRoots(ctx *context.T, call rpc.ServerCall, handle principal.BlessingsHandle) error
+	// BlessingStoreSet puts the specified blessing in the blessing store under the provided pattern.
+	BlessingStoreSet(ctx *context.T, call rpc.ServerCall, blessingsHandle principal.BlessingsHandle, pattern security.BlessingPattern) (*principal.JsBlessings, error)
+	// BlessingStoreForPeer retrieves the blessings marked for the given peers.
+	BlessingStoreForPeer(ctx *context.T, call rpc.ServerCall, peerBlessings []string) (*principal.JsBlessings, error)
+	// BlessingStoreSetDefault sets the default blessings.
+	BlessingStoreSetDefault(ctx *context.T, call rpc.ServerCall, blessingsHandle principal.BlessingsHandle) error
+	// BlessingStoreDefault fetches the default blessings for the principal of the controller.
+	BlessingStoreDefault(*context.T, rpc.ServerCall) (*principal.JsBlessings, error)
+	// BlessingStorePublicKey fetches the public key of the principal for which this store hosts blessings.
+	BlessingStorePublicKey(*context.T, rpc.ServerCall) (string, error)
+	// BlessingStorePeerBlessings returns all the blessings that the BlessingStore holds.
+	BlessingStorePeerBlessings(*context.T, rpc.ServerCall) (map[security.BlessingPattern]*principal.JsBlessings, error)
+	// BlessingStoreDebugString retrieves a debug string describing the state of the blessing store
+	BlessingStoreDebugString(*context.T, rpc.ServerCall) (string, error)
+	// RemoteBlessings fetches the remote blessings for a given name and method.
+	RemoteBlessings(ctx *context.T, call rpc.ServerCall, name string, method string) ([]string, error)
+	// Signature fetches the signature for a given name.
+	Signature(ctx *context.T, call rpc.ServerCall, name string) ([]signature.Interface, error)
+<<<<<<< HEAD
+=======
+	// GetDefaultBlessings fetches the default blessings for the principal of the controller.
+	GetDefaultBlessings(*context.T, rpc.ServerCall) (*principal.JsBlessings, error)
+>>>>>>> master
+	// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
+	UnionOfBlessings(ctx *context.T, call rpc.ServerCall, toJoin []principal.BlessingsHandle) (*principal.JsBlessings, error)
+}
+
+// ControllerServerStubMethods is the server interface containing
+// Controller methods, as expected by rpc.Server.
+// There is no difference between this interface and ControllerServerMethods
+// since there are no streaming methods.
+type ControllerServerStubMethods ControllerServerMethods
+
+// ControllerServerStub adds universal methods to ControllerServerStubMethods.
+type ControllerServerStub interface {
+	ControllerServerStubMethods
+	// Describe the Controller interfaces.
+	Describe__() []rpc.InterfaceDesc
+}
+
+// ControllerServer returns a server stub for Controller.
+// It converts an implementation of ControllerServerMethods into
+// an object that may be used by rpc.Server.
+func ControllerServer(impl ControllerServerMethods) ControllerServerStub {
+	stub := implControllerServerStub{
+		impl: impl,
+	}
+	// Initialize GlobState; always check the stub itself first, to handle the
+	// case where the user has the Glob method defined in their VDL source.
+	if gs := rpc.NewGlobState(stub); gs != nil {
+		stub.gs = gs
+	} else if gs := rpc.NewGlobState(impl); gs != nil {
+		stub.gs = gs
+	}
+	return stub
+}
+
+type implControllerServerStub struct {
+	impl ControllerServerMethods
+	gs   *rpc.GlobState
+}
+
+func (s implControllerServerStub) Serve(ctx *context.T, call rpc.ServerCall, i0 string, i1 uint32, i2 []RpcServerOption) error {
+	return s.impl.Serve(ctx, call, i0, i1, i2)
+}
+
+func (s implControllerServerStub) Stop(ctx *context.T, call rpc.ServerCall, i0 uint32) error {
+	return s.impl.Stop(ctx, call, i0)
+}
+
+func (s implControllerServerStub) AddName(ctx *context.T, call rpc.ServerCall, i0 uint32, i1 string) error {
+	return s.impl.AddName(ctx, call, i0, i1)
+}
+
+func (s implControllerServerStub) RemoveName(ctx *context.T, call rpc.ServerCall, i0 uint32, i1 string) error {
+	return s.impl.RemoveName(ctx, call, i0, i1)
+}
+
+func (s implControllerServerStub) UnlinkBlessings(ctx *context.T, call rpc.ServerCall, i0 principal.BlessingsHandle) error {
+	return s.impl.UnlinkBlessings(ctx, call, i0)
+}
+
+func (s implControllerServerStub) BlessingsDebugString(ctx *context.T, call rpc.ServerCall, i0 principal.BlessingsHandle) (string, error) {
+	return s.impl.BlessingsDebugString(ctx, call, i0)
+}
+
+func (s implControllerServerStub) Bless(ctx *context.T, call rpc.ServerCall, i0 string, i1 principal.BlessingsHandle, i2 string, i3 []security.Caveat) (string, principal.BlessingsHandle, error) {
+	return s.impl.Bless(ctx, call, i0, i1, i2, i3)
+}
+
+func (s implControllerServerStub) BlessSelf(ctx *context.T, call rpc.ServerCall, i0 string, i1 []security.Caveat) (string, principal.BlessingsHandle, error) {
+	return s.impl.BlessSelf(ctx, call, i0, i1)
+}
+
+func (s implControllerServerStub) AddToRoots(ctx *context.T, call rpc.ServerCall, i0 principal.BlessingsHandle) error {
+	return s.impl.AddToRoots(ctx, call, i0)
+}
+
+func (s implControllerServerStub) BlessingStoreSet(ctx *context.T, call rpc.ServerCall, i0 principal.BlessingsHandle, i1 security.BlessingPattern) (*principal.JsBlessings, error) {
+	return s.impl.BlessingStoreSet(ctx, call, i0, i1)
+}
+
+func (s implControllerServerStub) BlessingStoreForPeer(ctx *context.T, call rpc.ServerCall, i0 []string) (*principal.JsBlessings, error) {
+	return s.impl.BlessingStoreForPeer(ctx, call, i0)
+}
+
+func (s implControllerServerStub) BlessingStoreSetDefault(ctx *context.T, call rpc.ServerCall, i0 principal.BlessingsHandle) error {
+	return s.impl.BlessingStoreSetDefault(ctx, call, i0)
+}
+
+func (s implControllerServerStub) BlessingStoreDefault(ctx *context.T, call rpc.ServerCall) (*principal.JsBlessings, error) {
+	return s.impl.BlessingStoreDefault(ctx, call)
+}
+
+func (s implControllerServerStub) BlessingStorePublicKey(ctx *context.T, call rpc.ServerCall) (string, error) {
+	return s.impl.BlessingStorePublicKey(ctx, call)
+}
+
+func (s implControllerServerStub) BlessingStorePeerBlessings(ctx *context.T, call rpc.ServerCall) (map[security.BlessingPattern]*principal.JsBlessings, error) {
+	return s.impl.BlessingStorePeerBlessings(ctx, call)
+}
+
+func (s implControllerServerStub) BlessingStoreDebugString(ctx *context.T, call rpc.ServerCall) (string, error) {
+	return s.impl.BlessingStoreDebugString(ctx, call)
+}
+
+func (s implControllerServerStub) RemoteBlessings(ctx *context.T, call rpc.ServerCall, i0 string, i1 string) ([]string, error) {
+	return s.impl.RemoteBlessings(ctx, call, i0, i1)
+}
+
+func (s implControllerServerStub) Signature(ctx *context.T, call rpc.ServerCall, i0 string) ([]signature.Interface, error) {
+	return s.impl.Signature(ctx, call, i0)
+}
+
+func (s implControllerServerStub) UnionOfBlessings(ctx *context.T, call rpc.ServerCall, i0 []principal.BlessingsHandle) (*principal.JsBlessings, error) {
+	return s.impl.UnionOfBlessings(ctx, call, i0)
+}
+
+func (s implControllerServerStub) UnionOfBlessings(ctx *context.T, call rpc.ServerCall, i0 []principal.BlessingsHandle) (*principal.JsBlessings, error) {
+	return s.impl.UnionOfBlessings(ctx, call, i0)
+}
+
+func (s implControllerServerStub) Globber() *rpc.GlobState {
+	return s.gs
+}
+
+func (s implControllerServerStub) Describe__() []rpc.InterfaceDesc {
+	return []rpc.InterfaceDesc{ControllerDesc}
+}
+
+// ControllerDesc describes the Controller interface.
+var ControllerDesc rpc.InterfaceDesc = descController
+
+// descController hides the desc to keep godoc clean.
+var descController = rpc.InterfaceDesc{
+	Name:    "Controller",
+	PkgPath: "v.io/x/ref/services/wspr/internal/app",
+	Methods: []rpc.MethodDesc{
+		{
+			Name: "Serve",
+			Doc:  "// Serve instructs WSPR to start listening for calls on behalf\n// of a javascript server.",
+			InArgs: []rpc.ArgDesc{
+				{"name", ``},       // string
+				{"serverId", ``},   // uint32
+				{"serverOpts", ``}, // []RpcServerOption
+			},
+		},
+		{
+			Name: "Stop",
+			Doc:  "// Stop instructs WSPR to stop listening for calls for the\n// given javascript server.",
+			InArgs: []rpc.ArgDesc{
+				{"serverId", ``}, // uint32
+			},
+		},
+		{
+			Name: "AddName",
+			Doc:  "// AddName adds a published name to an existing server.",
+			InArgs: []rpc.ArgDesc{
+				{"serverId", ``}, // uint32
+				{"name", ``},     // string
+			},
+		},
+		{
+			Name: "RemoveName",
+			Doc:  "// RemoveName removes a published name from an existing server.",
+			InArgs: []rpc.ArgDesc{
+				{"serverId", ``}, // uint32
+				{"name", ``},     // string
+			},
+		},
+		{
+			Name: "UnlinkBlessings",
+			Doc:  "// UnlinkBlessings removes the given blessings from the blessings store.",
+			InArgs: []rpc.ArgDesc{
+				{"handle", ``}, // principal.BlessingsHandle
+			},
+		},
+		{
+			Name: "BlessingsDebugString",
+			Doc:  "// BlessingsDebugString gets a string useful for debugging blessings.",
+			InArgs: []rpc.ArgDesc{
+				{"handle", ``}, // principal.BlessingsHandle
+			},
+			OutArgs: []rpc.ArgDesc{
+				{"", ``}, // string
+			},
+		},
+		{
+			Name: "Bless",
+			Doc:  "// Bless binds extensions of blessings held by this principal to\n// another principal (represented by its public key).",
+			InArgs: []rpc.ArgDesc{
+				{"publicKey", ``}, // string
+				{"handle", ``},    // principal.BlessingsHandle
+				{"extension", ``}, // string
+				{"caveat", ``},    // []security.Caveat
+			},
+			OutArgs: []rpc.ArgDesc{
+				{"publicKeyOut", ``}, // string
+				{"handleOut", ``},    // principal.BlessingsHandle
+			},
+		},
+		{
+			Name: "BlessSelf",
+			Doc:  "// BlessSelf creates a blessing with the provided name for this principal.",
+			InArgs: []rpc.ArgDesc{
+				{"name", ``},    // string
+				{"caveats", ``}, // []security.Caveat
+			},
+			OutArgs: []rpc.ArgDesc{
+				{"publicKeyOut", ``}, // string
+				{"handleOut", ``},    // principal.BlessingsHandle
+			},
+		},
+		{
+			Name: "AddToRoots",
+			Doc:  "// AddToRoots adds the provided blessing as a root.",
+			InArgs: []rpc.ArgDesc{
+				{"handle", ``}, // principal.BlessingsHandle
+			},
+		},
+		{
+			Name: "BlessingStoreSet",
+			Doc:  "// BlessingStoreSet puts the specified blessing in the blessing store under the provided pattern.",
+			InArgs: []rpc.ArgDesc{
+				{"blessingsHandle", ``}, // principal.BlessingsHandle
+				{"pattern", ``},         // security.BlessingPattern
+			},
+			OutArgs: []rpc.ArgDesc{
+				{"", ``}, // *principal.JsBlessings
+			},
+		},
+		{
+			Name: "BlessingStoreForPeer",
+			Doc:  "// BlessingStoreForPeer retrieves the blessings marked for the given peers.",
+			InArgs: []rpc.ArgDesc{
+				{"peerBlessings", ``}, // []string
+			},
+			OutArgs: []rpc.ArgDesc{
+				{"", ``}, // *principal.JsBlessings
+			},
+		},
+		{
+			Name: "BlessingStoreSetDefault",
+			Doc:  "// BlessingStoreSetDefault sets the default blessings.",
+			InArgs: []rpc.ArgDesc{
+				{"blessingsHandle", ``}, // principal.BlessingsHandle
+			},
+		},
+		{
+			Name: "BlessingStoreDefault",
+			Doc:  "// BlessingStoreDefault fetches the default blessings for the principal of the controller.",
+			OutArgs: []rpc.ArgDesc{
+				{"", ``}, // *principal.JsBlessings
+			},
+		},
+		{
+			Name: "BlessingStorePublicKey",
+			Doc:  "// BlessingStorePublicKey fetches the public key of the principal for which this store hosts blessings.",
+			OutArgs: []rpc.ArgDesc{
+				{"", ``}, // string
+			},
+		},
+		{
+			Name: "BlessingStorePeerBlessings",
+			Doc:  "// BlessingStorePeerBlessings returns all the blessings that the BlessingStore holds.",
+			OutArgs: []rpc.ArgDesc{
+				{"", ``}, // map[security.BlessingPattern]*principal.JsBlessings
+			},
+		},
+		{
+			Name: "BlessingStoreDebugString",
+			Doc:  "// BlessingStoreDebugString retrieves a debug string describing the state of the blessing store",
+			OutArgs: []rpc.ArgDesc{
+				{"", ``}, // string
+			},
+		},
+		{
+			Name: "RemoteBlessings",
+			Doc:  "// RemoteBlessings fetches the remote blessings for a given name and method.",
+			InArgs: []rpc.ArgDesc{
+				{"name", ``},   // string
+				{"method", ``}, // string
+			},
+			OutArgs: []rpc.ArgDesc{
+				{"", ``}, // []string
+			},
+		},
+		{
+			Name: "Signature",
+			Doc:  "// Signature fetches the signature for a given name.",
+			InArgs: []rpc.ArgDesc{
+				{"name", ``}, // string
+			},
+			OutArgs: []rpc.ArgDesc{
+				{"", ``}, // []signature.Interface
+			},
+		},
+		{
+			Name: "UnionOfBlessings",
+			Doc:  "// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.",
+			InArgs: []rpc.ArgDesc{
+				{"toJoin", ``}, // []principal.BlessingsHandle
+			},
+			OutArgs: []rpc.ArgDesc{
+				{"", ``}, // *principal.JsBlessings
+			},
+		},
+		{
+			Name: "UnionOfBlessings",
+			Doc:  "// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.",
+			InArgs: []rpc.ArgDesc{
+				{"toJoin", ``}, // []principal.BlessingsHandle
+			},
+			OutArgs: []rpc.ArgDesc{
+				{"", ``}, // *principal.JsBlessings
+			},
+		},
+	},
+}
diff --git a/services/wspr/internal/app/controller.vdl.orig b/services/wspr/internal/app/controller.vdl.orig
new file mode 100644
index 0000000..87cc159
--- /dev/null
+++ b/services/wspr/internal/app/controller.vdl.orig
@@ -0,0 +1,67 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package app
+
+import (
+	"signature"
+
+	"v.io/v23/security"
+	"v.io/x/ref/services/wspr/internal/principal"
+)
+
+type Controller interface {
+	// Serve instructs WSPR to start listening for calls on behalf
+	// of a javascript server.
+	Serve(name string, serverId uint32, serverOpts []RpcServerOption) error
+	// Stop instructs WSPR to stop listening for calls for the
+	// given javascript server.
+	Stop(serverId uint32) error
+	// AddName adds a published name to an existing server.
+	AddName(serverId uint32, name string) error
+	// RemoveName removes a published name from an existing server.
+	RemoveName(serverId uint32, name string) error
+
+	// UnlinkBlessings removes the given blessings from the blessings store.
+	UnlinkBlessings(handle principal.BlessingsHandle) error
+	// BlessingsDebugString gets a string useful for debugging blessings.
+	BlessingsDebugString(handle principal.BlessingsHandle) (string | error)
+	// Bless binds extensions of blessings held by this principal to
+	// another principal (represented by its public key).
+	Bless(publicKey string, handle principal.BlessingsHandle, extension string, caveat []security.Caveat) (publicKeyOut string, handleOut principal.BlessingsHandle | error)
+	// BlessSelf creates a blessing with the provided name for this principal.
+	BlessSelf(name string, caveats []security.Caveat) (publicKeyOut string, handleOut principal.BlessingsHandle | error)
+	// AddToRoots adds the provided blessing as a root.
+	AddToRoots(handle principal.BlessingsHandle) error
+
+	// BlessingStoreSet puts the specified blessing in the blessing store under the provided pattern.
+	BlessingStoreSet(blessingsHandle principal.BlessingsHandle, pattern security.BlessingPattern) (?principal.JsBlessings | error)
+	// BlessingStoreForPeer retrieves the blessings marked for the given peers.
+	BlessingStoreForPeer(peerBlessings []string) (?principal.JsBlessings | error)
+	// BlessingStoreSetDefault sets the default blessings.
+	BlessingStoreSetDefault(blessingsHandle principal.BlessingsHandle) error
+	// BlessingStoreDefault fetches the default blessings for the principal of the controller.
+	BlessingStoreDefault() (?principal.JsBlessings | error)
+	// BlessingStorePublicKey fetches the public key of the principal for which this store hosts blessings.
+	BlessingStorePublicKey() (string | error)
+	// BlessingStorePeerBlessings returns all the blessings that the BlessingStore holds.
+	BlessingStorePeerBlessings() (map[security.BlessingPattern]?principal.JsBlessings | error)
+	// BlessingStoreDebugString retrieves a debug string describing the state of the blessing store
+	BlessingStoreDebugString() (string | error)
+
+
+	// RemoteBlessings fetches the remote blessings for a given name and method.
+	RemoteBlessings(name, method string) ([]string | error)
+	// Signature fetches the signature for a given name.
+	Signature(name string) ([]signature.Interface | error)
+
+<<<<<<< HEAD
+  // UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
+=======
+	// GetDefaultBlessings fetches the default blessings for the principal of the controller.
+	GetDefaultBlessings() (?principal.JsBlessings | error)
+	// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
+>>>>>>> master
+	UnionOfBlessings(toJoin []principal.BlessingsHandle) (?principal.JsBlessings | error)
+}
