wspr: Support for all methods on the blessing store

MultiPart: 1/2
Change-Id: If0bba07cd161d8ef577f0b1efa067f1cf2ada25a
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)
+}