Merge "veyron/lib/testutil/integration: add more godoc"
diff --git a/lib/exec/config.go b/lib/exec/config.go
index 52c622f..71fffd5 100644
--- a/lib/exec/config.go
+++ b/lib/exec/config.go
@@ -1,12 +1,10 @@
 package exec
 
 import (
-	"bytes"
-	"strings"
 	"sync"
 
 	"v.io/core/veyron2/verror2"
-	"v.io/core/veyron2/vom"
+	"v.io/core/veyron2/vom2"
 )
 
 // Config defines a simple key-value configuration.  Keys and values are
@@ -52,13 +50,13 @@
 	return &cfg{m: make(map[string]string)}
 }
 
-func (c cfg) Set(key, value string) {
+func (c *cfg) Set(key, value string) {
 	c.Lock()
 	defer c.Unlock()
 	c.m[key] = value
 }
 
-func (c cfg) Get(key string) (string, error) {
+func (c *cfg) Get(key string) (string, error) {
 	c.RLock()
 	defer c.RUnlock()
 	v, ok := c.m[key]
@@ -68,7 +66,7 @@
 	return v, nil
 }
 
-func (c cfg) Dump() (res map[string]string) {
+func (c *cfg) Dump() (res map[string]string) {
 	res = make(map[string]string)
 	c.RLock()
 	defer c.RUnlock()
@@ -78,31 +76,31 @@
 	return
 }
 
-func (c cfg) Clear(key string) {
+func (c *cfg) Clear(key string) {
 	c.Lock()
 	defer c.Unlock()
 	delete(c.m, key)
 }
 
-func (c cfg) Serialize() (string, error) {
-	var buf bytes.Buffer
+func (c *cfg) Serialize() (string, error) {
 	c.RLock()
-	defer c.RUnlock()
-	if err := vom.NewEncoder(&buf).Encode(c.m); err != nil {
+	data, err := vom2.Encode(c.m)
+	c.RUnlock()
+	if err != nil {
 		return "", err
 	}
-	return buf.String(), nil
+	return string(data), nil
 }
 
-func (c cfg) MergeFrom(serialized string) error {
+func (c *cfg) MergeFrom(serialized string) error {
 	var newM map[string]string
-	if err := vom.NewDecoder(strings.NewReader(serialized)).Decode(&newM); err != nil {
+	if err := vom2.Decode([]byte(serialized), &newM); err != nil {
 		return err
 	}
 	c.Lock()
-	defer c.Unlock()
 	for k, v := range newM {
 		c.m[k] = v
 	}
+	c.Unlock()
 	return nil
 }
diff --git a/lib/modules/shell.go b/lib/modules/shell.go
index ecaefde..6ed18d4 100644
--- a/lib/modules/shell.go
+++ b/lib/modules/shell.go
@@ -155,7 +155,7 @@
 		return nil, err
 	}
 	syscall.CloseOnExec(fd)
-	p, err := agent.NewAgentPrincipal(ctx, fd)
+	p, err := agent.NewAgentPrincipal(ctx, fd, veyron2.GetClient(ctx))
 	if err != nil {
 		return nil, err
 	}
diff --git a/lib/signals/signals.go b/lib/signals/signals.go
index e2d64a6..564c6c6 100644
--- a/lib/signals/signals.go
+++ b/lib/signals/signals.go
@@ -4,6 +4,7 @@
 	"os"
 	"os/signal"
 	"syscall"
+	"time"
 
 	"v.io/core/veyron2"
 	"v.io/core/veyron2/context"
@@ -19,6 +20,25 @@
 	DoubleStopExitCode = 1
 )
 
+// TODO(caprita): Needless to say, this is a hack.  The motivator was getting
+// the device manager (run by the security agent) to shut down cleanly when the
+// process group containing both the agent and device manager receives a signal
+// (and the agent propagates that signal to the child).  We should be able to
+// finesse this by demonizing the device manager and/or being smarter about how
+// and when the agent sends the signal to the child.
+
+// SameSignalTimeWindow specifies the time window during which multiple
+// deliveries of the same signal are counted as one signal.  If set to zero, no
+// such de-duping occurs.  This is useful in situations where a process receives
+// a signal explicitly sent by its parent when the parent receives the signal,
+// but also receives it independently by virtue of being part of the same
+// process group.
+//
+// This is a variable, so that I can be set appropriately.  Note, there is no
+// locking around it, the assumption being that it's set during initialization
+// and never reset afterwards.
+var SameSignalTimeWindow time.Duration
+
 // defaultSignals returns a set of platform-specific signals that an application
 // is encouraged to listen on.
 func defaultSignals() []os.Signal {
@@ -68,11 +88,19 @@
 	go func() {
 		// First signal received.
 		sig := <-ch
+		sigTime := time.Now()
 		ret <- sig
 		// Wait for a second signal, and force an exit if the process is
 		// still executing cleanup code.
-		<-ch
-		os.Exit(DoubleStopExitCode)
+		for {
+			secondSig := <-ch
+			// If signal de-duping is enabled, ignore the signal if
+			// it's the same signal and has occured within the
+			// specified time window.
+			if SameSignalTimeWindow <= 0 || secondSig.String() != sig.String() || sigTime.Add(SameSignalTimeWindow).Before(time.Now()) {
+				os.Exit(DoubleStopExitCode)
+			}
+		}
 	}()
 	return ret
 }
diff --git a/profiles/chrome/chromeinit.go b/profiles/chrome/chromeinit.go
index e7c37cb..b18108d 100644
--- a/profiles/chrome/chromeinit.go
+++ b/profiles/chrome/chromeinit.go
@@ -19,6 +19,6 @@
 	if err != nil {
 		return nil, nil, shutdown, err
 	}
-	veyron2.GetLogger(ctx).VI(1).Infof("Initializing chrome profile.")
+	runtime.GetLogger(ctx).VI(1).Infof("Initializing chrome profile.")
 	return runtime, ctx, shutdown, nil
 }
diff --git a/profiles/gce/initx.go b/profiles/gce/initx.go
index 60f1e69..4aa63c8 100644
--- a/profiles/gce/initx.go
+++ b/profiles/gce/initx.go
@@ -41,7 +41,7 @@
 	if err != nil {
 		return nil, nil, shutdown, err
 	}
-	veyron2.GetLogger(ctx).VI(1).Infof("Initializing GCE profile.")
+	runtime.GetLogger(ctx).VI(1).Infof("Initializing GCE profile.")
 
 	lf := commonFlags.ListenFlags()
 	listenSpec := ipc.ListenSpec{
diff --git a/profiles/genericinit.go b/profiles/genericinit.go
index 73224f6..cbd7312 100644
--- a/profiles/genericinit.go
+++ b/profiles/genericinit.go
@@ -20,7 +20,7 @@
 	if err != nil {
 		return nil, nil, nil, err
 	}
-	veyron2.GetLogger(ctx).VI(1).Infof("Initializing generic profile.")
+	runtime.GetLogger(ctx).VI(1).Infof("Initializing generic profile.")
 
 	ac := appcycle.New()
 	ctx = runtime.SetAppCycle(ctx, ac)
diff --git a/profiles/roaming/roaminginit.go b/profiles/roaming/roaminginit.go
index f36720d..533cabb 100644
--- a/profiles/roaming/roaminginit.go
+++ b/profiles/roaming/roaminginit.go
@@ -76,7 +76,7 @@
 		}
 	}
 
-	publisher := veyron2.GetPublisher(ctx)
+	publisher := runtime.GetPublisher(ctx)
 
 	// Create stream in Init function to avoid a race between any
 	// goroutines started here and consumers started after Init returns.
@@ -106,13 +106,13 @@
 	cleanupCh := make(chan struct{})
 	watcherCh := make(chan struct{})
 
-	listenSpec.StreamPublisher = veyron2.GetPublisher(ctx)
+	listenSpec.StreamPublisher = publisher
 	listenSpec.StreamName = SettingsStreamName
 	listenSpec.AddressChooser = internal.IPAddressChooser
 
 	ctx = runtime.SetListenSpec(ctx, listenSpec)
 
-	go monitorNetworkSettingsX(ctx, watcher, prev, stop, cleanupCh, watcherCh, ch, ListenSpec)
+	go monitorNetworkSettingsX(runtime, ctx, watcher, prev, stop, cleanupCh, watcherCh, ch)
 	profileShutdown := func() {
 		close(cleanupCh)
 		shutdown()
@@ -124,11 +124,18 @@
 
 // monitorNetworkSettings will monitor network configuration changes and
 // publish subsequent Settings to reflect any changes detected.
-func monitorNetworkSettingsX(ctx *context.T, watcher netconfig.NetConfigWatcher, prev netstate.AddrList, pubStop, cleanup <-chan struct{},
-	watcherLoop chan<- struct{}, ch chan<- config.Setting, listenSpec ipc.ListenSpec) {
+func monitorNetworkSettingsX(
+	runtime *grt.RuntimeX,
+	ctx *context.T,
+	watcher netconfig.NetConfigWatcher,
+	prev netstate.AddrList,
+	pubStop, cleanup <-chan struct{},
+	watcherLoop chan<- struct{},
+	ch chan<- config.Setting) {
 	defer close(ch)
 
-	log := veyron2.GetLogger(ctx)
+	log := runtime.GetLogger(ctx)
+	listenSpec := runtime.GetListenSpec(ctx)
 
 	// TODO(cnicolaou): add support for listening on multiple network addresses.
 
diff --git a/runtimes/google/ipc/benchmark/service.vdl.go b/runtimes/google/ipc/benchmark/service.vdl.go
index cea2802..a09b115 100644
--- a/runtimes/google/ipc/benchmark/service.vdl.go
+++ b/runtimes/google/ipc/benchmark/service.vdl.go
@@ -14,14 +14,8 @@
 	__context "v.io/core/veyron2/context"
 	__ipc "v.io/core/veyron2/ipc"
 	__vdlutil "v.io/core/veyron2/vdl/vdlutil"
-	__wiretype "v.io/core/veyron2/wiretype"
 )
 
-// TODO(toddw): Remove this line once the new signature support is done.
-// It corrects a bug where __wiretype is unused in VDL pacakges where only
-// bootstrap types are used on interfaces.
-const _ = __wiretype.TypeIDInvalid
-
 // BenchmarkClientMethods is the client interface
 // containing Benchmark methods.
 type BenchmarkClientMethods interface {
@@ -80,17 +74,6 @@
 	return
 }
 
-func (c implBenchmarkClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&o0, &err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
 // BenchmarkEchoStreamClientStream is the client stream for Benchmark.EchoStream.
 type BenchmarkEchoStreamClientStream interface {
 	// RecvStream returns the receiver side of the Benchmark.EchoStream client stream.
@@ -220,8 +203,6 @@
 	BenchmarkServerStubMethods
 	// Describe the Benchmark interfaces.
 	Describe__() []__ipc.InterfaceDesc
-	// Signature will be replaced with Describe__.
-	Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
 }
 
 // BenchmarkServer returns a server stub for Benchmark.
@@ -293,33 +274,6 @@
 	},
 }
 
-func (s implBenchmarkServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
-	// TODO(toddw): Replace with new Describe__ implementation.
-	result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
-	result.Methods["Echo"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "Payload", Type: 66},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 66},
-			{Name: "", Type: 67},
-		},
-	}
-	result.Methods["EchoStream"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 67},
-		},
-		InStream:  66,
-		OutStream: 66,
-	}
-
-	result.TypeDefs = []__vdlutil.Any{
-		__wiretype.NamedPrimitiveType{Type: 0x32, Name: "byte", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x41, Name: "", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
-
-	return result, nil
-}
-
 // BenchmarkEchoStreamServerStream is the server stream for Benchmark.EchoStream.
 type BenchmarkEchoStreamServerStream interface {
 	// RecvStream returns the receiver side of the Benchmark.EchoStream server stream.
diff --git a/runtimes/google/ipc/client.go b/runtimes/google/ipc/client.go
index a472e68..2199a8d 100644
--- a/runtimes/google/ipc/client.go
+++ b/runtimes/google/ipc/client.go
@@ -21,7 +21,6 @@
 	old_verror "v.io/core/veyron2/verror"
 	verror "v.io/core/veyron2/verror2"
 	"v.io/core/veyron2/vlog"
-	"v.io/core/veyron2/vom"
 	"v.io/core/veyron2/vom2"
 	"v.io/core/veyron2/vtrace"
 
@@ -67,7 +66,7 @@
 
 	errArgEncoding = verror.Register(pkgPath+".argEncoding", verror.NoRetry, "failed to encode arg #{3}{:4:}")
 
-	errMismatchedResults = verror.Register(pkgPath+".mismatchedResults", verror.NoRetry, "expected {3} results, but got {4}")
+	errMismatchedResults = verror.Register(pkgPath+".mismatchedResults", verror.NoRetry, "got {3} results, but want {4}")
 
 	errResultDecoding = verror.Register(pkgPath+".resultDecoding", verror.NoRetry, "failed to decode result #{3}{:4}")
 
@@ -399,8 +398,8 @@
 	var servers []string
 	var pattern security.BlessingPattern
 
-	if resolved, err := c.ns.ResolveX(ctx, name, resolveOpts...); err != nil {
-		vlog.Errorf("ResolveX: %v", err)
+	if resolved, err := c.ns.Resolve(ctx, name, resolveOpts...); err != nil {
+		vlog.Errorf("Resolve: %v", err)
 		if verror.Is(err, naming.ErrNoSuchName.ID) {
 			return nil, verror.RetryRefetch, verror.Make(verror.NoServers, ctx, name)
 		}
@@ -674,12 +673,12 @@
 // flowClient implements the RPC client-side protocol for a single RPC, over a
 // flow that's already connected to the server.
 type flowClient struct {
-	ctx      *context.T   // context to annotate with call details
-	dec      vomDecoder   // to decode responses and results from the server
-	enc      vomEncoder   // to encode requests and args to the server
-	server   []string     // Blessings bound to the server that authorize it to receive the IPC request from the client.
-	flow     stream.Flow  // the underlying flow
-	response ipc.Response // each decoded response message is kept here
+	ctx      *context.T    // context to annotate with call details
+	dec      *vom2.Decoder // to decode responses and results from the server
+	enc      *vom2.Encoder // to encode requests and args to the server
+	server   []string      // Blessings bound to the server that authorize it to receive the IPC request from the client.
+	flow     stream.Flow   // the underlying flow
+	response ipc.Response  // each decoded response message is kept here
 
 	discharges []security.Discharge // discharges used for this request
 	dc         vc.DischargeClient   // client-global discharge-client
@@ -697,25 +696,18 @@
 func newFlowClient(ctx *context.T, server []string, flow stream.Flow, dc vc.DischargeClient) (*flowClient, error) {
 	fc := &flowClient{
 		ctx:    ctx,
-		dec:    vom.NewDecoder(flow),
-		enc:    vom.NewEncoder(flow),
 		server: server,
 		flow:   flow,
 		dc:     dc,
 	}
-	if vom2.IsEnabled() {
-		var err error
-		if fc.enc, err = vom2.NewBinaryEncoder(flow); err != nil {
-			berr := verror.Make(verror.BadProtocol, fc.ctx, verror.Make(errVomEncoder, fc.ctx, err))
-			return nil, fc.close(berr)
-		}
-		if fc.dec, err = vom2.NewDecoder(flow); err != nil {
-			berr := verror.Make(verror.BadProtocol, fc.ctx, verror.Make(errVomDecoder, fc.ctx, err))
-			return nil, fc.close(berr)
-		}
-	} else {
-		fc.dec = vom.NewDecoder(flow)
-		fc.enc = vom.NewEncoder(flow)
+	var err error
+	if fc.enc, err = vom2.NewBinaryEncoder(flow); err != nil {
+		berr := verror.Make(verror.BadProtocol, fc.ctx, verror.Make(errVomEncoder, fc.ctx, err))
+		return nil, fc.close(berr)
+	}
+	if fc.dec, err = vom2.NewDecoder(flow); err != nil {
+		berr := verror.Make(verror.BadProtocol, fc.ctx, verror.Make(errVomDecoder, fc.ctx, err))
+		return nil, fc.close(berr)
 	}
 	return fc, nil
 }
diff --git a/runtimes/google/ipc/client_test.go b/runtimes/google/ipc/client_test.go
index a124355..e44b5bb 100644
--- a/runtimes/google/ipc/client_test.go
+++ b/runtimes/google/ipc/client_test.go
@@ -98,7 +98,7 @@
 }
 
 func numServers(t *testing.T, name string) int {
-	me, err := veyron2.GetNamespace(gctx).ResolveX(gctx, name)
+	me, err := veyron2.GetNamespace(gctx).Resolve(gctx, name)
 	if err != nil {
 		return 0
 	}
diff --git a/runtimes/google/ipc/full_test.go b/runtimes/google/ipc/full_test.go
index 3db30e5..e8d702d 100644
--- a/runtimes/google/ipc/full_test.go
+++ b/runtimes/google/ipc/full_test.go
@@ -233,7 +233,7 @@
 }
 
 func verifyMount(t *testing.T, ns naming.Namespace, name string) []string {
-	me, err := ns.ResolveX(testContext(), name)
+	me, err := ns.Resolve(testContext(), name)
 	if err != nil {
 		t.Errorf("%s: %s not found in mounttable", loc(1), name)
 		return nil
@@ -242,7 +242,7 @@
 }
 
 func verifyMountMissing(t *testing.T, ns naming.Namespace, name string) {
-	if me, err := ns.ResolveX(testContext(), name); err == nil {
+	if me, err := ns.Resolve(testContext(), name); err == nil {
 		names := me.Names()
 		t.Errorf("%s: %s not supposed to be found in mounttable; got %d servers instead: %v", loc(1), name, len(names), names)
 	}
@@ -280,7 +280,7 @@
 // It must return a name since it'll be passed to StartCall.
 func fakeWSName(ns naming.Namespace, name string) (string, error) {
 	// Find the ws endpoint and use that.
-	me, err := ns.ResolveX(testContext(), name)
+	me, err := ns.Resolve(testContext(), name)
 	if err != nil {
 		return "", err
 	}
diff --git a/runtimes/google/ipc/server.go b/runtimes/google/ipc/server.go
index e9b7066..d6df99b 100644
--- a/runtimes/google/ipc/server.go
+++ b/runtimes/google/ipc/server.go
@@ -22,7 +22,6 @@
 	old_verror "v.io/core/veyron2/verror"
 	verror "v.io/core/veyron2/verror2"
 	"v.io/core/veyron2/vlog"
-	"v.io/core/veyron2/vom"
 	"v.io/core/veyron2/vom2"
 	"v.io/core/veyron2/vtrace"
 
@@ -35,7 +34,6 @@
 
 	// TODO(cnicolaou): finish verror -> verror2 transition, in particular
 	// for communicating from server to client.
-	// TODO(cnicolaou): remove the vom1 code now that vom2 is in place.
 )
 
 var (
@@ -122,7 +120,6 @@
 			s.preferredProtocols = []string(opt)
 		}
 	}
-	// TODO(suharshs,mattr): Get a client from the context.
 	client, err := InternalNewClient(streamMgr, ns)
 	if err != nil {
 		return nil, fmt.Errorf("failed to create discharge-client: %v", err)
@@ -158,7 +155,7 @@
 	if s.ns != nil {
 		var entry *naming.MountEntry
 		var err error
-		if entry, err = s.ns.ResolveX(s.ctx, address); err != nil {
+		if entry, err = s.ns.Resolve(s.ctx, address); err != nil {
 			return "", err
 		}
 		names = entry.Names()
@@ -796,23 +793,14 @@
 	return nil
 }
 
-// TODO(toddw): Remove these interfaces after the vom2 transition.
-type vomEncoder interface {
-	Encode(v interface{}) error
-}
-
-type vomDecoder interface {
-	Decode(v interface{}) error
-}
-
 // flowServer implements the RPC server-side protocol for a single RPC, over a
 // flow that's already connected to the client.
 type flowServer struct {
 	*context.T
 	server *server        // ipc.Server that this flow server belongs to
 	disp   ipc.Dispatcher // ipc.Dispatcher that will serve RPCs on this flow
-	dec    vomDecoder     // to decode requests and args from the client
-	enc    vomEncoder     // to encode responses and results to the client
+	dec    *vom2.Decoder  // to decode requests and args from the client
+	enc    *vom2.Encoder  // to encode responses and results to the client
 	flow   stream.Flow    // underlying flow
 
 	// Fields filled in during the server invocation.
@@ -841,66 +829,18 @@
 		flow:       flow,
 		discharges: make(map[string]security.Discharge),
 	}
-	if vom2.IsEnabled() {
-		var err error
-		if fs.dec, err = vom2.NewDecoder(flow); err != nil {
-			flow.Close()
-			return nil, err
-		}
-		if fs.enc, err = vom2.NewBinaryEncoder(flow); err != nil {
-			flow.Close()
-			return nil, err
-		}
-	} else {
-		fs.dec = vom.NewDecoder(flow)
-		fs.enc = vom.NewEncoder(flow)
+	var err error
+	if fs.dec, err = vom2.NewDecoder(flow); err != nil {
+		flow.Close()
+		return nil, err
+	}
+	if fs.enc, err = vom2.NewBinaryEncoder(flow); err != nil {
+		flow.Close()
+		return nil, err
 	}
 	return fs, nil
 }
 
-// Vom does not encode untyped nils.
-// Consequently, the ipc system does not allow nil results with an interface
-// type from server methods.  The one exception being errors.
-//
-// For now, the following hacky assumptions are made, which will be revisited when
-// a decision is made on how untyped nils should be encoded/decoded in
-// vom/vom2:
-//
-// - Server methods return 0 or more results
-// - Any values returned by the server that have an interface type are either
-//   non-nil or of type error.
-func vomErrorHack(res interface{}) vom.Value {
-	v := vom.ValueOf(res)
-	if !v.IsValid() {
-		// Untyped nils are assumed to be nil-errors.
-		var boxed old_verror.E
-		return vom.ValueOf(&boxed).Elem()
-	}
-	if err, iserr := res.(error); iserr {
-		// Convert errors to verror since errors are often not
-		// serializable via vom/gob (errors.New and fmt.Errorf return a
-		// type with no exported fields).
-		return vom.ValueOf(old_verror.Convert(err))
-	}
-	return v
-}
-
-// TODO(toddw): Remove this function and encodeValueHack after the vom2 transition.
-func vom2ErrorHack(res interface{}) interface{} {
-	if err, ok := res.(error); ok {
-		return &err
-	}
-	return res
-}
-
-// TODO(toddw): Remove this function and vom2ErrorHack after the vom2 transition.
-func (fs *flowServer) encodeValueHack(res interface{}) error {
-	if vom2.IsEnabled() {
-		return fs.enc.Encode(vom2ErrorHack(res))
-	}
-	return fs.enc.(*vom.Encoder).EncodeValue(vomErrorHack(res))
-}
-
 func (fs *flowServer) serve() error {
 	defer fs.flow.Close()
 
@@ -931,7 +871,7 @@
 		return response.Error
 	}
 	for ix, res := range results {
-		if err := fs.encodeValueHack(res); err != nil {
+		if err := fs.enc.Encode(res); err != nil {
 			if err == io.EOF {
 				return err
 			}
diff --git a/runtimes/google/ipc/server_test.go b/runtimes/google/ipc/server_test.go
index 1f362be..b71aed9 100644
--- a/runtimes/google/ipc/server_test.go
+++ b/runtimes/google/ipc/server_test.go
@@ -198,7 +198,7 @@
 	waitfor := func(expect int) {
 		then := time.Now().Add(time.Minute)
 		for {
-			me, err := ns.ResolveX(testContext(), name)
+			me, err := ns.Resolve(testContext(), name)
 			if err == nil && len(me.Servers) == expect {
 				close(ch)
 				return
@@ -268,7 +268,7 @@
 	}
 
 	for {
-		if _, err := ns.ResolveX(testContext(), name); err != nil {
+		if _, err := ns.Resolve(testContext(), name); err != nil {
 			break
 		}
 		time.Sleep(10 * time.Millisecond)
diff --git a/runtimes/google/lib/deque/deque.go b/runtimes/google/lib/deque/deque.go
index 54ddbfb..a104de2 100644
--- a/runtimes/google/lib/deque/deque.go
+++ b/runtimes/google/lib/deque/deque.go
@@ -105,10 +105,9 @@
 			q.contents = make([]interface{}, initialQueueSize)
 			return
 		}
-		contents := make([]interface{}, len(q.contents)*2)
-		for i := 0; i != q.size; i++ {
-			contents[i] = q.contents[(q.fx+i)%len(q.contents)]
-		}
+		contents := make([]interface{}, q.size*2)
+		i := copy(contents[:], q.contents[q.fx:])
+		copy(contents[i:], q.contents[:q.fx])
 		q.contents = contents
 		q.fx = 0
 		q.bx = q.size
diff --git a/runtimes/google/lib/deque/deque_test.go b/runtimes/google/lib/deque/deque_test.go
index 2e34c41..ae0d4d3 100644
--- a/runtimes/google/lib/deque/deque_test.go
+++ b/runtimes/google/lib/deque/deque_test.go
@@ -209,3 +209,41 @@
 		t.Errorf("Iteration did not stop correctly,expected 6 iterations, got %d", iterations)
 	}
 }
+
+func BenchmarkPushFront(b *testing.B) {
+	var q T
+	for i := 0; i < b.N; i++ {
+		q.PushFront(i)
+	}
+}
+
+func BenchmarkPushBack(b *testing.B) {
+	var q T
+	for i := 0; i < b.N; i++ {
+		q.PushBack(i)
+	}
+}
+
+func BenchmarkPopFront(b *testing.B) {
+	var q T
+	for i := 0; i < b.N; i++ {
+		q.PushBack(i)
+	}
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		q.PopFront()
+	}
+}
+
+func BenchmarkPopBack(b *testing.B) {
+	var q T
+	for i := 0; i < b.N; i++ {
+		q.PushFront(i)
+	}
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		q.PopBack()
+	}
+}
diff --git a/runtimes/google/lib/publisher/publisher.go b/runtimes/google/lib/publisher/publisher.go
index c5d35ed..5ccf6e7 100644
--- a/runtimes/google/lib/publisher/publisher.go
+++ b/runtimes/google/lib/publisher/publisher.go
@@ -342,7 +342,7 @@
 func (ps *pubState) published() []string {
 	var ret []string
 	for name, _ := range ps.names {
-		e, err := ps.ns.ResolveToMountTableX(ps.ctx, name)
+		e, err := ps.ns.ResolveToMountTable(ps.ctx, name)
 		if err != nil {
 			vlog.Errorf("ipc pub: couldn't resolve %v to mount table: %v", name, err)
 			continue
diff --git a/runtimes/google/lib/publisher/publisher_test.go b/runtimes/google/lib/publisher/publisher_test.go
index c0d0c4d..a947799 100644
--- a/runtimes/google/lib/publisher/publisher_test.go
+++ b/runtimes/google/lib/publisher/publisher_test.go
@@ -28,11 +28,11 @@
 }
 
 func resolve(t *testing.T, ns naming.Namespace, name string) []string {
-	servers, err := ns.Resolve(testContext(), name)
+	me, err := ns.Resolve(testContext(), name)
 	if err != nil {
 		t.Fatalf("failed to resolve %q", name)
 	}
-	return servers
+	return me.Names()
 }
 
 func TestAddAndRemove(t *testing.T) {
diff --git a/runtimes/google/naming/namespace/all_test.go b/runtimes/google/naming/namespace/all_test.go
index 406a884..ad898a7 100644
--- a/runtimes/google/naming/namespace/all_test.go
+++ b/runtimes/google/naming/namespace/all_test.go
@@ -149,19 +149,19 @@
 }
 
 func testResolveToMountTable(t *testing.T, ctx *context.T, ns naming.Namespace, name string, want ...string) {
-	doResolveTest(t, "ResolveToMountTable", ns.ResolveToMountTableX, ctx, name, want)
+	doResolveTest(t, "ResolveToMountTable", ns.ResolveToMountTable, ctx, name, want)
 }
 
 func testResolveToMountTableWithPattern(t *testing.T, ctx *context.T, ns naming.Namespace, name string, pattern naming.ResolveOpt, want ...string) {
-	doResolveTest(t, "ResolveToMountTable", ns.ResolveToMountTableX, ctx, name, want, pattern)
+	doResolveTest(t, "ResolveToMountTable", ns.ResolveToMountTable, ctx, name, want, pattern)
 }
 
 func testResolve(t *testing.T, ctx *context.T, ns naming.Namespace, name string, want ...string) {
-	doResolveTest(t, "Resolve", ns.ResolveX, ctx, name, want)
+	doResolveTest(t, "Resolve", ns.Resolve, ctx, name, want)
 }
 
 func testResolveWithPattern(t *testing.T, ctx *context.T, ns naming.Namespace, name string, pattern naming.ResolveOpt, want ...string) {
-	doResolveTest(t, "Resolve", ns.ResolveX, ctx, name, want, pattern)
+	doResolveTest(t, "Resolve", ns.Resolve, ctx, name, want, pattern)
 }
 
 type serverEntry struct {
@@ -562,7 +562,7 @@
 	for i := 0; i < 40; i++ {
 		cycle += "/c3/c4"
 	}
-	if _, err := ns.ResolveX(c, "c1/"+cycle); !verror.Is(err, naming.ErrResolutionDepthExceeded.ID) {
+	if _, err := ns.Resolve(c, "c1/"+cycle); !verror.Is(err, naming.ErrResolutionDepthExceeded.ID) {
 		boom(t, "Failed to detect cycle")
 	}
 
diff --git a/runtimes/google/naming/namespace/mount.go b/runtimes/google/naming/namespace/mount.go
index 9b7d186..66bf6d0 100644
--- a/runtimes/google/naming/namespace/mount.go
+++ b/runtimes/google/naming/namespace/mount.go
@@ -85,10 +85,11 @@
 // dispatch executes f in parallel for each mount table implementing mTName.
 func (ns *namespace) dispatch(ctx *context.T, mTName string, f func(*context.T, string, string) status) error {
 	// Resolve to all the mount tables implementing name.
-	mts, err := ns.ResolveToMountTable(ctx, mTName)
+	me, err := ns.ResolveToMountTable(ctx, mTName)
 	if err != nil {
 		return err
 	}
+	mts := me.Names()
 	// Apply f to each of the returned mount tables.
 	c := make(chan status, len(mts))
 	for _, mt := range mts {
diff --git a/runtimes/google/naming/namespace/resolve.go b/runtimes/google/naming/namespace/resolve.go
index bc79cc8..97f8e9b 100644
--- a/runtimes/google/naming/namespace/resolve.go
+++ b/runtimes/google/naming/namespace/resolve.go
@@ -32,7 +32,7 @@
 		}
 		// Not in cache, call the real server.
 		callCtx, _ := context.WithTimeout(ctx, callTimeout)
-		call, err := client.StartCall(callCtx, pattern_and_name, "ResolveStepX", nil, append(opts, options.NoResolve{})...)
+		call, err := client.StartCall(callCtx, pattern_and_name, "ResolveStep", nil, append(opts, options.NoResolve{})...)
 		if err != nil {
 			finalErr = err
 			vlog.VI(2).Infof("ResolveStep.StartCall %s failed: %s", name, err)
@@ -68,14 +68,14 @@
 	return len(e.Name) == 0
 }
 
-// ResolveX implements veyron2/naming.Namespace.
-func (ns *namespace) ResolveX(ctx *context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
+// Resolve implements veyron2/naming.Namespace.
+func (ns *namespace) Resolve(ctx *context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
 	defer vlog.LogCall()()
 	e, _ := ns.rootMountEntry(name)
 	if vlog.V(2) {
 		_, file, line, _ := runtime.Caller(1)
-		vlog.Infof("ResolveX(%s) called from %s:%d", name, file, line)
-		vlog.Infof("ResolveX(%s) -> rootMountEntry %v", name, *e)
+		vlog.Infof("Resolve(%s) called from %s:%d", name, file, line)
+		vlog.Infof("Resolve(%s) -> rootMountEntry %v", name, *e)
 	}
 	if skipResolve(opts) {
 		return e, nil
@@ -93,9 +93,9 @@
 	}
 	// Iterate walking through mount table servers.
 	for remaining := ns.maxResolveDepth; remaining > 0; remaining-- {
-		vlog.VI(2).Infof("ResolveX(%s) loop %v", name, *e)
+		vlog.VI(2).Infof("Resolve(%s) loop %v", name, *e)
 		if !e.ServesMountTable() || terminal(e) {
-			vlog.VI(1).Infof("ResolveX(%s) -> %v", name, *e)
+			vlog.VI(1).Infof("Resolve(%s) -> %v", name, *e)
 			return e, nil
 		}
 		var err error
@@ -104,13 +104,13 @@
 			// Lots of reasons why another error can happen.  We are trying
 			// to single out "this isn't a mount table".
 			if notAnMT(err) {
-				vlog.VI(1).Infof("ResolveX(%s) -> %v", name, curr)
+				vlog.VI(1).Infof("Resolve(%s) -> %v", name, curr)
 				return curr, nil
 			}
 			if verror.Is(err, naming.ErrNoSuchNameRoot.ID) {
 				err = verror.Make(naming.ErrNoSuchName, ctx, name)
 			}
-			vlog.VI(1).Infof("ResolveX(%s) -> (%s: %v)", err, name, curr)
+			vlog.VI(1).Infof("Resolve(%s) -> (%s: %v)", err, name, curr)
 			return nil, err
 		}
 		pattern = ""
@@ -118,24 +118,14 @@
 	return nil, verror.Make(naming.ErrResolutionDepthExceeded, ctx)
 }
 
-// Resolve implements veyron2/naming.Namespace.
-func (ns *namespace) Resolve(ctx *context.T, name string, opts ...naming.ResolveOpt) ([]string, error) {
-	defer vlog.LogCall()()
-	e, err := ns.ResolveX(ctx, name, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return e.Names(), nil
-}
-
-// ResolveToMountTableX implements veyron2/naming.Namespace.
-func (ns *namespace) ResolveToMountTableX(ctx *context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
+// ResolveToMountTable implements veyron2/naming.Namespace.
+func (ns *namespace) ResolveToMountTable(ctx *context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
 	defer vlog.LogCall()()
 	e, _ := ns.rootMountEntry(name)
 	if vlog.V(2) {
 		_, file, line, _ := runtime.Caller(1)
-		vlog.Infof("ResolveToMountTableX(%s) called from %s:%d", name, file, line)
-		vlog.Infof("ResolveToMountTableX(%s) -> rootNames %v", name, e)
+		vlog.Infof("ResolveToMountTable(%s) called from %s:%d", name, file, line)
+		vlog.Infof("ResolveToMountTable(%s) -> rootNames %v", name, e)
 	}
 	if len(e.Servers) == 0 {
 		return nil, verror.Make(naming.ErrNoMountTable, ctx)
@@ -144,33 +134,33 @@
 	client := veyron2.GetClient(ctx)
 	last := e
 	for remaining := ns.maxResolveDepth; remaining > 0; remaining-- {
-		vlog.VI(2).Infof("ResolveToMountTableX(%s) loop %v", name, e)
+		vlog.VI(2).Infof("ResolveToMountTable(%s) loop %v", name, e)
 		var err error
 		curr := e
 		// If the next name to resolve doesn't point to a mount table, we're done.
 		if !e.ServesMountTable() || terminal(e) {
-			vlog.VI(1).Infof("ResolveToMountTableX(%s) -> %v", name, last)
+			vlog.VI(1).Infof("ResolveToMountTable(%s) -> %v", name, last)
 			return last, nil
 		}
 		if e, err = ns.resolveAgainstMountTable(ctx, client, e, pattern); err != nil {
 			if verror.Is(err, naming.ErrNoSuchNameRoot.ID) {
-				vlog.VI(1).Infof("ResolveToMountTableX(%s) -> %v (NoSuchRoot: %v)", name, last, curr)
+				vlog.VI(1).Infof("ResolveToMountTable(%s) -> %v (NoSuchRoot: %v)", name, last, curr)
 				return last, nil
 			}
 			if verror.Is(err, naming.ErrNoSuchName.ID) {
-				vlog.VI(1).Infof("ResolveToMountTableX(%s) -> %v (NoSuchName: %v)", name, curr, curr)
+				vlog.VI(1).Infof("ResolveToMountTable(%s) -> %v (NoSuchName: %v)", name, curr, curr)
 				return curr, nil
 			}
 			// Lots of reasons why another error can happen.  We are trying
 			// to single out "this isn't a mount table".
 			if notAnMT(err) {
-				vlog.VI(1).Infof("ResolveToMountTableX(%s) -> %v", name, last)
+				vlog.VI(1).Infof("ResolveToMountTable(%s) -> %v", name, last)
 				return last, nil
 			}
 			// TODO(caprita): If the server is unreachable for
 			// example, we may still want to return its parent
 			// mounttable rather than an error.
-			vlog.VI(1).Infof("ResolveToMountTableX(%s) -> %v", name, err)
+			vlog.VI(1).Infof("ResolveToMountTable(%s) -> %v", name, err)
 			return nil, err
 		}
 		last = curr
@@ -179,16 +169,6 @@
 	return nil, verror.Make(naming.ErrResolutionDepthExceeded, ctx)
 }
 
-// ResolveToMountTable implements veyron2/naming.Namespace.
-func (ns *namespace) ResolveToMountTable(ctx *context.T, name string, opts ...naming.ResolveOpt) ([]string, error) {
-	defer vlog.LogCall()()
-	e, err := ns.ResolveToMountTableX(ctx, name, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return e.Names(), nil
-}
-
 // FlushCache flushes the most specific entry found for name.  It returns true if anything was
 // actually flushed.
 func (ns *namespace) FlushCacheEntry(name string) bool {
diff --git a/runtimes/google/rt/rt.go b/runtimes/google/rt/rt.go
index 77f1258..c7bcafa 100644
--- a/runtimes/google/rt/rt.go
+++ b/runtimes/google/rt/rt.go
@@ -137,15 +137,16 @@
 		}
 	}
 
-	// This call to NewClient creates a client that is attached to the context used
-	// by the NewAgentPrincipal call in initSecurity. The context used by NewAgentPrincipal
-	// is incomplete and only works because the agent uses anonymous unix sockets and
+	// This call to NewClient creates a client that is used by the
+	// NewAgentPrincipal call in initSecurity. This client is incomplete
+	// and only works because the agent uses anonymous unix sockets and
 	// VCSecurityNone.
-	if rt.client, err = rt.NewClient(); err != nil {
+	client, err := rt.NewClient()
+	if err != nil {
 		return nil, fmt.Errorf("failed to create new client: %s", err)
 	}
 
-	if err := rt.initSecurity(handle, rt.flags.Credentials); err != nil {
+	if err := rt.initSecurity(handle, rt.flags.Credentials, client); err != nil {
 		return nil, fmt.Errorf("failed to init security: %s", err)
 	}
 
diff --git a/runtimes/google/rt/runtimex.go b/runtimes/google/rt/runtimex.go
index c2a5ac3..ff35b2d 100644
--- a/runtimes/google/rt/runtimex.go
+++ b/runtimes/google/rt/runtimex.go
@@ -166,16 +166,16 @@
 		return nil, nil, nil, err
 	}
 
-	// The client we attach here is incomplete (has a nil principal) and only works
+	// The client we create here is incomplete (has a nil principal) and only works
 	// because the agent uses anonymous unix sockets and VCSecurityNone.
 	// After security is initialized we will attach a real client.
-	ctx, _, err = r.SetNewClient(ctx)
+	_, client, err := r.SetNewClient(ctx)
 	if err != nil {
 		return nil, nil, nil, err
 	}
 
 	// Initialize security.
-	principal, err := initSecurity(ctx, handle, flags.Credentials)
+	principal, err := initSecurity(ctx, handle, flags.Credentials, client)
 	if err != nil {
 		return nil, nil, nil, err
 	}
diff --git a/runtimes/google/rt/security.go b/runtimes/google/rt/security.go
index 5f6a14d..1ea73f4 100644
--- a/runtimes/google/rt/security.go
+++ b/runtimes/google/rt/security.go
@@ -4,6 +4,7 @@
 	"os"
 	"syscall"
 
+	"v.io/core/veyron2/ipc"
 	"v.io/core/veyron2/security"
 
 	"v.io/core/veyron/lib/exec"
@@ -16,8 +17,8 @@
 	return rt.principal
 }
 
-func (rt *vrt) initSecurity(handle *exec.ChildHandle, credentials string) error {
-	if err := rt.setupPrincipal(handle, credentials); err != nil {
+func (rt *vrt) initSecurity(handle *exec.ChildHandle, credentials string, client ipc.Client) error {
+	if err := rt.setupPrincipal(handle, credentials, client); err != nil {
 		return err
 	}
 	stats.NewString("security/principal/key").Set(rt.principal.PublicKey().String())
@@ -26,7 +27,7 @@
 	return nil
 }
 
-func (rt *vrt) setupPrincipal(handle *exec.ChildHandle, credentials string) error {
+func (rt *vrt) setupPrincipal(handle *exec.ChildHandle, credentials string, client ipc.Client) error {
 	if rt.principal != nil {
 		return nil
 	}
@@ -34,7 +35,7 @@
 		return err
 	} else if fd >= 0 {
 		var err error
-		rt.principal, err = rt.connectToAgent(fd)
+		rt.principal, err = rt.connectToAgent(fd, client)
 		return err
 	}
 	if len(credentials) > 0 {
@@ -60,7 +61,7 @@
 	return vsecurity.InitDefaultBlessings(rt.principal, defaultBlessingName())
 }
 
-func (rt *vrt) connectToAgent(fd int) (security.Principal, error) {
+func (rt *vrt) connectToAgent(fd int, client ipc.Client) (security.Principal, error) {
 	// Dup the fd, so we can create multiple runtimes.
 	syscall.ForkLock.Lock()
 	newfd, err := syscall.Dup(fd)
@@ -71,5 +72,5 @@
 	if err != nil {
 		return nil, err
 	}
-	return agent.NewAgentPrincipal(rt.NewContext(), newfd)
+	return agent.NewAgentPrincipal(rt.NewContext(), newfd, client)
 }
diff --git a/runtimes/google/rt/securityx.go b/runtimes/google/rt/securityx.go
index 0c8ca3f..040ca83 100644
--- a/runtimes/google/rt/securityx.go
+++ b/runtimes/google/rt/securityx.go
@@ -8,6 +8,7 @@
 	"syscall"
 
 	"v.io/core/veyron2/context"
+	"v.io/core/veyron2/ipc"
 	"v.io/core/veyron2/mgmt"
 	"v.io/core/veyron2/security"
 
@@ -17,8 +18,8 @@
 	"v.io/core/veyron/security/agent"
 )
 
-func initSecurity(ctx *context.T, handle *exec.ChildHandle, credentials string) (security.Principal, error) {
-	principal, err := setupPrincipal(ctx, handle, credentials)
+func initSecurity(ctx *context.T, handle *exec.ChildHandle, credentials string, client ipc.Client) (security.Principal, error) {
+	principal, err := setupPrincipal(ctx, handle, credentials, client)
 	if err != nil {
 		return nil, err
 	}
@@ -30,7 +31,7 @@
 	return principal, nil
 }
 
-func setupPrincipal(ctx *context.T, handle *exec.ChildHandle, credentials string) (security.Principal, error) {
+func setupPrincipal(ctx *context.T, handle *exec.ChildHandle, credentials string, client ipc.Client) (security.Principal, error) {
 	var err error
 	var principal security.Principal
 	if principal, _ = ctx.Value(principalKey).(security.Principal); principal != nil {
@@ -39,7 +40,7 @@
 	if fd, err := agentFD(handle); err != nil {
 		return nil, err
 	} else if fd >= 0 {
-		return agent.NewAgentPrincipal(ctx, fd)
+		return agent.NewAgentPrincipal(ctx, fd, client)
 	}
 	if len(credentials) > 0 {
 		// TODO(ataly, ashankar): If multiple runtimes are getting
diff --git a/runtimes/google/testing/mocks/ipc/simple_client.go b/runtimes/google/testing/mocks/ipc/simple_client.go
index 23a6b89..d90ccd7 100644
--- a/runtimes/google/testing/mocks/ipc/simple_client.go
+++ b/runtimes/google/testing/mocks/ipc/simple_client.go
@@ -3,13 +3,14 @@
 import (
 	"errors"
 	"fmt"
-	"reflect"
 	"sync"
 
 	"v.io/core/veyron2/context"
 	"v.io/core/veyron2/ipc"
 	"v.io/core/veyron2/security"
+	"v.io/core/veyron2/vdl/valconv"
 	"v.io/core/veyron2/vlog"
+	"v.io/core/veyron2/vom2"
 )
 
 // NewSimpleClient creates a new mocked ipc client where the given map of method name
@@ -51,8 +52,21 @@
 		return nil, errors.New(fmt.Sprintf("method %s not found", method))
 	}
 
+	// Copy the results so that they can be modified without effecting the original.
+	// This must be done via vom encode and decode rather than a direct deep copy because (among other reasons)
+	// reflect-based deep copy on vdl.Type objects will fail because of their private fields. This is not a problem with vom
+	// as it manually creates the type objects. It is also more realistic to use the same mechanism as the ultimate calls.
+	vomBytes, err := vom2.Encode(results)
+	if err != nil {
+		panic(fmt.Sprintf("Error copying value with vom (failed on encode): %v", err))
+	}
+	var copiedResults []interface{}
+	if err := vom2.Decode(vomBytes, &copiedResults); err != nil {
+		panic(fmt.Sprintf("Error copying value with vom (failed on decode): %v", err))
+	}
+
 	clientCall := mockCall{
-		results: results,
+		results: copiedResults,
 	}
 
 	c.Lock()
@@ -92,10 +106,11 @@
 	}
 	for ax, res := range resultptrs {
 		if mc.results[ax] != nil {
-			reflect.ValueOf(res).Elem().Set(reflect.ValueOf(mc.results[ax]))
+			if err := valconv.Convert(res, mc.results[ax]); err != nil {
+				panic(fmt.Sprintf("Error converting out argument %#v: %v", mc.results[ax], err))
+			}
 		}
 	}
-
 	return nil
 }
 
diff --git a/runtimes/google/testing/mocks/ipc/simple_client_test.go b/runtimes/google/testing/mocks/ipc/simple_client_test.go
index 0cf23e6..a4bd4f0 100644
--- a/runtimes/google/testing/mocks/ipc/simple_client_test.go
+++ b/runtimes/google/testing/mocks/ipc/simple_client_test.go
@@ -35,7 +35,7 @@
 		return
 	}
 	var resultOne string
-	var resultTwo int
+	var resultTwo int64
 	method1Call.Finish(&resultOne, &resultTwo)
 	if resultOne != "one" {
 		t.Errorf(`FinishCall: first result was "%v", want "one"`, resultOne)
@@ -73,21 +73,21 @@
 }
 
 type sampleStruct struct {
-	name string
+	Name string
 }
 
 func TestStructResult(t *testing.T) {
 	client := NewSimpleClient(map[string][]interface{}{
 		"foo": []interface{}{
-			sampleStruct{name: "bar"},
+			sampleStruct{Name: "bar"},
 		},
 	})
 	ctx := testContext()
 	call, _ := client.StartCall(ctx, "name/obj", "foo", []interface{}{})
 	var result sampleStruct
 	call.Finish(&result)
-	if result.name != "bar" {
-		t.Errorf(`FinishCall: second result was "%v", want "bar"`, result.name)
+	if result.Name != "bar" {
+		t.Errorf(`FinishCall: second result was "%v", want "bar"`, result.Name)
 		return
 	}
 }
diff --git a/runtimes/google/testing/mocks/naming/namespace.go b/runtimes/google/testing/mocks/naming/namespace.go
index c46eca8..ad9a139 100644
--- a/runtimes/google/testing/mocks/naming/namespace.go
+++ b/runtimes/google/testing/mocks/naming/namespace.go
@@ -65,29 +65,9 @@
 	return nil
 }
 
-func (ns *namespace) Resolve(ctx *context.T, name string, opts ...naming.ResolveOpt) ([]string, error) {
+func (ns *namespace) Resolve(ctx *context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
 	defer vlog.LogCall()()
-	if address, _ := naming.SplitAddressName(name); len(address) > 0 {
-		return []string{name}, nil
-	}
-	ns.Lock()
-	defer ns.Unlock()
-	for prefix, servers := range ns.mounts {
-		if strings.HasPrefix(name, prefix) {
-			suffix := strings.TrimLeft(strings.TrimPrefix(name, prefix), "/")
-			var ret []string
-			for _, s := range servers {
-				ret = append(ret, naming.JoinAddressName(s, suffix))
-			}
-			return ret, nil
-		}
-	}
-	return nil, verror.Make(naming.ErrNoSuchName, ctx, fmt.Sprintf("Resolve name %q not found in %v", name, ns.mounts))
-}
-
-func (ns *namespace) ResolveX(ctx *context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
-	defer vlog.LogCall()()
-	e, err := ns.ns.ResolveX(ctx, name, options.NoResolve{})
+	e, err := ns.ns.Resolve(ctx, name, options.NoResolve{})
 	if err != nil {
 		return e, err
 	}
@@ -111,14 +91,7 @@
 	return nil, verror.Make(naming.ErrNoSuchName, ctx, fmt.Sprintf("Resolve name %q not found in %v", name, ns.mounts))
 }
 
-func (ns *namespace) ResolveToMountTableX(ctx *context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
-	defer vlog.LogCall()()
-	// TODO(mattr): Implement this method for tests that might need it.
-	panic("ResolveToMountTable not implemented")
-	return nil, nil
-}
-
-func (ns *namespace) ResolveToMountTable(ctx *context.T, name string, opts ...naming.ResolveOpt) ([]string, error) {
+func (ns *namespace) ResolveToMountTable(ctx *context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
 	defer vlog.LogCall()()
 	// TODO(mattr): Implement this method for tests that might need it.
 	panic("ResolveToMountTable not implemented")
diff --git a/security/agent/agent_test.go b/security/agent/agent_test.go
index 7236034..bfc7ddd 100644
--- a/security/agent/agent_test.go
+++ b/security/agent/agent_test.go
@@ -11,6 +11,7 @@
 	"v.io/core/veyron/security/agent"
 	"v.io/core/veyron/security/agent/server"
 
+	"v.io/core/veyron2"
 	"v.io/core/veyron2/context"
 	"v.io/core/veyron2/rt"
 	"v.io/core/veyron2/security"
@@ -25,7 +26,7 @@
 	defer sock.Close()
 
 	var agentP security.Principal
-	if agentP, err = agent.NewAgentPrincipal(ctx, int(sock.Fd())); err != nil {
+	if agentP, err = agent.NewAgentPrincipal(ctx, int(sock.Fd()), veyron2.GetClient(ctx)); err != nil {
 		t.Fatal(err)
 	}
 	return agentP
diff --git a/security/agent/client.go b/security/agent/client.go
index e5604d2..0c2912a 100644
--- a/security/agent/client.go
+++ b/security/agent/client.go
@@ -8,7 +8,6 @@
 	"os"
 
 	"v.io/core/veyron/lib/unixfd"
-	"v.io/core/veyron2"
 	"v.io/core/veyron2/context"
 	"v.io/core/veyron2/ipc"
 	"v.io/core/veyron2/naming"
@@ -40,7 +39,7 @@
 
 	ctx, _ := vtrace.SetNewTrace(c.ctx)
 	// VCSecurityNone is safe here since we're using anonymous unix sockets.
-	if call, err = c.client.StartCall(ctx, c.name, name, args, options.VCSecurityNone); err == nil {
+	if call, err = c.client.StartCall(ctx, c.name, name, args, options.VCSecurityNone, options.NoResolve{}); err == nil {
 		if ierr := call.Finish(results...); ierr != nil {
 			err = ierr
 		}
@@ -59,7 +58,7 @@
 // 'fd' is the socket for connecting to the agent, typically obtained from
 // os.GetEnv(agent.FdVarName).
 // 'ctx' should not have a deadline, and should never be cancelled.
-func NewAgentPrincipal(ctx *context.T, fd int) (security.Principal, error) {
+func NewAgentPrincipal(ctx *context.T, fd int, insecureClient ipc.Client) (security.Principal, error) {
 	f := os.NewFile(uintptr(fd), "agent_client")
 	defer f.Close()
 	conn, err := net.FileConn(f)
@@ -73,7 +72,7 @@
 		return nil, err
 	}
 	caller := caller{
-		client: veyron2.GetClient(ctx),
+		client: insecureClient,
 		name:   naming.JoinAddressName(naming.FormatEndpoint(addr.Network(), addr.String()), ""),
 		ctx:    ctx,
 	}
diff --git a/security/agent/keymgr/keymgr_test.go b/security/agent/keymgr/keymgr_test.go
index f9d18b7..422767a 100644
--- a/security/agent/keymgr/keymgr_test.go
+++ b/security/agent/keymgr/keymgr_test.go
@@ -12,6 +12,7 @@
 	"v.io/core/veyron/security/agent"
 	"v.io/core/veyron/security/agent/server"
 
+	"v.io/core/veyron2"
 	"v.io/core/veyron2/context"
 	"v.io/core/veyron2/rt"
 	"v.io/core/veyron2/security"
@@ -70,7 +71,7 @@
 		return nil, err
 	}
 
-	return agent.NewAgentPrincipal(ctx, fd)
+	return agent.NewAgentPrincipal(ctx, fd, veyron2.GetClient(ctx))
 }
 
 func TestSigning(t *testing.T) {
diff --git a/security/agent/pingpong/wire.vdl.go b/security/agent/pingpong/wire.vdl.go
index 4344728..2f1915b 100644
--- a/security/agent/pingpong/wire.vdl.go
+++ b/security/agent/pingpong/wire.vdl.go
@@ -8,15 +8,8 @@
 	__veyron2 "v.io/core/veyron2"
 	__context "v.io/core/veyron2/context"
 	__ipc "v.io/core/veyron2/ipc"
-	__vdlutil "v.io/core/veyron2/vdl/vdlutil"
-	__wiretype "v.io/core/veyron2/wiretype"
 )
 
-// TODO(toddw): Remove this line once the new signature support is done.
-// It corrects a bug where __wiretype is unused in VDL pacakges where only
-// bootstrap types are used on interfaces.
-const _ = __wiretype.TypeIDInvalid
-
 // PingPongClientMethods is the client interface
 // containing PingPong methods.
 //
@@ -65,17 +58,6 @@
 	return
 }
 
-func (c implPingPongClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&o0, &err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
 // PingPongServerMethods is the interface a server writer
 // implements for PingPong.
 //
@@ -95,8 +77,6 @@
 	PingPongServerStubMethods
 	// Describe the PingPong interfaces.
 	Describe__() []__ipc.InterfaceDesc
-	// Signature will be replaced with Describe__.
-	Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
 }
 
 // PingPongServer returns a server stub for PingPong.
@@ -154,22 +134,3 @@
 		},
 	},
 }
-
-func (s implPingPongServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
-	// TODO(toddw): Replace with new Describe__ implementation.
-	result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
-	result.Methods["Ping"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "message", Type: 3},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 3},
-			{Name: "", Type: 65},
-		},
-	}
-
-	result.TypeDefs = []__vdlutil.Any{
-		__wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
-
-	return result, nil
-}
diff --git a/security/agent/server/wire.vdl.go b/security/agent/server/wire.vdl.go
index 1fa94ac..ddd4eab 100644
--- a/security/agent/server/wire.vdl.go
+++ b/security/agent/server/wire.vdl.go
@@ -11,14 +11,8 @@
 	__context "v.io/core/veyron2/context"
 	__ipc "v.io/core/veyron2/ipc"
 	__vdlutil "v.io/core/veyron2/vdl/vdlutil"
-	__wiretype "v.io/core/veyron2/wiretype"
 )
 
-// TODO(toddw): Remove this line once the new signature support is done.
-// It corrects a bug where __wiretype is unused in VDL pacakges where only
-// bootstrap types are used on interfaces.
-const _ = __wiretype.TypeIDInvalid
-
 // AgentClientMethods is the client interface
 // containing Agent methods.
 type AgentClientMethods interface {
@@ -257,17 +251,6 @@
 	return
 }
 
-func (c implAgentClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&o0, &err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
 // AgentServerMethods is the interface a server writer
 // implements for Agent.
 type AgentServerMethods interface {
@@ -301,8 +284,6 @@
 	AgentServerStubMethods
 	// Describe the Agent interfaces.
 	Describe__() []__ipc.InterfaceDesc
-	// Signature will be replaced with Describe__.
-	Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
 }
 
 // AgentServer returns a server stub for Agent.
@@ -574,188 +555,3 @@
 		},
 	},
 }
-
-func (s implAgentServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
-	// TODO(toddw): Replace with new Describe__ implementation.
-	result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
-	result.Methods["AddToRoots"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "blessing", Type: 74},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 75},
-		},
-	}
-	result.Methods["Bless"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "key", Type: 66},
-			{Name: "wit", Type: 74},
-			{Name: "extension", Type: 3},
-			{Name: "caveat", Type: 67},
-			{Name: "additionalCaveats", Type: 68},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 74},
-			{Name: "", Type: 75},
-		},
-	}
-	result.Methods["BlessSelf"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "name", Type: 3},
-			{Name: "caveats", Type: 68},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 74},
-			{Name: "", Type: 75},
-		},
-	}
-	result.Methods["BlessingRootsAdd"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "root", Type: 66},
-			{Name: "pattern", Type: 77},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 75},
-		},
-	}
-	result.Methods["BlessingRootsDebugString"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 3},
-			{Name: "", Type: 75},
-		},
-	}
-	result.Methods["BlessingRootsRecognized"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "root", Type: 66},
-			{Name: "blessing", Type: 3},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 75},
-		},
-	}
-	result.Methods["BlessingStoreDebugString"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 3},
-			{Name: "", Type: 75},
-		},
-	}
-	result.Methods["BlessingStoreDefault"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 74},
-			{Name: "", Type: 75},
-		},
-	}
-	result.Methods["BlessingStoreForPeer"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "peerBlessings", Type: 61},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 74},
-			{Name: "", Type: 75},
-		},
-	}
-	result.Methods["BlessingStorePeerBlessings"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 80},
-			{Name: "", Type: 75},
-		},
-	}
-	result.Methods["BlessingStoreSet"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "blessings", Type: 74},
-			{Name: "forPeers", Type: 77},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 74},
-			{Name: "", Type: 75},
-		},
-	}
-	result.Methods["BlessingStoreSetDefault"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "blessings", Type: 74},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 75},
-		},
-	}
-	result.Methods["BlessingsByName"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "name", Type: 77},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 78},
-			{Name: "", Type: 75},
-		},
-	}
-	result.Methods["BlessingsInfo"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "blessings", Type: 74},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 79},
-			{Name: "", Type: 75},
-		},
-	}
-	result.Methods["MintDischarge"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "tp", Type: 76},
-			{Name: "caveat", Type: 67},
-			{Name: "additionalCaveats", Type: 68},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 76},
-			{Name: "", Type: 75},
-		},
-	}
-	result.Methods["PublicKey"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 66},
-			{Name: "", Type: 75},
-		},
-	}
-	result.Methods["Sign"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "message", Type: 66},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 70},
-			{Name: "", Type: 75},
-		},
-	}
-
-	result.TypeDefs = []__vdlutil.Any{
-		__wiretype.NamedPrimitiveType{Type: 0x32, Name: "byte", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x41, Name: "", Tags: []string(nil)}, __wiretype.StructType{
-			[]__wiretype.FieldType{
-				__wiretype.FieldType{Type: 0x42, Name: "ValidatorVOM"},
-			},
-			"v.io/core/veyron2/security.Caveat", []string(nil)},
-		__wiretype.SliceType{Elem: 0x43, Name: "", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x3, Name: "v.io/core/veyron2/security.Hash", Tags: []string(nil)}, __wiretype.StructType{
-			[]__wiretype.FieldType{
-				__wiretype.FieldType{Type: 0x42, Name: "Purpose"},
-				__wiretype.FieldType{Type: 0x45, Name: "Hash"},
-				__wiretype.FieldType{Type: 0x42, Name: "R"},
-				__wiretype.FieldType{Type: 0x42, Name: "S"},
-			},
-			"v.io/core/veyron2/security.Signature", []string(nil)},
-		__wiretype.StructType{
-			[]__wiretype.FieldType{
-				__wiretype.FieldType{Type: 0x3, Name: "Extension"},
-				__wiretype.FieldType{Type: 0x42, Name: "PublicKey"},
-				__wiretype.FieldType{Type: 0x44, Name: "Caveats"},
-				__wiretype.FieldType{Type: 0x46, Name: "Signature"},
-			},
-			"v.io/core/veyron2/security.Certificate", []string(nil)},
-		__wiretype.SliceType{Elem: 0x47, Name: "", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x48, Name: "", Tags: []string(nil)}, __wiretype.StructType{
-			[]__wiretype.FieldType{
-				__wiretype.FieldType{Type: 0x49, Name: "CertificateChains"},
-			},
-			"v.io/core/veyron2/security.WireBlessings", []string(nil)},
-		__wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x1, Name: "anydata", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x3, Name: "v.io/core/veyron2/security.BlessingPattern", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x4a, Name: "", Tags: []string(nil)}, __wiretype.MapType{Key: 0x3, Elem: 0x44, Name: "", Tags: []string(nil)}, __wiretype.MapType{Key: 0x4d, Elem: 0x4a, Name: "", Tags: []string(nil)}}
-
-	return result, nil
-}
diff --git a/services/identity/identity.vdl.go b/services/identity/identity.vdl.go
index c369461..97d9997 100644
--- a/services/identity/identity.vdl.go
+++ b/services/identity/identity.vdl.go
@@ -11,15 +11,8 @@
 	__veyron2 "v.io/core/veyron2"
 	__context "v.io/core/veyron2/context"
 	__ipc "v.io/core/veyron2/ipc"
-	__vdlutil "v.io/core/veyron2/vdl/vdlutil"
-	__wiretype "v.io/core/veyron2/wiretype"
 )
 
-// TODO(toddw): Remove this line once the new signature support is done.
-// It corrects a bug where __wiretype is unused in VDL pacakges where only
-// bootstrap types are used on interfaces.
-const _ = __wiretype.TypeIDInvalid
-
 // OAuthBlesserClientMethods is the client interface
 // containing OAuthBlesser methods.
 //
@@ -82,17 +75,6 @@
 	return
 }
 
-func (c implOAuthBlesserClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&o0, &err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
 // OAuthBlesserServerMethods is the interface a server writer
 // implements for OAuthBlesser.
 //
@@ -126,8 +108,6 @@
 	OAuthBlesserServerStubMethods
 	// Describe the OAuthBlesser interfaces.
 	Describe__() []__ipc.InterfaceDesc
-	// Signature will be replaced with Describe__.
-	Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
 }
 
 // OAuthBlesserServer returns a server stub for OAuthBlesser.
@@ -188,52 +168,6 @@
 	},
 }
 
-func (s implOAuthBlesserServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
-	// TODO(toddw): Replace with new Describe__ implementation.
-	result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
-	result.Methods["BlessUsingAccessToken"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "token", Type: 3},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "blessing", Type: 74},
-			{Name: "email", Type: 3},
-			{Name: "err", Type: 75},
-		},
-	}
-
-	result.TypeDefs = []__vdlutil.Any{
-		__wiretype.NamedPrimitiveType{Type: 0x32, Name: "byte", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x41, Name: "", Tags: []string(nil)}, __wiretype.StructType{
-			[]__wiretype.FieldType{
-				__wiretype.FieldType{Type: 0x42, Name: "ValidatorVOM"},
-			},
-			"v.io/core/veyron2/security.Caveat", []string(nil)},
-		__wiretype.SliceType{Elem: 0x43, Name: "", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x3, Name: "v.io/core/veyron2/security.Hash", Tags: []string(nil)}, __wiretype.StructType{
-			[]__wiretype.FieldType{
-				__wiretype.FieldType{Type: 0x42, Name: "Purpose"},
-				__wiretype.FieldType{Type: 0x45, Name: "Hash"},
-				__wiretype.FieldType{Type: 0x42, Name: "R"},
-				__wiretype.FieldType{Type: 0x42, Name: "S"},
-			},
-			"v.io/core/veyron2/security.Signature", []string(nil)},
-		__wiretype.StructType{
-			[]__wiretype.FieldType{
-				__wiretype.FieldType{Type: 0x3, Name: "Extension"},
-				__wiretype.FieldType{Type: 0x42, Name: "PublicKey"},
-				__wiretype.FieldType{Type: 0x44, Name: "Caveats"},
-				__wiretype.FieldType{Type: 0x46, Name: "Signature"},
-			},
-			"v.io/core/veyron2/security.Certificate", []string(nil)},
-		__wiretype.SliceType{Elem: 0x47, Name: "", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x48, Name: "", Tags: []string(nil)}, __wiretype.StructType{
-			[]__wiretype.FieldType{
-				__wiretype.FieldType{Type: 0x49, Name: "CertificateChains"},
-			},
-			"v.io/core/veyron2/security.WireBlessings", []string(nil)},
-		__wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
-
-	return result, nil
-}
-
 // MacaroonBlesserClientMethods is the client interface
 // containing MacaroonBlesser methods.
 //
@@ -284,17 +218,6 @@
 	return
 }
 
-func (c implMacaroonBlesserClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&o0, &err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
 // MacaroonBlesserServerMethods is the interface a server writer
 // implements for MacaroonBlesser.
 //
@@ -316,8 +239,6 @@
 	MacaroonBlesserServerStubMethods
 	// Describe the MacaroonBlesser interfaces.
 	Describe__() []__ipc.InterfaceDesc
-	// Signature will be replaced with Describe__.
-	Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
 }
 
 // MacaroonBlesserServer returns a server stub for MacaroonBlesser.
@@ -376,48 +297,3 @@
 		},
 	},
 }
-
-func (s implMacaroonBlesserServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
-	// TODO(toddw): Replace with new Describe__ implementation.
-	result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
-	result.Methods["Bless"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "macaroon", Type: 3},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "blessing", Type: 74},
-			{Name: "err", Type: 75},
-		},
-	}
-
-	result.TypeDefs = []__vdlutil.Any{
-		__wiretype.NamedPrimitiveType{Type: 0x32, Name: "byte", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x41, Name: "", Tags: []string(nil)}, __wiretype.StructType{
-			[]__wiretype.FieldType{
-				__wiretype.FieldType{Type: 0x42, Name: "ValidatorVOM"},
-			},
-			"v.io/core/veyron2/security.Caveat", []string(nil)},
-		__wiretype.SliceType{Elem: 0x43, Name: "", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x3, Name: "v.io/core/veyron2/security.Hash", Tags: []string(nil)}, __wiretype.StructType{
-			[]__wiretype.FieldType{
-				__wiretype.FieldType{Type: 0x42, Name: "Purpose"},
-				__wiretype.FieldType{Type: 0x45, Name: "Hash"},
-				__wiretype.FieldType{Type: 0x42, Name: "R"},
-				__wiretype.FieldType{Type: 0x42, Name: "S"},
-			},
-			"v.io/core/veyron2/security.Signature", []string(nil)},
-		__wiretype.StructType{
-			[]__wiretype.FieldType{
-				__wiretype.FieldType{Type: 0x3, Name: "Extension"},
-				__wiretype.FieldType{Type: 0x42, Name: "PublicKey"},
-				__wiretype.FieldType{Type: 0x44, Name: "Caveats"},
-				__wiretype.FieldType{Type: 0x46, Name: "Signature"},
-			},
-			"v.io/core/veyron2/security.Certificate", []string(nil)},
-		__wiretype.SliceType{Elem: 0x47, Name: "", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x48, Name: "", Tags: []string(nil)}, __wiretype.StructType{
-			[]__wiretype.FieldType{
-				__wiretype.FieldType{Type: 0x49, Name: "CertificateChains"},
-			},
-			"v.io/core/veyron2/security.WireBlessings", []string(nil)},
-		__wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
-
-	return result, nil
-}
diff --git a/services/identity/server/identityd.go b/services/identity/server/identityd.go
index 5eb3938..c1b2c99 100644
--- a/services/identity/server/identityd.go
+++ b/services/identity/server/identityd.go
@@ -154,24 +154,28 @@
 	if err != nil {
 		return nil, nil, fmt.Errorf("failed to create new ipc.Server: %v", err)
 	}
-	eps, err := server.Listen(*listenSpec)
-	if err != nil {
-		return nil, nil, fmt.Errorf("server.Listen(%v) failed: %v", *listenSpec, err)
-	}
-	ep := eps[0]
 
-	dispatcher := newDispatcher(macaroonKey, oauthBlesserParams(s.oauthBlesserParams, s.revocationManager, ep))
 	principal := veyron2.GetPrincipal(ctx)
-	objectname := naming.Join("identity", fmt.Sprintf("%v", principal.BlessingStore().Default()))
-	if err := server.ServeDispatcher(objectname, dispatcher); err != nil {
+	objectAddr := naming.Join("identity", fmt.Sprintf("%v", principal.BlessingStore().Default()))
+	var rootedObjectAddr string
+	if eps, err := server.Listen(*listenSpec); err != nil {
+		defer server.Stop()
+		return nil, nil, fmt.Errorf("server.Listen(%v) failed: %v", *listenSpec, err)
+	} else if nsroots := veyron2.GetNamespace(ctx).Roots(); len(nsroots) >= 1 {
+		rootedObjectAddr = naming.Join(nsroots[0], objectAddr)
+	} else {
+		rootedObjectAddr = eps[0].Name()
+	}
+	dispatcher := newDispatcher(macaroonKey, oauthBlesserParams(s.oauthBlesserParams, rootedObjectAddr))
+	if err := server.ServeDispatcher(objectAddr, dispatcher); err != nil {
 		return nil, nil, fmt.Errorf("failed to start Veyron services: %v", err)
 	}
 	published, _ := server.Published()
 	if len(published) == 0 {
-		// No addresses published, publish the endpoint instead (which may not be usable everywhere, but oh-well).
-		published = append(published, ep.String())
+		// No addresses successfully published, return what we expect to be published at.
+		published = []string{rootedObjectAddr}
 	}
-	vlog.Infof("Blessing and discharger services enabled at %v", published)
+	vlog.Infof("Blessing and discharger services will be published at %v", rootedObjectAddr)
 	return server, published, nil
 }
 
@@ -199,8 +203,8 @@
 	return nil, nil, verror.Make(verror.NoExist, nil, suffix)
 }
 
-func oauthBlesserParams(inputParams blesser.OAuthBlesserParams, revocationManager revocation.RevocationManager, ep naming.Endpoint) blesser.OAuthBlesserParams {
-	inputParams.DischargerLocation = naming.JoinAddressName(ep.String(), dischargerService)
+func oauthBlesserParams(inputParams blesser.OAuthBlesserParams, servername string) blesser.OAuthBlesserParams {
+	inputParams.DischargerLocation = naming.Join(servername, dischargerService)
 	return inputParams
 }
 
diff --git a/services/mgmt/application/impl/acl_test.go b/services/mgmt/application/impl/acl_test.go
index c603e34..1f682a0 100644
--- a/services/mgmt/application/impl/acl_test.go
+++ b/services/mgmt/application/impl/acl_test.go
@@ -36,8 +36,6 @@
 var globalCtx *context.T
 var globalCancel context.CancelFunc
 
-// This is also a modules world.
-// Insert necessary code here to be a modules test.
 func init() {
 	// TODO(rjkroege): Remove when vom2 is ready.
 	vdlutil.Register(&naming.VDLMountedServer{})
diff --git a/services/mgmt/application/impl/service.go b/services/mgmt/application/impl/service.go
index b0c6cc4..8ad14cd 100644
--- a/services/mgmt/application/impl/service.go
+++ b/services/mgmt/application/impl/service.go
@@ -265,7 +265,7 @@
 	return acl, etag, nil
 }
 
-// setACL wites a TaggedACLMap into the Memstore at the provided path.
+// setACL writes a TaggedACLMap into the Memstore at the provided path.
 // where path is expected to have already been cleaned by naming.Join.
 func setACL(store *fs.Memstore, path string, acl access.TaggedACLMap, etag string) error {
 	_, oetag, err := getACL(store, path)
diff --git a/services/mgmt/binary/impl/fs_utils.go b/services/mgmt/binary/impl/fs_utils.go
index 1147d21..9468fb6 100644
--- a/services/mgmt/binary/impl/fs_utils.go
+++ b/services/mgmt/binary/impl/fs_utils.go
@@ -26,10 +26,10 @@
 func checksumExists(path string) error {
 	switch _, err := os.Stat(path); {
 	case os.IsNotExist(err):
-		return verror.Make(errInvalidPart, nil, path)
+		return verror.Make(ErrInvalidPart, nil, path)
 	case err != nil:
 		vlog.Errorf("Stat(%v) failed: %v", path, err)
-		return verror.Make(errOperationFailed, nil, path)
+		return verror.Make(ErrOperationFailed, nil, path)
 	}
 	checksumFile := filepath.Join(path, checksum)
 	_, err := os.Stat(checksumFile)
@@ -38,7 +38,7 @@
 		return verror.Make(verror.NoExist, nil, path)
 	case err != nil:
 		vlog.Errorf("Stat(%v) failed: %v", checksumFile, err)
-		return verror.Make(errOperationFailed, nil, path)
+		return verror.Make(ErrOperationFailed, nil, path)
 	default:
 		return nil
 	}
@@ -58,7 +58,7 @@
 	infos, err := ioutil.ReadDir(path)
 	if err != nil {
 		vlog.Errorf("ReadDir(%v) failed: %v", path, err)
-		return []string{}, verror.Make(errOperationFailed, nil, path)
+		return []string{}, verror.Make(ErrOperationFailed, nil, path)
 	}
 	nDirs := 0
 	for _, info := range infos {
@@ -73,10 +73,10 @@
 			idx, err := strconv.Atoi(partName)
 			if err != nil {
 				vlog.Errorf("Atoi(%v) failed: %v", partName, err)
-				return []string{}, verror.Make(errOperationFailed, nil, path)
+				return []string{}, verror.Make(ErrOperationFailed, nil, path)
 			}
 			if idx < 0 || idx >= len(infos) || result[idx] != "" {
-				return []string{}, verror.Make(errOperationFailed, nil, path)
+				return []string{}, verror.Make(ErrOperationFailed, nil, path)
 			}
 			result[idx] = filepath.Join(path, partName)
 		} else {
@@ -84,7 +84,7 @@
 				continue
 			}
 			// The only entries should correspond to the part dirs.
-			return []string{}, verror.Make(errOperationFailed, nil, path)
+			return []string{}, verror.Make(ErrOperationFailed, nil, path)
 		}
 	}
 	return result, nil
diff --git a/services/mgmt/binary/impl/http.go b/services/mgmt/binary/impl/http.go
index 23363c1..1b34812 100644
--- a/services/mgmt/binary/impl/http.go
+++ b/services/mgmt/binary/impl/http.go
@@ -43,7 +43,7 @@
 		var err error
 		if partFiles[i], err = os.Open(dataPath); err != nil {
 			vlog.Errorf("Open(%v) failed: %v", dataPath, err)
-			return nil, verror.Make(errOperationFailed, nil, dataPath)
+			return nil, verror.Make(ErrOperationFailed, nil, dataPath)
 		}
 	}
 	return multipart.NewFile(name, partFiles)
diff --git a/services/mgmt/binary/impl/http_test.go b/services/mgmt/binary/impl/http_test.go
index 601ddd3..db4b0a5 100644
--- a/services/mgmt/binary/impl/http_test.go
+++ b/services/mgmt/binary/impl/http_test.go
@@ -1,4 +1,4 @@
-package impl
+package impl_test
 
 import (
 	"bytes"
@@ -11,6 +11,7 @@
 	"v.io/core/veyron2/services/mgmt/repository"
 
 	"v.io/core/veyron/lib/testutil"
+	"v.io/core/veyron/services/mgmt/binary/impl"
 )
 
 // TestHTTP checks that HTTP download works.
@@ -24,7 +25,7 @@
 		data := make([][]byte, length)
 		for i := 0; i < length; i++ {
 			// Random size, but at least 1 (avoid empty parts).
-			size := testutil.Rand.Intn(1000*bufferLength) + 1
+			size := testutil.Rand.Intn(1000*impl.BufferLength) + 1
 			data[i] = testutil.RandomBytes(size)
 		}
 		mediaInfo := repository.MediaInfo{Type: "application/octet-stream"}
@@ -32,7 +33,7 @@
 			t.Fatalf("Create() failed: %v", err)
 		}
 		for i := 0; i < length; i++ {
-			if streamErr, err := invokeUpload(t, binary, data[i], int32(i)); streamErr != nil || err != nil {
+			if streamErr, err := invokeUpload(t, gctx, binary, data[i], int32(i)); streamErr != nil || err != nil {
 				t.FailNow()
 			}
 		}
diff --git a/services/mgmt/binary/impl/impl_test.go b/services/mgmt/binary/impl/impl_test.go
index 5b52ad3..09fb3a4 100644
--- a/services/mgmt/binary/impl/impl_test.go
+++ b/services/mgmt/binary/impl/impl_test.go
@@ -1,19 +1,15 @@
-package impl
+package impl_test
 
 import (
 	"bytes"
 	"crypto/md5"
 	"encoding/hex"
 	"fmt"
-	"io/ioutil"
 	"net"
 	"net/http"
-	"os"
-	"path/filepath"
 	"reflect"
 	"testing"
 
-	"v.io/core/veyron2"
 	"v.io/core/veyron2/context"
 	"v.io/core/veyron2/naming"
 	"v.io/core/veyron2/rt"
@@ -22,7 +18,9 @@
 	"v.io/core/veyron2/vlog"
 
 	"v.io/core/veyron/lib/testutil"
-	"v.io/core/veyron/profiles"
+	_ "v.io/core/veyron/profiles/static"
+	"v.io/core/veyron/services/mgmt/binary/impl"
+	mgmttest "v.io/core/veyron/services/mgmt/lib/testutil"
 )
 
 const (
@@ -41,121 +39,41 @@
 	gctx = runtime.NewContext()
 }
 
-// invokeUpload invokes the Upload RPC using the given client binary
-// <binary> and streams the given binary <binary> to it.
-func invokeUpload(t *testing.T, binary repository.BinaryClientMethods, data []byte, part int32) (error, error) {
-	stream, err := binary.Upload(gctx, part)
-	if err != nil {
-		t.Errorf("Upload() failed: %v", err)
-		return nil, err
-	}
-	sender := stream.SendStream()
-	if streamErr := sender.Send(data); streamErr != nil {
-		err := stream.Finish()
-		if err != nil {
-			t.Logf("Finish() failed: %v", err)
-		}
-		t.Logf("Send() failed: %v", streamErr)
-		return streamErr, err
-	}
-	if streamErr := sender.Close(); streamErr != nil {
-		err := stream.Finish()
-		if err != nil {
-			t.Logf("Finish() failed: %v", err)
-		}
-		t.Logf("Close() failed: %v", streamErr)
-		return streamErr, err
-	}
-	if err := stream.Finish(); err != nil {
-		t.Logf("Finish() failed: %v", err)
-		return nil, err
-	}
-	return nil, nil
-}
-
-// invokeDownload invokes the Download RPC using the given client binary
-// <binary> and streams binary from to it.
-func invokeDownload(t *testing.T, binary repository.BinaryClientMethods, part int32) ([]byte, error, error) {
-	stream, err := binary.Download(gctx, part)
-	if err != nil {
-		t.Errorf("Download() failed: %v", err)
-		return nil, nil, err
-	}
-	output := make([]byte, 0)
-	rStream := stream.RecvStream()
-	for rStream.Advance() {
-		bytes := rStream.Value()
-		output = append(output, bytes...)
-	}
-
-	if streamErr := rStream.Err(); streamErr != nil {
-		err := stream.Finish()
-		if err != nil {
-			t.Logf("Finish() failed: %v", err)
-		}
-		t.Logf("Advance() failed with: %v", streamErr)
-		return nil, streamErr, err
-	}
-
-	if err := stream.Finish(); err != nil {
-		t.Logf("Finish() failed: %v", err)
-		return nil, nil, err
-	}
-	return output, nil, nil
-}
-
 // startServer starts the binary repository server.
 func startServer(t *testing.T, depth int) (repository.BinaryClientMethods, string, string, func()) {
 	// Setup the root of the binary repository.
-	rootDir, err := ioutil.TempDir("", veyronPrefix)
-	if err != nil {
-		t.Fatalf("TempDir() failed: %v", err)
-	}
-	path, perm := filepath.Join(rootDir, VersionFile), os.FileMode(0600)
-	if err := ioutil.WriteFile(path, []byte(Version), perm); err != nil {
-		vlog.Fatalf("WriteFile(%v, %v, %v) failed: %v", path, Version, perm, err)
-	}
+	rootDir, cleanup := mgmttest.SetupRootDir(t, "bindir")
+	prepDirectory(t, rootDir)
+
 	// Setup and start the binary repository server.
-	server, err := veyron2.NewServer(gctx)
-	if err != nil {
-		t.Fatalf("NewServer() failed: %v", err)
-	}
+	server, endpoint := mgmttest.NewServer(gctx)
+
 	listener, err := net.Listen("tcp", "127.0.0.1:0")
 	if err != nil {
 		t.Fatal(err)
 	}
-	state, err := NewState(rootDir, listener.Addr().String(), depth)
+	state, err := impl.NewState(rootDir, listener.Addr().String(), depth)
 	if err != nil {
 		t.Fatalf("NewState(%v, %v) failed: %v", rootDir, listener.Addr().String(), depth, err)
 	}
 	go func() {
-		if err := http.Serve(listener, http.FileServer(NewHTTPRoot(state))); err != nil {
+		if err := http.Serve(listener, http.FileServer(impl.NewHTTPRoot(state))); err != nil {
 			vlog.Fatalf("Serve() failed: %v", err)
 		}
 	}()
-	dispatcher := NewDispatcher(state, nil)
-	endpoints, err := server.Listen(profiles.LocalListenSpec)
-	if err != nil {
-		t.Fatalf("Listen(%s) failed: %v", profiles.LocalListenSpec, err)
-	}
-	endpoint := endpoints[0]
+	dispatcher := impl.NewDispatcher(state, nil)
 	dontPublishName := ""
 	if err := server.ServeDispatcher(dontPublishName, dispatcher); err != nil {
 		t.Fatalf("Serve(%q) failed: %v", dontPublishName, err)
 	}
-	name := naming.JoinAddressName(endpoint.String(), "test")
+	name := naming.JoinAddressName(endpoint, "test")
 	binary := repository.BinaryClient(name)
-	return binary, endpoint.String(), fmt.Sprintf("http://%s/test", listener.Addr()), func() {
+	return binary, endpoint, fmt.Sprintf("http://%s/test", listener.Addr()), func() {
 		// Shutdown the binary repository server.
 		if err := server.Stop(); err != nil {
 			t.Fatalf("Stop() failed: %v", err)
 		}
-		if err := os.RemoveAll(path); err != nil {
-			t.Fatalf("RemoveAll(%v) failed: %v", path, err)
-		}
-		if err := os.RemoveAll(rootDir); err != nil {
-			t.Fatalf("RemoveAll(%v) failed: %v", rootDir, err)
-		}
+		cleanup()
 	}
 }
 
@@ -166,14 +84,13 @@
 	for i := 0; i < md5.Size; i++ {
 		binary, ep, _, cleanup := startServer(t, i)
 		defer cleanup()
-		// Create up to 4MB of random bytes.
-		size := testutil.Rand.Intn(1000 * bufferLength)
-		data := testutil.RandomBytes(size)
+		data := testData()
+
 		// Test the binary repository interface.
 		if err := binary.Create(gctx, 1, repository.MediaInfo{Type: "application/octet-stream"}); err != nil {
 			t.Fatalf("Create() failed: %v", err)
 		}
-		if streamErr, err := invokeUpload(t, binary, data, 0); streamErr != nil || err != nil {
+		if streamErr, err := invokeUpload(t, gctx, binary, data, 0); streamErr != nil || err != nil {
 			t.FailNow()
 		}
 		parts, _, err := binary.Stat(gctx)
@@ -189,7 +106,7 @@
 		if expected, got := len(data), int(parts[0].Size); expected != got {
 			t.Fatalf("Unexpected size: expected %v, got %v", expected, got)
 		}
-		output, streamErr, err := invokeDownload(t, binary, 0)
+		output, streamErr, err := invokeDownload(t, gctx, binary, 0)
 		if streamErr != nil || err != nil {
 			t.FailNow()
 		}
@@ -219,15 +136,14 @@
 		// Create <length> chunks of up to 4MB of random bytes.
 		data := make([][]byte, length)
 		for i := 0; i < length; i++ {
-			size := testutil.Rand.Intn(1000 * bufferLength)
-			data[i] = testutil.RandomBytes(size)
+			data[i] = testData()
 		}
 		// Test the binary repository interface.
 		if err := binary.Create(gctx, int32(length), repository.MediaInfo{Type: "application/octet-stream"}); err != nil {
 			t.Fatalf("Create() failed: %v", err)
 		}
 		for i := 0; i < length; i++ {
-			if streamErr, err := invokeUpload(t, binary, data[i], int32(i)); streamErr != nil || err != nil {
+			if streamErr, err := invokeUpload(t, gctx, binary, data[i], int32(i)); streamErr != nil || err != nil {
 				t.FailNow()
 			}
 		}
@@ -237,7 +153,7 @@
 		}
 		for i := 0; i < length; i++ {
 			hpart := md5.New()
-			output, streamErr, err := invokeDownload(t, binary, int32(i))
+			output, streamErr, err := invokeDownload(t, gctx, binary, int32(i))
 			if streamErr != nil || err != nil {
 				t.FailNow()
 			}
@@ -269,8 +185,7 @@
 		// Create <length> chunks of up to 4MB of random bytes.
 		data := make([][]byte, length)
 		for i := 0; i < length; i++ {
-			size := testutil.Rand.Intn(1000 * bufferLength)
-			data[i] = testutil.RandomBytes(size)
+			data[i] = testData()
 		}
 		if err := binary.Create(gctx, int32(length), repository.MediaInfo{Type: "application/octet-stream"}); err != nil {
 			t.Fatalf("Create() failed: %v", err)
@@ -284,15 +199,15 @@
 			}
 			finished := true
 			for _, part := range parts {
-				finished = finished && (part != MissingPart)
+				finished = finished && (part != impl.MissingPart)
 			}
 			if finished {
 				break
 			}
 			for i := 0; i < length; i++ {
 				fail := testutil.Rand.Intn(2)
-				if parts[i] == MissingPart && fail != 0 {
-					if streamErr, err := invokeUpload(t, binary, data[i], int32(i)); streamErr != nil || err != nil {
+				if parts[i] == impl.MissingPart && fail != 0 {
+					if streamErr, err := invokeUpload(t, gctx, binary, data[i], int32(i)); streamErr != nil || err != nil {
 						t.FailNow()
 					}
 				}
@@ -311,9 +226,8 @@
 	const length = 2
 	data := make([][]byte, length)
 	for i := 0; i < length; i++ {
-		size := testutil.Rand.Intn(1000 * bufferLength)
-		data[i] = make([]byte, size)
-		for j := 0; j < size; j++ {
+		data[i] = testData()
+		for j := 0; j < len(data[i]); j++ {
 			data[i][j] = byte(testutil.Rand.Int())
 		}
 	}
@@ -325,36 +239,36 @@
 	} else if want := verror.Exist.ID; !verror.Is(err, want) {
 		t.Fatalf("Unexpected error: %v, expected error id %v", err, want)
 	}
-	if streamErr, err := invokeUpload(t, binary, data[0], 0); streamErr != nil || err != nil {
+	if streamErr, err := invokeUpload(t, gctx, binary, data[0], 0); streamErr != nil || err != nil {
 		t.Fatalf("Upload() failed: %v", err)
 	}
-	if _, err := invokeUpload(t, binary, data[0], 0); err == nil {
+	if _, err := invokeUpload(t, gctx, binary, data[0], 0); err == nil {
 		t.Fatalf("Upload() did not fail when it should have")
 	} else if want := verror.Exist.ID; !verror.Is(err, want) {
 		t.Fatalf("Unexpected error: %v, expected error id %v", err, want)
 	}
-	if _, _, err := invokeDownload(t, binary, 1); err == nil {
+	if _, _, err := invokeDownload(t, gctx, binary, 1); err == nil {
 		t.Fatalf("Download() did not fail when it should have")
 	} else if want := verror.NoExist.ID; !verror.Is(err, want) {
 		t.Fatalf("Unexpected error: %v, expected error id %v", err, want)
 	}
-	if streamErr, err := invokeUpload(t, binary, data[1], 1); streamErr != nil || err != nil {
+	if streamErr, err := invokeUpload(t, gctx, binary, data[1], 1); streamErr != nil || err != nil {
 		t.Fatalf("Upload() failed: %v", err)
 	}
-	if _, streamErr, err := invokeDownload(t, binary, 0); streamErr != nil || err != nil {
+	if _, streamErr, err := invokeDownload(t, gctx, binary, 0); streamErr != nil || err != nil {
 		t.Fatalf("Download() failed: %v", err)
 	}
 	// Upload/Download on a part number that's outside the range set forth in
 	// Create should fail.
 	for _, part := range []int32{-1, length} {
-		if _, err := invokeUpload(t, binary, []byte("dummy"), part); err == nil {
+		if _, err := invokeUpload(t, gctx, binary, []byte("dummy"), part); err == nil {
 			t.Fatalf("Upload() did not fail when it should have")
-		} else if want := errInvalidPart.ID; !verror.Is(err, want) {
+		} else if want := impl.ErrInvalidPart.ID; !verror.Is(err, want) {
 			t.Fatalf("Unexpected error: %v, expected error id %v", err, want)
 		}
-		if _, _, err := invokeDownload(t, binary, part); err == nil {
+		if _, _, err := invokeDownload(t, gctx, binary, part); err == nil {
 			t.Fatalf("Download() did not fail when it should have")
-		} else if want := errInvalidPart.ID; !verror.Is(err, want) {
+		} else if want := impl.ErrInvalidPart.ID; !verror.Is(err, want) {
 			t.Fatalf("Unexpected error: %v, expected error id %v", err, want)
 		}
 	}
@@ -371,9 +285,7 @@
 func TestGlob(t *testing.T) {
 	_, ep, _, cleanup := startServer(t, 2)
 	defer cleanup()
-	// Create up to 4MB of random bytes.
-	size := testutil.Rand.Intn(1000 * bufferLength)
-	data := testutil.RandomBytes(size)
+	data := testData()
 
 	objects := []string{"foo", "bar", "hello world", "a/b/c"}
 	for _, obj := range objects {
@@ -383,7 +295,7 @@
 		if err := binary.Create(gctx, 1, repository.MediaInfo{Type: "application/octet-stream"}); err != nil {
 			t.Fatalf("Create() failed: %v", err)
 		}
-		if streamErr, err := invokeUpload(t, binary, data, 0); streamErr != nil || err != nil {
+		if streamErr, err := invokeUpload(t, gctx, binary, data, 0); streamErr != nil || err != nil {
 			t.FailNow()
 		}
 	}
diff --git a/services/mgmt/binary/impl/service.go b/services/mgmt/binary/impl/service.go
index 5ec3fc5..0ce7bbe 100644
--- a/services/mgmt/binary/impl/service.go
+++ b/services/mgmt/binary/impl/service.go
@@ -53,10 +53,10 @@
 const pkgPath = "v.io/core/veyron/services/mgmt/binary/impl"
 
 var (
-	errInProgress      = verror.Register(pkgPath+".errInProgress", verror.NoRetry, "{1:}{2:} identical upload already in progress{:_}")
-	errInvalidParts    = verror.Register(pkgPath+".errInvalidParts", verror.NoRetry, "{1:}{2:} invalid number of binary parts{:_}")
-	errInvalidPart     = verror.Register(pkgPath+".errInvalidPart", verror.NoRetry, "{1:}{2:} invalid binary part number{:_}")
-	errOperationFailed = verror.Register(pkgPath+".errOperationFailed", verror.NoRetry, "{1:}{2:} operation failed{:_}")
+	ErrInProgress      = verror.Register(pkgPath+".errInProgress", verror.NoRetry, "{1:}{2:} identical upload already in progress{:_}")
+	ErrInvalidParts    = verror.Register(pkgPath+".errInvalidParts", verror.NoRetry, "{1:}{2:} invalid number of binary parts{:_}")
+	ErrInvalidPart     = verror.Register(pkgPath+".errInvalidPart", verror.NoRetry, "{1:}{2:} invalid binary part number{:_}")
+	ErrOperationFailed = verror.Register(pkgPath+".errOperationFailed", verror.NoRetry, "{1:}{2:} operation failed{:_}")
 )
 
 // TODO(jsimsa): When VDL supports composite literal constants, remove
@@ -75,38 +75,38 @@
 	}
 }
 
-const bufferLength = 4096
+const BufferLength = 4096
 
 func (i *binaryService) Create(context ipc.ServerContext, nparts int32, mediaInfo repository.MediaInfo) error {
 	vlog.Infof("%v.Create(%v, %v)", i.suffix, nparts, mediaInfo)
 	if nparts < 1 {
-		return verror.Make(errInvalidParts, context.Context())
+		return verror.Make(ErrInvalidParts, context.Context())
 	}
 	parent, perm := filepath.Dir(i.path), os.FileMode(0700)
 	if err := os.MkdirAll(parent, perm); err != nil {
 		vlog.Errorf("MkdirAll(%v, %v) failed: %v", parent, perm, err)
-		return verror.Make(errOperationFailed, context.Context())
+		return verror.Make(ErrOperationFailed, context.Context())
 	}
 	prefix := "creating-"
 	tmpDir, err := ioutil.TempDir(parent, prefix)
 	if err != nil {
 		vlog.Errorf("TempDir(%v, %v) failed: %v", parent, prefix, err)
-		return verror.Make(errOperationFailed, context.Context())
+		return verror.Make(ErrOperationFailed, context.Context())
 	}
 	nameFile := filepath.Join(tmpDir, "name")
 	if err := ioutil.WriteFile(nameFile, []byte(i.suffix), os.FileMode(0600)); err != nil {
 		vlog.Errorf("WriteFile(%q) failed: %v", nameFile)
-		return verror.Make(errOperationFailed, context.Context())
+		return verror.Make(ErrOperationFailed, context.Context())
 	}
 	infoFile := filepath.Join(tmpDir, "mediainfo")
 	jInfo, err := json.Marshal(mediaInfo)
 	if err != nil {
 		vlog.Errorf("json.Marshal(%v) failed: %v", mediaInfo, err)
-		return verror.Make(errOperationFailed, context.Context())
+		return verror.Make(ErrOperationFailed, context.Context())
 	}
 	if err := ioutil.WriteFile(infoFile, jInfo, os.FileMode(0600)); err != nil {
 		vlog.Errorf("WriteFile(%q) failed: %v", infoFile, err)
-		return verror.Make(errOperationFailed, context.Context())
+		return verror.Make(ErrOperationFailed, context.Context())
 	}
 	for j := 0; j < int(nparts); j++ {
 		partPath, partPerm := generatePartPath(tmpDir, j), os.FileMode(0700)
@@ -115,7 +115,7 @@
 			if err := os.RemoveAll(tmpDir); err != nil {
 				vlog.Errorf("RemoveAll(%v) failed: %v", tmpDir, err)
 			}
-			return verror.Make(errOperationFailed, context.Context())
+			return verror.Make(ErrOperationFailed, context.Context())
 		}
 	}
 	// Use os.Rename() to atomically create the binary directory
@@ -130,7 +130,7 @@
 			return verror.Make(verror.Exist, context.Context(), i.path)
 		}
 		vlog.Errorf("Rename(%v, %v) failed: %v", tmpDir, i.path, err)
-		return verror.Make(errOperationFailed, context.Context(), i.path)
+		return verror.Make(ErrOperationFailed, context.Context(), i.path)
 	}
 	return nil
 }
@@ -142,18 +142,18 @@
 			return verror.Make(verror.NoExist, context.Context(), i.path)
 		}
 		vlog.Errorf("Stat(%v) failed: %v", i.path, err)
-		return verror.Make(errOperationFailed, context.Context())
+		return verror.Make(ErrOperationFailed, context.Context())
 	}
 	// Use os.Rename() to atomically remove the binary directory
 	// structure.
 	path := filepath.Join(filepath.Dir(i.path), "removing-"+filepath.Base(i.path))
 	if err := os.Rename(i.path, path); err != nil {
 		vlog.Errorf("Rename(%v, %v) failed: %v", i.path, path, err)
-		return verror.Make(errOperationFailed, context.Context(), i.path)
+		return verror.Make(ErrOperationFailed, context.Context(), i.path)
 	}
 	if err := os.RemoveAll(path); err != nil {
 		vlog.Errorf("Remove(%v) failed: %v", path, err)
-		return verror.Make(errOperationFailed, context.Context())
+		return verror.Make(ErrOperationFailed, context.Context())
 	}
 	for {
 		// Remove the binary and all directories on the path back to the
@@ -167,7 +167,7 @@
 				break
 			}
 			vlog.Errorf("Remove(%v) failed: %v", path, err)
-			return verror.Make(errOperationFailed, context.Context())
+			return verror.Make(ErrOperationFailed, context.Context())
 		}
 	}
 	return nil
@@ -183,23 +183,23 @@
 	file, err := os.Open(dataPath)
 	if err != nil {
 		vlog.Errorf("Open(%v) failed: %v", dataPath, err)
-		return verror.Make(errOperationFailed, context.Context())
+		return verror.Make(ErrOperationFailed, context.Context())
 	}
 	defer file.Close()
-	buffer := make([]byte, bufferLength)
+	buffer := make([]byte, BufferLength)
 	sender := context.SendStream()
 	for {
 		n, err := file.Read(buffer)
 		if err != nil && err != io.EOF {
 			vlog.Errorf("Read() failed: %v", err)
-			return verror.Make(errOperationFailed, context.Context())
+			return verror.Make(ErrOperationFailed, context.Context())
 		}
 		if n == 0 {
 			break
 		}
 		if err := sender.Send(buffer[:n]); err != nil {
 			vlog.Errorf("Send() failed: %v", err)
-			return verror.Make(errOperationFailed, context.Context())
+			return verror.Make(ErrOperationFailed, context.Context())
 		}
 	}
 	return nil
@@ -228,7 +228,7 @@
 				continue
 			}
 			vlog.Errorf("ReadFile(%v) failed: %v", checksumFile, err)
-			return []binary.PartInfo{}, repository.MediaInfo{}, verror.Make(errOperationFailed, context.Context())
+			return []binary.PartInfo{}, repository.MediaInfo{}, verror.Make(ErrOperationFailed, context.Context())
 		}
 		dataFile := filepath.Join(part, data)
 		fi, err := os.Stat(dataFile)
@@ -238,7 +238,7 @@
 				continue
 			}
 			vlog.Errorf("Stat(%v) failed: %v", dataFile, err)
-			return []binary.PartInfo{}, repository.MediaInfo{}, verror.Make(errOperationFailed, context.Context())
+			return []binary.PartInfo{}, repository.MediaInfo{}, verror.Make(ErrOperationFailed, context.Context())
 		}
 		result = append(result, binary.PartInfo{Checksum: string(bytes), Size: fi.Size()})
 	}
@@ -246,12 +246,12 @@
 	jInfo, err := ioutil.ReadFile(infoFile)
 	if err != nil {
 		vlog.Errorf("ReadFile(%q) failed: %v", infoFile)
-		return []binary.PartInfo{}, repository.MediaInfo{}, verror.Make(errOperationFailed, context.Context())
+		return []binary.PartInfo{}, repository.MediaInfo{}, verror.Make(ErrOperationFailed, context.Context())
 	}
 	var mediaInfo repository.MediaInfo
 	if err := json.Unmarshal(jInfo, &mediaInfo); err != nil {
 		vlog.Errorf("json.Unmarshal(%v) failed: %v", jInfo, err)
-		return []binary.PartInfo{}, repository.MediaInfo{}, verror.Make(errOperationFailed, context.Context())
+		return []binary.PartInfo{}, repository.MediaInfo{}, verror.Make(ErrOperationFailed, context.Context())
 	}
 	return result, mediaInfo, nil
 }
@@ -270,17 +270,17 @@
 	lockFile, err := os.OpenFile(lockPath, flags, perm)
 	if err != nil {
 		if os.IsExist(err) {
-			return verror.Make(errInProgress, context.Context(), path)
+			return verror.Make(ErrInProgress, context.Context(), path)
 		}
 		vlog.Errorf("OpenFile(%v, %v, %v) failed: %v", lockPath, flags, suffix, err)
-		return verror.Make(errOperationFailed, context.Context())
+		return verror.Make(ErrOperationFailed, context.Context())
 	}
 	defer os.Remove(lockFile.Name())
 	defer lockFile.Close()
 	file, err := ioutil.TempFile(path, suffix)
 	if err != nil {
 		vlog.Errorf("TempFile(%v, %v) failed: %v", path, suffix, err)
-		return verror.Make(errOperationFailed, context.Context())
+		return verror.Make(ErrOperationFailed, context.Context())
 	}
 	defer file.Close()
 	h := md5.New()
@@ -292,7 +292,7 @@
 			if err := os.Remove(file.Name()); err != nil {
 				vlog.Errorf("Remove(%v) failed: %v", file.Name(), err)
 			}
-			return verror.Make(errOperationFailed, context.Context())
+			return verror.Make(ErrOperationFailed, context.Context())
 		}
 		h.Write(bytes)
 	}
@@ -302,7 +302,7 @@
 		if err := os.Remove(file.Name()); err != nil {
 			vlog.Errorf("Remove(%v) failed: %v", file.Name(), err)
 		}
-		return verror.Make(errOperationFailed, context.Context())
+		return verror.Make(ErrOperationFailed, context.Context())
 	}
 
 	hash := hex.EncodeToString(h.Sum(nil))
@@ -312,7 +312,7 @@
 		if err := os.Remove(file.Name()); err != nil {
 			vlog.Errorf("Remove(%v) failed: %v", file.Name(), err)
 		}
-		return verror.Make(errOperationFailed, context.Context())
+		return verror.Make(ErrOperationFailed, context.Context())
 	}
 	dataFile := filepath.Join(path, data)
 	if err := os.Rename(file.Name(), dataFile); err != nil {
@@ -320,7 +320,7 @@
 		if err := os.Remove(file.Name()); err != nil {
 			vlog.Errorf("Remove(%v) failed: %v", file.Name(), err)
 		}
-		return verror.Make(errOperationFailed, context.Context())
+		return verror.Make(ErrOperationFailed, context.Context())
 	}
 	return nil
 }
@@ -332,7 +332,7 @@
 	}
 	n := i.createObjectNameTree().find(elems, false)
 	if n == nil {
-		return nil, verror.Make(errOperationFailed, context.Context())
+		return nil, verror.Make(ErrOperationFailed, context.Context())
 	}
 	ch := make(chan string)
 	go func() {
diff --git a/services/mgmt/binary/impl/util_test.go b/services/mgmt/binary/impl/util_test.go
new file mode 100644
index 0000000..d747dd7
--- /dev/null
+++ b/services/mgmt/binary/impl/util_test.go
@@ -0,0 +1,91 @@
+package impl_test
+
+import (
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"testing"
+
+	"v.io/core/veyron2/context"
+	"v.io/core/veyron2/services/mgmt/repository"
+
+	"v.io/core/veyron/lib/testutil"
+	"v.io/core/veyron/services/mgmt/binary/impl"
+)
+
+// invokeUpload invokes the Upload RPC using the given client binary
+// <binary> and streams the given binary <binary> to it.
+func invokeUpload(t *testing.T, ctx *context.T, binary repository.BinaryClientMethods, data []byte, part int32) (error, error) {
+	stream, err := binary.Upload(ctx, part)
+	if err != nil {
+		t.Errorf("Upload() failed: %v", err)
+		return nil, err
+	}
+	sender := stream.SendStream()
+	if streamErr := sender.Send(data); streamErr != nil {
+		err := stream.Finish()
+		if err != nil {
+			t.Logf("Finish() failed: %v", err)
+		}
+		t.Logf("Send() failed: %v", streamErr)
+		return streamErr, err
+	}
+	if streamErr := sender.Close(); streamErr != nil {
+		err := stream.Finish()
+		if err != nil {
+			t.Logf("Finish() failed: %v", err)
+		}
+		t.Logf("Close() failed: %v", streamErr)
+		return streamErr, err
+	}
+	if err := stream.Finish(); err != nil {
+		t.Logf("Finish() failed: %v", err)
+		return nil, err
+	}
+	return nil, nil
+}
+
+// invokeDownload invokes the Download RPC using the given client binary
+// <binary> and streams binary from to it.
+func invokeDownload(t *testing.T, ctx *context.T, binary repository.BinaryClientMethods, part int32) ([]byte, error, error) {
+	stream, err := binary.Download(ctx, part)
+	if err != nil {
+		t.Errorf("Download() failed: %v", err)
+		return nil, nil, err
+	}
+	output := make([]byte, 0)
+	rStream := stream.RecvStream()
+	for rStream.Advance() {
+		bytes := rStream.Value()
+		output = append(output, bytes...)
+	}
+
+	if streamErr := rStream.Err(); streamErr != nil {
+		err := stream.Finish()
+		if err != nil {
+			t.Logf("Finish() failed: %v", err)
+		}
+		t.Logf("Advance() failed with: %v", streamErr)
+		return nil, streamErr, err
+	}
+
+	if err := stream.Finish(); err != nil {
+		t.Logf("Finish() failed: %v", err)
+		return nil, nil, err
+	}
+	return output, nil, nil
+}
+
+func prepDirectory(t *testing.T, rootDir string) {
+	path, perm := filepath.Join(rootDir, impl.VersionFile), os.FileMode(0600)
+	if err := ioutil.WriteFile(path, []byte(impl.Version), perm); err != nil {
+		t.Fatalf(testutil.FormatLogLine(2, "WriteFile(%v, %v, %v) failed: %v", path, impl.Version, perm, err))
+	}
+}
+
+// testData creates up to 4MB of random bytes.
+func testData() []byte {
+	size := testutil.Rand.Intn(1000 * impl.BufferLength)
+	data := testutil.RandomBytes(size)
+	return data
+}
diff --git a/services/mgmt/device/config.vdl.go b/services/mgmt/device/config.vdl.go
index 4e35ccc..1a14ccb 100644
--- a/services/mgmt/device/config.vdl.go
+++ b/services/mgmt/device/config.vdl.go
@@ -8,15 +8,8 @@
 	__veyron2 "v.io/core/veyron2"
 	__context "v.io/core/veyron2/context"
 	__ipc "v.io/core/veyron2/ipc"
-	__vdlutil "v.io/core/veyron2/vdl/vdlutil"
-	__wiretype "v.io/core/veyron2/wiretype"
 )
 
-// TODO(toddw): Remove this line once the new signature support is done.
-// It corrects a bug where __wiretype is unused in VDL pacakges where only
-// bootstrap types are used on interfaces.
-const _ = __wiretype.TypeIDInvalid
-
 // ConfigClientMethods is the client interface
 // containing Config methods.
 //
@@ -66,17 +59,6 @@
 	return
 }
 
-func (c implConfigClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&o0, &err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
 // ConfigServerMethods is the interface a server writer
 // implements for Config.
 //
@@ -97,8 +79,6 @@
 	ConfigServerStubMethods
 	// Describe the Config interfaces.
 	Describe__() []__ipc.InterfaceDesc
-	// Signature will be replaced with Describe__.
-	Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
 }
 
 // ConfigServer returns a server stub for Config.
@@ -157,22 +137,3 @@
 		},
 	},
 }
-
-func (s implConfigServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
-	// TODO(toddw): Replace with new Describe__ implementation.
-	result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
-	result.Methods["Set"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "key", Type: 3},
-			{Name: "value", Type: 3},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 65},
-		},
-	}
-
-	result.TypeDefs = []__vdlutil.Any{
-		__wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
-
-	return result, nil
-}
diff --git a/services/mgmt/device/deviced/commands.go b/services/mgmt/device/deviced/commands.go
index edf5e95..1689b77 100644
--- a/services/mgmt/device/deviced/commands.go
+++ b/services/mgmt/device/deviced/commands.go
@@ -15,8 +15,10 @@
 	installFrom string
 	suidHelper  string
 	agent       string
+	initHelper  string
 	singleUser  bool
 	sessionMode bool
+	initMode    bool
 )
 
 const deviceDirEnv = "VANADIUM_DEVICE_DIR"
@@ -47,8 +49,10 @@
 	cmdInstall.Flags.StringVar(&installFrom, "from", "", "if specified, performs the installation from the provided application envelope object name")
 	cmdInstall.Flags.StringVar(&suidHelper, "suid_helper", "", "path to suid helper")
 	cmdInstall.Flags.StringVar(&agent, "agent", "", "path to security agent")
+	cmdInstall.Flags.StringVar(&initHelper, "init_helper", "", "path to sysinit helper")
 	cmdInstall.Flags.BoolVar(&singleUser, "single_user", false, "if set, performs the installation assuming a single-user system")
 	cmdInstall.Flags.BoolVar(&sessionMode, "session_mode", false, "if set, installs the device manager to run a single session. Otherwise, the device manager is configured to get restarted upon exit")
+	cmdInstall.Flags.BoolVar(&initMode, "init_mode", false, "if set, installs the device manager with the system init service manager")
 }
 
 func runInstall(cmd *cmdline.Command, args []string) error {
@@ -66,7 +70,10 @@
 	if agent == "" {
 		return cmd.UsageErrorf("--agent must be set")
 	}
-	if err := impl.SelfInstall(installationDir(), suidHelper, agent, singleUser, sessionMode, args, os.Environ()); err != nil {
+	if initMode && initHelper == "" {
+		return cmd.UsageErrorf("--init_helper must be set")
+	}
+	if err := impl.SelfInstall(installationDir(), suidHelper, agent, initHelper, singleUser, sessionMode, initMode, args, os.Environ(), cmd.Stderr(), cmd.Stdout()); err != nil {
 		vlog.Errorf("SelfInstall failed: %v", err)
 		return err
 	}
@@ -80,8 +87,8 @@
 	Long:  fmt.Sprintf("Removes the device manager installation from %s (if the env var set), or the current dir otherwise", deviceDirEnv),
 }
 
-func runUninstall(*cmdline.Command, []string) error {
-	if err := impl.Uninstall(installationDir()); err != nil {
+func runUninstall(cmd *cmdline.Command, _ []string) error {
+	if err := impl.Uninstall(installationDir(), cmd.Stderr(), cmd.Stdout()); err != nil {
 		vlog.Errorf("Uninstall failed: %v", err)
 		return err
 	}
@@ -95,8 +102,8 @@
 	Long:  fmt.Sprintf("Starts the device manager installed under from %s (if the env var set), or the current dir otherwise", deviceDirEnv),
 }
 
-func runStart(*cmdline.Command, []string) error {
-	if err := impl.Start(installationDir(), nil, nil); err != nil {
+func runStart(cmd *cmdline.Command, _ []string) error {
+	if err := impl.Start(installationDir(), cmd.Stderr(), cmd.Stdout()); err != nil {
 		vlog.Errorf("Start failed: %v", err)
 		return err
 	}
@@ -110,16 +117,33 @@
 	Long:  fmt.Sprintf("Stops the device manager installed under from %s (if the env var set), or the current dir otherwise", deviceDirEnv),
 }
 
-func runStop(*cmdline.Command, []string) error {
+func runStop(cmd *cmdline.Command, _ []string) error {
 	runtime, err := rt.New()
 	if err != nil {
 		vlog.Errorf("Could not initialize runtime: %v", err)
 		return err
 	}
 	defer runtime.Cleanup()
-	if err := impl.Stop(runtime.NewContext(), installationDir()); err != nil {
+	if err := impl.Stop(runtime.NewContext(), installationDir(), cmd.Stderr(), cmd.Stdout()); err != nil {
 		vlog.Errorf("Stop failed: %v", err)
 		return err
 	}
 	return nil
 }
+
+var cmdProfile = &cmdline.Command{
+	Run:   runProfile,
+	Name:  "profile",
+	Short: "Dumps profile for the device manager.",
+	Long:  "Prints the internal profile description for the device manager.",
+}
+
+func runProfile(cmd *cmdline.Command, _ []string) error {
+	spec, err := impl.ComputeDeviceProfile()
+	if err != nil {
+		vlog.Errorf("ComputeDeviceProfile failed: %v", err)
+		return err
+	}
+	fmt.Fprintf(cmd.Stdout(), "Profile: %#v\n", spec)
+	return nil
+}
diff --git a/services/mgmt/device/deviced/main.go b/services/mgmt/device/deviced/main.go
index 9b21878..710b33f 100644
--- a/services/mgmt/device/deviced/main.go
+++ b/services/mgmt/device/deviced/main.go
@@ -9,7 +9,7 @@
 		Long: `
 deviced can be used to launch, configure, or manage the device manager.
 `,
-		Children: []*cmdline.Command{cmdInstall, cmdUninstall, cmdStart, cmdStop},
+		Children: []*cmdline.Command{cmdInstall, cmdUninstall, cmdStart, cmdStop, cmdProfile},
 		Run:      runServer,
 	}
 	rootCmd.Main()
diff --git a/services/mgmt/device/deviced/server.go b/services/mgmt/device/deviced/server.go
index 5ec30e7..69eef3a 100644
--- a/services/mgmt/device/deviced/server.go
+++ b/services/mgmt/device/deviced/server.go
@@ -2,6 +2,7 @@
 
 import (
 	"flag"
+	"time"
 
 	"v.io/lib/cmdline"
 
@@ -15,10 +16,10 @@
 )
 
 var (
-	// TODO(caprita): publishAs and stopExitCode should be provided by the
+	// TODO(caprita): publishAs and restartExitCode should be provided by the
 	// config?
-	publishAs    = flag.String("name", "", "name to publish the device manager at")
-	stopExitCode = flag.Int("stop_exit_code", 0, "exit code to return when stopped via the Stop RPC")
+	publishAs       = flag.String("name", "", "name to publish the device manager at")
+	restartExitCode = flag.Int("restart_exit_code", 0, "exit code to return when device manager should be restarted")
 )
 
 func runServer(*cmdline.Command, []string) error {
@@ -54,7 +55,7 @@
 	// implementation detail).
 
 	var exitErr error
-	dispatcher, err := impl.NewDispatcher(veyron2.GetPrincipal(ctx), configState, func() { exitErr = cmdline.ErrExitCode(*stopExitCode) })
+	dispatcher, err := impl.NewDispatcher(veyron2.GetPrincipal(ctx), configState, func() { exitErr = cmdline.ErrExitCode(*restartExitCode) })
 	if err != nil {
 		vlog.Errorf("Failed to create dispatcher: %v", err)
 		return err
@@ -66,7 +67,9 @@
 	vlog.VI(0).Infof("Device manager published as: %v", *publishAs)
 	impl.InvokeCallback(runtime.NewContext(), name)
 
-	// Wait until shutdown.
+	// Wait until shutdown.  Ignore duplicate signals (sent by agent and
+	// received as part of process group).
+	signals.SameSignalTimeWindow = 500 * time.Millisecond
 	<-signals.ShutdownOnSignals(ctx)
 
 	return exitErr
diff --git a/services/mgmt/device/impl/app_service.go b/services/mgmt/device/impl/app_service.go
index 5ccb84e..940df40 100644
--- a/services/mgmt/device/impl/app_service.go
+++ b/services/mgmt/device/impl/app_service.go
@@ -147,6 +147,7 @@
 	"v.io/core/veyron/security/agent"
 	"v.io/core/veyron/security/agent/keymgr"
 	iconfig "v.io/core/veyron/services/mgmt/device/config"
+	"v.io/core/veyron/services/mgmt/lib/acls"
 	libbinary "v.io/core/veyron/services/mgmt/lib/binary"
 	libpackages "v.io/core/veyron/services/mgmt/lib/packages"
 )
@@ -206,7 +207,7 @@
 	// instance.
 	suffix []string
 	uat    BlessingSystemAssociationStore
-	locks  aclLocks
+	locks  *acls.Locks
 	// Reference to the devicemanager top-level ACL list.
 	deviceACL access.TaggedACLMap
 	// securityAgent holds state related to the security agent (nil if not
@@ -393,20 +394,6 @@
 	return versionDir, updateLink(versionDir, filepath.Join(installationDir, "current"))
 }
 
-// TODO(rjkroege): Refactor this code with the instance creation code.
-func initializeInstallationACLs(principal security.Principal, dir string, blessings []string, acl access.TaggedACLMap) error {
-	// Add the invoker's blessings.
-	for _, b := range blessings {
-		for _, tag := range access.AllTypicalTags() {
-			acl.Add(security.BlessingPattern(b), string(tag))
-		}
-	}
-	aclDir := path.Join(dir, "acls")
-	aclData := path.Join(aclDir, "data")
-	aclSig := path.Join(aclDir, "signature")
-	return writeACLs(principal, aclData, aclSig, aclDir, acl)
-}
-
 func (i *appService) Install(call ipc.ServerContext, applicationVON string, config device.Config) (string, error) {
 	if len(i.suffix) > 0 {
 		return "", verror2.Make(ErrInvalidSuffix, call.Context())
@@ -443,7 +430,7 @@
 	// TODO(caprita,rjkroege): Should the installation ACLs really be
 	// seeded with the device ACL? Instead, might want to hide the deviceACL
 	// from the app?
-	if err := initializeInstallationACLs(call.LocalPrincipal(), installationDir, call.RemoteBlessings().ForContext(call), i.deviceACL.Copy()); err != nil {
+	if err := i.initializeSubACLs(call.LocalPrincipal(), installationDir, call.RemoteBlessings().ForContext(call), i.deviceACL.Copy()); err != nil {
 		return "", err
 	}
 	deferrer = nil
@@ -500,7 +487,7 @@
 		defer conn.Close()
 
 		// TODO(caprita): release the socket created by NewAgentPrincipal.
-		if p, err = agent.NewAgentPrincipal(ctx, int(conn.Fd())); err != nil {
+		if p, err = agent.NewAgentPrincipal(ctx, int(conn.Fd()), veyron2.GetClient(ctx)); err != nil {
 			vlog.Errorf("NewAgentPrincipal() failed: %v", err)
 			return verror2.Make(ErrOperationFailed, nil)
 		}
@@ -629,16 +616,14 @@
 	return nil
 }
 
-func initializeInstanceACLs(principal security.Principal, instanceDir string, blessings []string, acl access.TaggedACLMap) error {
+func (i *appService) initializeSubACLs(principal security.Principal, instanceDir string, blessings []string, acl access.TaggedACLMap) error {
 	for _, b := range blessings {
 		for _, tag := range access.AllTypicalTags() {
 			acl.Add(security.BlessingPattern(b), string(tag))
 		}
 	}
 	aclDir := path.Join(instanceDir, "acls")
-	aclData := path.Join(aclDir, "data")
-	aclSig := path.Join(aclDir, "signature")
-	return writeACLs(principal, aclData, aclSig, aclDir, acl)
+	return i.locks.SetPathACL(principal, aclDir, acl, "")
 }
 
 // newInstance sets up the directory for a new application instance.
@@ -686,7 +671,7 @@
 		return instanceDir, instanceID, err
 	}
 
-	if err := initializeInstanceACLs(call.LocalPrincipal(), instanceDir, call.RemoteBlessings().ForContext(call), i.deviceACL.Copy()); err != nil {
+	if err := i.initializeSubACLs(call.LocalPrincipal(), instanceDir, call.RemoteBlessings().ForContext(call), i.deviceACL.Copy()); err != nil {
 		return instanceDir, instanceID, err
 	}
 	return instanceDir, instanceID, nil
@@ -1311,13 +1296,13 @@
 	if err != nil {
 		return err
 	}
-	return setAppACL(ctx.LocalPrincipal(), i.locks, dir, acl, etag)
+	return i.locks.SetPathACL(ctx.LocalPrincipal(), path.Join(dir, "acls"), acl, etag)
 }
 
-func (i *appService) GetACL(_ ipc.ServerContext) (acl access.TaggedACLMap, etag string, err error) {
+func (i *appService) GetACL(ctx ipc.ServerContext) (acl access.TaggedACLMap, etag string, err error) {
 	dir, err := dirFromSuffix(i.suffix, i.config.Root)
 	if err != nil {
 		return nil, "", err
 	}
-	return getAppACL(i.locks, dir)
+	return i.locks.GetPathACL(ctx.LocalPrincipal(), path.Join(dir, "acls"))
 }
diff --git a/services/mgmt/device/impl/device_installer.go b/services/mgmt/device/impl/device_installer.go
index 15cf0ca..cfa0015 100644
--- a/services/mgmt/device/impl/device_installer.go
+++ b/services/mgmt/device/impl/device_installer.go
@@ -1,11 +1,39 @@
 package impl
 
+// The device installer logic is responsible for managing the device manager
+// server, including setting it up / tearing it down, and starting / stopping
+// it.
+//
+// When setting up the device manager installation, the installer creates a
+// directory structure from which the device manager can be run.  It sets up:
+//
+// <installDir>                - provided when installer is invoked
+//   dmroot/                   - created/owned by the installation
+//     device-manager/         - will be the root for the device manager server;
+//                               set as <Config.Root> (see comment in
+//                               device_service.go for what goes under here)
+//       base/                 - initial installation of device manager
+//         deviced             - link to deviced (self)
+//         deviced.sh          - script to start the device manager
+//       logs/                 - device manager logs will go here
+//     current                 - set as <Config.CurrentLink>
+//     agent_deviced.sh        - script to launch device manager under agent
+//     security/               - security agent keeps credentials here
+//       keys/
+//       principal/
+//     agent_logs/             - security agent logs
+//       STDERR-<timestamp>
+//       STDOUT-<timestamp>
+//     service_description     - json-encoded sysinit device manager config
+//     inithelper              - soft link to init helper
+
 import (
 	"fmt"
 	"io"
 	"io/ioutil"
 	"os"
 	"os/exec"
+	"os/user"
 	"path/filepath"
 	"regexp"
 	"strings"
@@ -16,12 +44,14 @@
 
 	"v.io/core/veyron/lib/flags/consts"
 	"v.io/core/veyron/services/mgmt/device/config"
+	"v.io/core/veyron/services/mgmt/sysinit"
 )
 
-// stopExitCode is the exit code that the device manager should return when it
-// gets a Stop RPC.  This number is picked quasi-arbitrarily from the set of
+// restartExitCode is the exit code that the device manager should return when it
+// wants to be restarted by its parent (i.e., the security agent).
+// This number is picked quasi-arbitrarily from the set of
 // exit codes without prior special meanings.
-const stopExitCode = 140
+const restartExitCode = 140
 
 // dmRoot is the directory name where the device manager installs itself.
 const dmRoot = "dmroot"
@@ -62,9 +92,34 @@
 	return filterEnvironment(env, allowedVarsRE, deniedVarsRE)
 }
 
+// initCommand verifies if init mode is enabled, and if so executes the
+// appropriate sysinit command.  Returns whether init mode was detected, as well
+// as any error encountered.
+func initCommand(root, command string, stderr, stdout io.Writer) (bool, error) {
+	sdFile := filepath.Join(root, "service_description")
+	if _, err := os.Stat(sdFile); err != nil {
+		if os.IsNotExist(err) {
+			return false, nil
+		}
+		return false, fmt.Errorf("Stat(%v) failed: %v", sdFile, err)
+	}
+	helperLink := filepath.Join(root, "inithelper")
+	cmd := exec.Command(helperLink, fmt.Sprintf("--service_description=%s", sdFile), command)
+	if stderr != nil {
+		cmd.Stderr = stderr
+	}
+	if stdout != nil {
+		cmd.Stdout = stdout
+	}
+	if err := cmd.Run(); err != nil {
+		return true, fmt.Errorf("Running init helper %v failed: %v", command, err)
+	}
+	return true, nil
+}
+
 // SelfInstall installs the device manager and configures it using the
 // environment and the supplied command-line flags.
-func SelfInstall(installDir, suidHelper, agent string, singleUser, sessionMode bool, args, env []string) error {
+func SelfInstall(installDir, suidHelper, agent, initHelper string, singleUser, sessionMode, init bool, args, env []string, stderr, stdout io.Writer) error {
 	root := filepath.Join(installDir, dmRoot)
 	if _, err := os.Stat(root); err == nil || !os.IsNotExist(err) {
 		return fmt.Errorf("%v already exists", root)
@@ -89,7 +144,7 @@
 		extraArgs = append(extraArgs, fmt.Sprintf("--name=%q", name))
 	}
 	if !sessionMode {
-		extraArgs = append(extraArgs, fmt.Sprintf("--stop_exit_code=%d", stopExitCode))
+		extraArgs = append(extraArgs, fmt.Sprintf("--restart_exit_code=%d", restartExitCode))
 	}
 	envelope := &application.Envelope{
 		Args: append(extraArgs, args...),
@@ -106,7 +161,8 @@
 	if err != nil {
 		return fmt.Errorf("failed to serialize config %v: %v", configState, err)
 	}
-	if err := generateScript(deviceDir, configSettings, envelope); err != nil {
+	logs := filepath.Join(root, "device-manager", "logs")
+	if err := generateScript(deviceDir, configSettings, envelope, logs); err != nil {
 		return err
 	}
 
@@ -115,8 +171,37 @@
 		return err
 	}
 
-	return generateAgentScript(root, agent, currLink, singleUser, sessionMode)
-	// TODO(caprita): Update system management daemon.
+	if err := generateAgentScript(root, agent, currLink, singleUser, sessionMode); err != nil {
+		return err
+	}
+	if init {
+		agentScript := filepath.Join(root, "agent_deviced.sh")
+		currentUser, err := user.Current()
+		if err != nil {
+			return err
+		}
+		sd := &sysinit.ServiceDescription{
+			Service:     "deviced",
+			Description: "Vanadium Device Manager",
+			Binary:      agentScript,
+			Command:     []string{agentScript},
+			User:        currentUser.Username,
+		}
+		sdFile := filepath.Join(root, "service_description")
+		if err := sd.SaveTo(sdFile); err != nil {
+			return fmt.Errorf("SaveTo for %v failed: %v", sd, err)
+		}
+		helperLink := filepath.Join(root, "inithelper")
+		if err := os.Symlink(initHelper, helperLink); err != nil {
+			return fmt.Errorf("Symlink(%v, %v) failed: %v", initHelper, helperLink, err)
+		}
+		if initMode, err := initCommand(root, "install", stderr, stdout); err != nil {
+			return err
+		} else if !initMode {
+			return fmt.Errorf("enabling init mode failed")
+		}
+	}
+	return nil
 }
 
 func generateAgentScript(workspace, agent, currLink string, singleUser, sessionMode bool) error {
@@ -130,8 +215,13 @@
 	if err := os.MkdirAll(keyDir, perm); err != nil {
 		return fmt.Errorf("MkdirAll(%v, %v) failed: %v", keyDir, perm, err)
 	}
+	logs := filepath.Join(workspace, "agent_logs")
+	if err := os.MkdirAll(logs, perm); err != nil {
+		return fmt.Errorf("MkdirAll(%v, %v) failed: %v", logs, perm, err)
+	}
 	// TODO(caprita): Switch all our generated bash scripts to use templates.
 	output := "#!/bin/bash\n"
+	output += fmt.Sprintln("readonly TIMESTAMP=$(date +%s%N)")
 	output += fmt.Sprintf("%s=%q ", consts.VeyronCredentials, principalDir)
 	// Escape the path to the binary; %q uses Go-syntax escaping, but it's
 	// close enough to Bash that we're using it as an approximation.
@@ -143,10 +233,13 @@
 		output += "--no_passphrase "
 	}
 	if !sessionMode {
-		output += fmt.Sprintf("--restart_exit_code=!%d ", stopExitCode)
+		output += fmt.Sprintf("--restart_exit_code=!0 ")
 	}
 	output += fmt.Sprintf("--additional_principals=%q ", keyDir)
-	output += fmt.Sprintf("%q\n", currLink)
+	stdoutLog, stderrLog := filepath.Join(logs, "STDERR"), filepath.Join(logs, "STDOUT")
+	// Write stdout and stderr both to the standard streams, and also to
+	// timestamped files.
+	output += fmt.Sprintf("%q > >(tee %s-$TIMESTAMP) 2> >(tee %s-$TIMESTAMP >&2)\n", currLink, stdoutLog, stderrLog)
 	path := filepath.Join(workspace, "agent_deviced.sh")
 	if err := ioutil.WriteFile(path, []byte(output), 0700); err != nil {
 		return fmt.Errorf("WriteFile(%v) failed: %v", path, err)
@@ -157,16 +250,18 @@
 
 // Uninstall undoes SelfInstall, removing the device manager's installation
 // directory.
-func Uninstall(installDir string) error {
+func Uninstall(installDir string, stdout, stderr io.Writer) error {
 	// TODO(caprita): ensure device is stopped?
 
 	root := filepath.Join(installDir, dmRoot)
+	if _, err := initCommand(root, "uninstall", stdout, stderr); err != nil {
+		return err
+	}
 	// TODO(caprita): Use suidhelper to delete dirs/files owned by other
 	// users under the app work dirs.
 	if err := os.RemoveAll(root); err != nil {
 		return fmt.Errorf("RemoveAll(%v) failed: %v", root, err)
 	}
-	// TODO(caprita): Update system management daemon.
 	return nil
 }
 
@@ -175,7 +270,13 @@
 	// TODO(caprita): make sure it's not already running?
 
 	root := filepath.Join(installDir, dmRoot)
-	// TODO(caprita): In non-session mode, use system management daemon.
+
+	if initMode, err := initCommand(root, "start", stderr, stdout); err != nil {
+		return err
+	} else if initMode {
+		return nil
+	}
+
 	agentScript := filepath.Join(root, "agent_deviced.sh")
 	cmd := exec.Command(agentScript)
 	if stderr != nil {
@@ -191,8 +292,13 @@
 }
 
 // Stop stops the device manager.
-func Stop(ctx *context.T, installDir string) error {
+func Stop(ctx *context.T, installDir string, stderr, stdout io.Writer) error {
 	root := filepath.Join(installDir, dmRoot)
+	if initMode, err := initCommand(root, "stop", stderr, stdout); err != nil {
+		return err
+	} else if initMode {
+		return nil
+	}
 	info, err := loadManagerInfo(filepath.Join(root, "device-manager"))
 	if err != nil {
 		return fmt.Errorf("loadManagerInfo failed: %v", err)
@@ -201,7 +307,5 @@
 		return fmt.Errorf("Stop failed: %v", err)
 	}
 	// TODO(caprita): Wait for the (device|agent) process to be gone.
-
-	// TODO(caprita): In non-session mode, use system management daemon.
 	return nil
 }
diff --git a/services/mgmt/device/impl/device_service.go b/services/mgmt/device/impl/device_service.go
index 02d1113..e8c9617 100644
--- a/services/mgmt/device/impl/device_service.go
+++ b/services/mgmt/device/impl/device_service.go
@@ -8,14 +8,18 @@
 //   device-manager/
 //     info                    - metadata for the device manager (such as object
 //                               name and process id)
+//     logs/                   - device manager logs
+//       STDERR-<timestamp>    - one for each execution of device manager
+//       STDOUT-<timestamp>    - one for each execution of device manager
 //     <version 1 timestamp>/  - timestamp of when the version was downloaded
 //       deviced               - the device manager binary
 //       deviced.sh            - a shell script to start the binary
 //     <version 2 timestamp>
 //     ...
 //     device-data/
-//       acl.devicemanager
-//	 acl.signature
+//       acls/
+//         data
+//         signature
 //	 associated.accounts
 //
 // The device manager is always expected to be started through the symbolic link
@@ -90,12 +94,12 @@
 
 // deviceService implements the Device manager's Device interface.
 type deviceService struct {
-	updating    *updatingState
-	stopHandler func()
-	callback    *callbackState
-	config      *config.State
-	disp        *dispatcher
-	uat         BlessingSystemAssociationStore
+	updating       *updatingState
+	restartHandler func()
+	callback       *callbackState
+	config         *config.State
+	disp           *dispatcher
+	uat            BlessingSystemAssociationStore
 }
 
 // managerInfo holds state about a running device manager.
@@ -140,31 +144,21 @@
 }
 
 func (*deviceService) Describe(ipc.ServerContext) (device.Description, error) {
-	empty := device.Description{}
-	deviceProfile, err := computeDeviceProfile()
-	if err != nil {
-		return empty, err
-	}
-	knownProfiles, err := getKnownProfiles()
-	if err != nil {
-		return empty, err
-	}
-	result := matchProfiles(deviceProfile, knownProfiles)
-	return result, nil
+	return describe()
 }
 
 func (*deviceService) IsRunnable(_ ipc.ServerContext, description binary.Description) (bool, error) {
-	deviceProfile, err := computeDeviceProfile()
+	deviceProfile, err := ComputeDeviceProfile()
 	if err != nil {
 		return false, err
 	}
-	binaryProfiles := make([]profile.Specification, 0)
+	binaryProfiles := make([]*profile.Specification, 0)
 	for name, _ := range description.Profiles {
 		profile, err := getProfile(name)
 		if err != nil {
 			return false, err
 		}
-		binaryProfiles = append(binaryProfiles, *profile)
+		binaryProfiles = append(binaryProfiles, profile)
 	}
 	result := matchProfiles(deviceProfile, binaryProfiles)
 	return len(result.Profiles) > 0, nil
@@ -196,6 +190,9 @@
 	if err := updateLink(s.config.Previous, s.config.CurrentLink); err != nil {
 		return err
 	}
+	if s.restartHandler != nil {
+		s.restartHandler()
+	}
 	veyron2.GetAppCycle(ctx).Stop()
 	return nil
 }
@@ -311,7 +308,7 @@
 
 // TODO(caprita): Move this to util.go since device_installer is also using it now.
 
-func generateScript(workspace string, configSettings []string, envelope *application.Envelope) error {
+func generateScript(workspace string, configSettings []string, envelope *application.Envelope, logs string) error {
 	// TODO(caprita): Remove this snippet of code, it doesn't seem to serve
 	// any purpose.
 	path, err := filepath.EvalSymlinks(os.Args[0])
@@ -321,6 +318,7 @@
 	}
 
 	output := "#!/bin/bash\n"
+	output += fmt.Sprintln("readonly TIMESTAMP=$(date +%s%N)")
 	output += strings.Join(config.QuoteEnv(append(envelope.Env, configSettings...)), " ") + " "
 	// Escape the path to the binary; %q uses Go-syntax escaping, but it's
 	// close enough to Bash that we're using it as an approximation.
@@ -329,7 +327,14 @@
 	// veyron/tools/debug/impl.go) instead.
 	output += fmt.Sprintf("exec %q", filepath.Join(workspace, "deviced")) + " "
 	output += strings.Join(envelope.Args, " ")
-	output += "\n"
+	if err := os.MkdirAll(logs, 0700); err != nil {
+		vlog.Errorf("MkdirAll(%v) failed: %v", logs, err)
+		return verror2.Make(ErrOperationFailed, nil)
+	}
+	stderrLog, stdoutLog := filepath.Join(logs, "STDERR"), filepath.Join(logs, "STDOUT")
+	// Write stdout and stderr both to the standard streams, and also to
+	// timestamped files.
+	output += fmt.Sprintf(" > >(tee %s-$TIMESTAMP) 2> >(tee %s-$TIMESTAMP >&2)\n", stdoutLog, stderrLog)
 	path = filepath.Join(workspace, "deviced.sh")
 	if err := ioutil.WriteFile(path, []byte(output), 0700); err != nil {
 		vlog.Errorf("WriteFile(%v) failed: %v", path, err)
@@ -389,7 +394,8 @@
 		return verror2.Make(ErrOperationFailed, ctx)
 	}
 
-	if err := generateScript(workspace, configSettings, envelope); err != nil {
+	logs := filepath.Join(s.config.Root, "device-manager", "logs")
+	if err := generateScript(workspace, configSettings, envelope, logs); err != nil {
 		return err
 	}
 
@@ -401,6 +407,9 @@
 		return err
 	}
 
+	if s.restartHandler != nil {
+		s.restartHandler()
+	}
 	veyron2.GetAppCycle(ctx).Stop()
 	deferrer = nil
 	return nil
@@ -443,15 +452,17 @@
 	return nil, verror2.Make(ErrInvalidSuffix, ctx.Context())
 }
 
-func (s *deviceService) Stop(call ipc.ServerContext, _ uint32) error {
-	if s.stopHandler != nil {
-		s.stopHandler()
-	}
+func (*deviceService) Stop(call ipc.ServerContext, _ uint32) error {
 	veyron2.GetAppCycle(call.Context()).Stop()
 	return nil
 }
 
-func (*deviceService) Suspend(call ipc.ServerContext) error {
+func (s *deviceService) Suspend(call ipc.ServerContext) error {
+	// TODO(caprita): move this to Restart and disable Suspend for device
+	// manager?
+	if s.restartHandler != nil {
+		s.restartHandler()
+	}
 	veyron2.GetAppCycle(call.Context()).Stop()
 	return nil
 }
@@ -482,11 +493,11 @@
 }
 
 func (s *deviceService) SetACL(ctx ipc.ServerContext, acl access.TaggedACLMap, etag string) error {
-	return s.disp.setACL(ctx.LocalPrincipal(), acl, etag, true /* store ACL on disk */)
+	return s.disp.locks.SetPathACL(ctx.LocalPrincipal(), s.disp.getACLDir(), acl, etag)
 }
 
-func (s *deviceService) GetACL(_ ipc.ServerContext) (acl access.TaggedACLMap, etag string, err error) {
-	return s.disp.getACL()
+func (s *deviceService) GetACL(ctx ipc.ServerContext) (acl access.TaggedACLMap, etag string, err error) {
+	return s.disp.locks.GetPathACL(ctx.LocalPrincipal(), s.disp.getACLDir())
 }
 
 func sameMachineCheck(ctx ipc.ServerContext) error {
diff --git a/services/mgmt/device/impl/dispatcher.go b/services/mgmt/device/impl/dispatcher.go
index dabfcbc..30cf651 100644
--- a/services/mgmt/device/impl/dispatcher.go
+++ b/services/mgmt/device/impl/dispatcher.go
@@ -2,7 +2,6 @@
 
 import (
 	"fmt"
-	"io/ioutil"
 	"os"
 	"path"
 	"path/filepath"
@@ -11,8 +10,7 @@
 
 	"v.io/core/veyron/security/agent"
 	"v.io/core/veyron/security/agent/keymgr"
-	vflag "v.io/core/veyron/security/flag"
-	"v.io/core/veyron/security/serialization"
+	"v.io/core/veyron/security/flag"
 	idevice "v.io/core/veyron/services/mgmt/device"
 	"v.io/core/veyron/services/mgmt/device/config"
 	"v.io/core/veyron/services/mgmt/lib/acls"
@@ -32,25 +30,14 @@
 // internalState wraps state shared between different device manager
 // invocations.
 type internalState struct {
-	callback      *callbackState
-	updating      *updatingState
-	securityAgent *securityAgentState
-	stopHandler   func()
+	callback       *callbackState
+	updating       *updatingState
+	securityAgent  *securityAgentState
+	restartHandler func()
 }
 
-// aclLocks provides a mutex lock for each acl file path.
-type aclLocks map[string]*sync.Mutex
-
 // dispatcher holds the state of the device manager dispatcher.
 type dispatcher struct {
-	// acl/auth hold the acl and authorizer used to authorize access to the
-	// device manager methods.
-	acl  access.TaggedACLMap
-	auth security.Authorizer
-	// etag holds the version string for the ACL. We use this for optimistic
-	// concurrency control when clients update the ACLs for the device
-	// manager.
-	etag string
 	// internal holds the state that persists across RPC method invocations.
 	internal *internalState
 	// config holds the device manager's (immutable) configuration state.
@@ -59,9 +46,9 @@
 	// dispatcher methods.
 	mu sync.RWMutex
 	// TODO(rjkroege): Consider moving this inside internal.
-	uat BlessingSystemAssociationStore
-	// TODO(rjkroege): Eliminate need for locks.
-	locks aclLocks
+	uat       BlessingSystemAssociationStore
+	locks     *acls.Locks
+	principal security.Principal
 }
 
 var _ ipc.Dispatcher = (*dispatcher)(nil)
@@ -85,7 +72,7 @@
 )
 
 // NewDispatcher is the device manager dispatcher factory.
-func NewDispatcher(principal security.Principal, config *config.State, stopHandler func()) (*dispatcher, error) {
+func NewDispatcher(principal security.Principal, config *config.State, restartHandler func()) (*dispatcher, error) {
 	if err := config.Validate(); err != nil {
 		return nil, fmt.Errorf("invalid config %v: %v", config, err)
 	}
@@ -104,48 +91,25 @@
 		return nil, fmt.Errorf("cannot create persistent store for identity to system account associations: %v", err)
 	}
 	d := &dispatcher{
-		etag: "default",
 		internal: &internalState{
-			callback:    newCallbackState(config.Name),
-			updating:    newUpdatingState(),
-			stopHandler: stopHandler,
+			callback:       newCallbackState(config.Name),
+			updating:       newUpdatingState(),
+			restartHandler: restartHandler,
 		},
-		config: config,
-		uat:    uat,
-		locks:  make(aclLocks),
+		config:    config,
+		uat:       uat,
+		locks:     acls.NewLocks(),
+		principal: principal,
 	}
-	// If there exists a signed ACL from a previous instance we prefer that.
-	aclFile, sigFile, _ := d.getACLFilePaths()
-	if _, err := os.Stat(aclFile); err == nil {
-		perm := os.FileMode(0700)
-		data, err := os.OpenFile(aclFile, os.O_RDONLY, perm)
-		if err != nil {
-			return nil, fmt.Errorf("failed to open acl file:%v", err)
-		}
-		defer data.Close()
-		sig, err := os.OpenFile(sigFile, os.O_RDONLY, perm)
-		if err != nil {
-			return nil, fmt.Errorf("failed to open signature file:%v", err)
-		}
-		defer sig.Close()
-		// read and verify the signature of the acl file
-		reader, err := serialization.NewVerifyingReader(data, sig, principal.PublicKey())
-		if err != nil {
-			return nil, fmt.Errorf("failed to read devicemanager ACL file:%v", err)
-		}
-		acl, err := access.ReadTaggedACLMap(reader)
-		if err != nil {
-			return nil, fmt.Errorf("failed to load devicemanager ACL:%v", err)
-		}
-		if err := d.setACL(principal, acl, d.etag, false /* just update etag */); err != nil {
+
+	tam, err := flag.TaggedACLMapFromFlag()
+	if err != nil {
+		return nil, err
+	}
+	if tam != nil {
+		if err := d.locks.SetPathACL(principal, d.getACLDir(), tam, ""); err != nil {
 			return nil, err
 		}
-	} else {
-		if d.auth = vflag.NewAuthorizerOrDie(); d.auth == nil {
-			// If there are no specified ACLs we grant devicemanager
-			// access to all principals until it is claimed.
-			d.auth = allowEveryone{}
-		}
 	}
 	// If we're in 'security agent mode', set up the key manager agent.
 	if len(os.Getenv(agent.FdVarName)) > 0 {
@@ -160,10 +124,8 @@
 	return d, nil
 }
 
-func (d *dispatcher) getACLFilePaths() (acl, signature, devicedata string) {
-	devicedata = filepath.Join(d.config.Root, "device-manager", "device-data")
-	acl, signature = filepath.Join(devicedata, "acl.devicemanager"), filepath.Join(devicedata, "acl.signature")
-	return
+func (d *dispatcher) getACLDir() string {
+	return filepath.Join(d.config.Root, "device-manager", "device-data", "acls")
 }
 
 func (d *dispatcher) claimDeviceManager(ctx ipc.ServerContext) error {
@@ -193,157 +155,32 @@
 			acl.Add(security.BlessingPattern(n), string(tag))
 		}
 	}
-	_, etag, err := d.getACL()
-	if err != nil {
-		vlog.Errorf("Failed to getACL:%v", err)
-		return verror.Make(ErrOperationFailed, nil)
-	}
-	if err := d.setACL(principal, acl, etag, true /* store ACL on disk */); err != nil {
+	if err := d.locks.SetPathACL(principal, d.getACLDir(), acl, ""); err != nil {
 		vlog.Errorf("Failed to setACL:%v", err)
 		return verror.Make(ErrOperationFailed, nil)
 	}
 	return nil
 }
 
-// TODO(rjkroege): Further refactor ACL-setting code.
-func setAppACL(principal security.Principal, locks aclLocks, dir string, acl access.TaggedACLMap, etag string) error {
-	aclpath := path.Join(dir, "acls", "data")
-	sigpath := path.Join(dir, "acls", "signature")
+// TODO(rjkroege): Consider refactoring authorizer implementations to
+// be shareable with other components.
+func newAuthorizer(principal security.Principal, dir string, locks *acls.Locks) (security.Authorizer, error) {
+	rootTam, _, err := locks.GetPathACL(principal, dir)
 
-	// Acquire lock. Locks are per path to an acls file.
-	lck, contains := locks[dir]
-	if !contains {
-		lck = new(sync.Mutex)
-		locks[dir] = lck
+	if err != nil && os.IsNotExist(err) {
+		vlog.Errorf("GetPathACL(%s) failed: %v", dir, err)
+		return allowEveryone{}, nil
+	} else if err != nil {
+		return nil, err
 	}
-	lck.Lock()
-	defer lck.Unlock()
 
-	f, err := os.Open(aclpath)
+	auth, err := access.TaggedACLAuthorizer(rootTam, access.TypicalTagType())
 	if err != nil {
-		vlog.Errorf("LoadACL(%s) failed: %v", aclpath, err)
-		return err
+		vlog.Errorf("Successfully obtained an ACL from the filesystem but TaggedACLAuthorizer couldn't use it: %v", err)
+		return nil, err
 	}
-	defer f.Close()
+	return auth, nil
 
-	curACL, err := access.ReadTaggedACLMap(f)
-	if err != nil {
-		vlog.Errorf("ReadTaggedACLMap(%s) failed: %v", aclpath, err)
-		return err
-	}
-	curEtag, err := acls.ComputeEtag(curACL)
-	if err != nil {
-		vlog.Errorf("acls.ComputeEtag failed: %v", err)
-		return err
-	}
-
-	if len(etag) > 0 && etag != curEtag {
-		return verror.Make(access.BadEtag, nil, etag, curEtag)
-	}
-
-	return writeACLs(principal, aclpath, sigpath, dir, acl)
-}
-
-func getAppACL(locks aclLocks, dir string) (access.TaggedACLMap, string, error) {
-	aclpath := path.Join(dir, "acls", "data")
-
-	// Acquire lock. Locks are per path to an acls file.
-	lck, contains := locks[dir]
-	if !contains {
-		lck = new(sync.Mutex)
-		locks[dir] = lck
-	}
-	lck.Lock()
-	defer lck.Unlock()
-
-	f, err := os.Open(aclpath)
-	if err != nil {
-		vlog.Errorf("Open(%s) failed: %v", aclpath, err)
-		return nil, "", err
-	}
-	defer f.Close()
-
-	acl, err := access.ReadTaggedACLMap(f)
-	if err != nil {
-		vlog.Errorf("ReadTaggedACLMap(%s) failed: %v", aclpath, err)
-		return nil, "", err
-	}
-	curEtag, err := acls.ComputeEtag(acl)
-	if err != nil {
-		return nil, "", err
-	}
-	return acl, curEtag, nil
-}
-
-func writeACLs(principal security.Principal, aclFile, sigFile, dir string, acl access.TaggedACLMap) error {
-	// Create dir directory if it does not exist
-	os.MkdirAll(dir, os.FileMode(0700))
-	// Save the object to temporary data and signature files, and then move
-	// those files to the actual data and signature file.
-	data, err := ioutil.TempFile(dir, "data")
-	if err != nil {
-		vlog.Errorf("Failed to open tmpfile data:%v", err)
-		return verror.Make(ErrOperationFailed, nil)
-	}
-	defer os.Remove(data.Name())
-	sig, err := ioutil.TempFile(dir, "sig")
-	if err != nil {
-		vlog.Errorf("Failed to open tmpfile sig:%v", err)
-		return verror.Make(ErrOperationFailed, nil)
-	}
-	defer os.Remove(sig.Name())
-	writer, err := serialization.NewSigningWriteCloser(data, sig, principal, nil)
-	if err != nil {
-		vlog.Errorf("Failed to create NewSigningWriteCloser:%v", err)
-		return verror.Make(ErrOperationFailed, nil)
-	}
-	if err = acl.WriteTo(writer); err != nil {
-		vlog.Errorf("Failed to SaveACL:%v", err)
-		return verror.Make(ErrOperationFailed, nil)
-	}
-	if err = writer.Close(); err != nil {
-		vlog.Errorf("Failed to Close() SigningWriteCloser:%v", err)
-		return verror.Make(ErrOperationFailed, nil)
-	}
-	if err := os.Rename(data.Name(), aclFile); err != nil {
-		return err
-	}
-	if err := os.Rename(sig.Name(), sigFile); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (d *dispatcher) setACL(principal security.Principal, acl access.TaggedACLMap, etag string, writeToFile bool) error {
-	d.mu.Lock()
-	defer d.mu.Unlock()
-	aclFile, sigFile, devicedata := d.getACLFilePaths()
-
-	if len(etag) > 0 && etag != d.etag {
-		return verror.Make(access.BadEtag, nil, etag, d.etag)
-	}
-	if writeToFile {
-		if err := writeACLs(principal, aclFile, sigFile, devicedata, acl); err != nil {
-			return err
-		}
-	}
-
-	etag, err := acls.ComputeEtag(acl)
-	if err != nil {
-		return err
-	}
-	auth, err := access.TaggedACLAuthorizer(acl, access.TypicalTagType())
-	if err != nil {
-		return err
-	}
-	d.acl, d.etag, d.auth = acl, etag, auth
-	return nil
-}
-
-func (d *dispatcher) getACL() (acl access.TaggedACLMap, etag string, err error) {
-	d.mu.RLock()
-	defer d.mu.RUnlock()
-	return d.acl, d.etag, nil
 }
 
 // DISPATCHER INTERFACE IMPLEMENTATION
@@ -355,8 +192,13 @@
 			i--
 		}
 	}
+	auth, err := newAuthorizer(d.principal, d.getACLDir(), d.locks)
+	if err != nil {
+		return nil, nil, err
+	}
+
 	if len(components) == 0 {
-		return ipc.ChildrenGlobberInvoker(deviceSuffix, appsSuffix), d.auth, nil
+		return ipc.ChildrenGlobberInvoker(deviceSuffix, appsSuffix), auth, nil
 	}
 	// The implementation of the device manager is split up into several
 	// invokers, which are instantiated depending on the receiver name
@@ -364,14 +206,14 @@
 	switch components[0] {
 	case deviceSuffix:
 		receiver := device.DeviceServer(&deviceService{
-			callback:    d.internal.callback,
-			updating:    d.internal.updating,
-			stopHandler: d.internal.stopHandler,
-			config:      d.config,
-			disp:        d,
-			uat:         d.uat,
+			callback:       d.internal.callback,
+			updating:       d.internal.updating,
+			restartHandler: d.internal.restartHandler,
+			config:         d.config,
+			disp:           d,
+			uat:            d.uat,
 		})
-		return receiver, d.auth, nil
+		return receiver, auth, nil
 	case appsSuffix:
 		// Requests to apps/*/*/*/logs are handled locally by LogFileService.
 		// Requests to apps/*/*/*/pprof are proxied to the apps' __debug/pprof object.
@@ -386,7 +228,7 @@
 			case "logs":
 				logsDir := filepath.Join(appInstanceDir, "logs")
 				suffix := naming.Join(components[5:]...)
-				return logsimpl.NewLogFileService(logsDir, suffix), d.auth, nil
+				return logsimpl.NewLogFileService(logsDir, suffix), auth, nil
 			case "pprof", "stats":
 				info, err := loadInstanceInfo(appInstanceDir)
 				if err != nil {
@@ -395,23 +237,19 @@
 				if !instanceStateIs(appInstanceDir, started) {
 					return nil, nil, verror.Make(ErrInvalidSuffix, nil)
 				}
-				var sigStub signatureStub
-				if kind == "pprof" {
-					sigStub = pprof.PProfServer(nil)
-				} else {
-					sigStub = stats.StatsServer(nil)
+				var desc []ipc.InterfaceDesc
+				switch kind {
+				case "pprof":
+					desc = pprof.PProfServer(nil).Describe__()
+				case "stats":
+					desc = stats.StatsServer(nil).Describe__()
 				}
 				suffix := naming.Join("__debug", naming.Join(components[4:]...))
 				remote := naming.JoinAddressName(info.AppCycleMgrName, suffix)
-				invoker := &proxyInvoker{
-					remote:  remote,
-					access:  access.Debug,
-					sigStub: sigStub,
-				}
-				return invoker, d.auth, nil
+				invoker := newProxyInvoker(remote, access.Debug, desc)
+				return invoker, auth, nil
 			}
 		}
-		deviceACLs, _, err := d.getACL()
 		if err != nil {
 			return nil, nil, err
 		}
@@ -421,10 +259,9 @@
 			suffix:        components[1:],
 			uat:           d.uat,
 			locks:         d.locks,
-			deviceACL:     deviceACLs,
 			securityAgent: d.internal.securityAgent,
 		})
-		appSpecificAuthorizer, err := newAppSpecificAuthorizer(d.auth, d.config, components[1:])
+		appSpecificAuthorizer, err := newAppSpecificAuthorizer(auth, d.config, components[1:])
 		if err != nil {
 			return nil, nil, err
 		}
diff --git a/services/mgmt/device/impl/impl_test.go b/services/mgmt/device/impl/impl_test.go
index d509be9..0e52bd3 100644
--- a/services/mgmt/device/impl/impl_test.go
+++ b/services/mgmt/device/impl/impl_test.go
@@ -187,7 +187,7 @@
 		}
 		configState.Root, configState.Helper, configState.Origin, configState.CurrentLink = args[0], args[1], args[2], args[3]
 	}
-	dispatcher, err := impl.NewDispatcher(veyron2.GetPrincipal(globalCtx), configState, func() { fmt.Println("stop handler") })
+	dispatcher, err := impl.NewDispatcher(veyron2.GetPrincipal(globalCtx), configState, func() { fmt.Println("restart handler") })
 	if err != nil {
 		vlog.Fatalf("Failed to create device manager dispatcher: %v", err)
 	}
@@ -400,6 +400,7 @@
 
 	dmh.CloseStdin()
 
+	dms.Expect("restart handler")
 	dms.Expect("factoryDM terminating")
 	dmh.Shutdown(os.Stderr, os.Stderr)
 
@@ -431,6 +432,7 @@
 		t.Fatalf("current link didn't change")
 	}
 
+	dms.Expect("restart handler")
 	dms.Expect("v2DM terminating")
 
 	dmh.Shutdown(os.Stderr, os.Stderr)
@@ -449,6 +451,7 @@
 	revertDevice(t, "v3DM")
 	revertDeviceExpectError(t, "v3DM", impl.ErrOperationInProgress.ID) // Revert already in progress.
 	dmh.CloseStdin()
+	dms.Expect("restart handler")
 	dms.Expect("v3DM terminating")
 	if evalLink() != scriptPathV2 {
 		t.Fatalf("current link was not reverted correctly")
@@ -463,6 +466,7 @@
 
 	// Revert the device manager to its previous version (factory).
 	revertDevice(t, "v2DM")
+	dms.Expect("restart handler")
 	dms.Expect("v2DM terminating")
 	if evalLink() != scriptPathFactory {
 		t.Fatalf("current link was not reverted correctly")
@@ -475,7 +479,6 @@
 	mgmttest.ReadPID(t, dms)
 	resolve(t, "factoryDM", 1) // Current link should have been launching factory version.
 	stopDevice(t, "factoryDM")
-	dms.Expect("stop handler")
 	dms.Expect("factoryDM terminating")
 	dms.ExpectEOF()
 
@@ -485,6 +488,7 @@
 	mgmttest.ReadPID(t, dms)
 	resolve(t, "factoryDM", 1)
 	suspendDevice(t, "factoryDM")
+	dms.Expect("restart handler")
 	dms.Expect("factoryDM terminating")
 	dms.ExpectEOF()
 }
@@ -879,13 +883,10 @@
 	// Create an envelope for an app.
 	*envelope = envelopeFromShell(sh, nil, appCmd, "google naps")
 
-	deviceStub := device.DeviceClient("dm//device")
-	acl, etag, err := deviceStub.GetACL(selfCtx)
-	if err != nil {
-		t.Fatalf("GetACL failed:%v", err)
-	}
-	if etag != "default" {
-		t.Fatalf("getACL expected:default, got:%v(%v)", etag, acl)
+	// On an unclaimed device manager, there will be no ACLs.
+	deviceStub := device.DeviceClient("dm/device")
+	if _, _, err := deviceStub.GetACL(selfCtx); err == nil {
+		t.Fatalf("GetACL should have failed but didn't.")
 	}
 
 	// Claim the devicemanager as "root/self/mydevice"
@@ -902,7 +903,8 @@
 	}
 	md5hash := md5.Sum(b.Bytes())
 	expectedETAG := hex.EncodeToString(md5hash[:])
-	if acl, etag, err = deviceStub.GetACL(selfCtx); err != nil {
+	acl, etag, err := deviceStub.GetACL(selfCtx)
+	if err != nil {
 		t.Fatal(err)
 	}
 	if etag != expectedETAG {
@@ -949,17 +951,19 @@
 	defer cleanup()
 
 	// Create a script wrapping the test target that implements suidhelper.
-	helperPath := generateSuidHelperScript(t, testDir)
+	suidHelperPath := generateSuidHelperScript(t, testDir)
 	// Create a dummy script mascarading as the security agent.
 	agentPath := generateAgentScript(t, testDir)
+	initHelperPath := ""
 
 	// Create an 'envelope' for the device manager that we can pass to the
 	// installer, to ensure that the device manager that the installer
 	// configures can run.
 	dmargs, dmenv := sh.CommandEnvelope(deviceManagerCmd, nil, "dm")
 	dmDir := filepath.Join(testDir, "dm")
-	singleUser, sessionMode := true, true
-	if err := impl.SelfInstall(dmDir, helperPath, agentPath, singleUser, sessionMode, dmargs[1:], dmenv); err != nil {
+	// TODO(caprita): Add test logic when initMode = true.
+	singleUser, sessionMode, initMode := true, true, false
+	if err := impl.SelfInstall(dmDir, suidHelperPath, agentPath, initHelperPath, singleUser, sessionMode, initMode, dmargs[1:], dmenv, os.Stderr, os.Stdout); err != nil {
 		t.Fatalf("SelfInstall failed: %v", err)
 	}
 
@@ -975,14 +979,13 @@
 	revertDeviceExpectError(t, "dm", impl.ErrUpdateNoOp.ID) // No previous version available.
 
 	// Stop the device manager.
-	if err := impl.Stop(globalCtx, dmDir); err != nil {
+	if err := impl.Stop(globalCtx, dmDir, os.Stderr, os.Stdout); err != nil {
 		t.Fatalf("Stop failed: %v", err)
 	}
-	dms.Expect("stop handler")
 	dms.Expect("dm terminating")
 
 	// Uninstall.
-	if err := impl.Uninstall(dmDir); err != nil {
+	if err := impl.Uninstall(dmDir, os.Stderr, os.Stdout); err != nil {
 		t.Fatalf("Uninstall failed: %v", err)
 	}
 	// Ensure that the installation is gone.
diff --git a/services/mgmt/device/impl/mock_repo_test.go b/services/mgmt/device/impl/mock_repo_test.go
index 16fed19..4c2dd10 100644
--- a/services/mgmt/device/impl/mock_repo_test.go
+++ b/services/mgmt/device/impl/mock_repo_test.go
@@ -3,9 +3,11 @@
 import (
 	"crypto/md5"
 	"encoding/hex"
+	"fmt"
 	"io"
 	"io/ioutil"
 	"os"
+	"reflect"
 	"testing"
 
 	"v.io/core/veyron2/ipc"
@@ -62,8 +64,11 @@
 }
 
 // APPLICATION REPOSITORY INTERFACE IMPLEMENTATION
-func (i *arInvoker) Match(ipc.ServerContext, []string) (application.Envelope, error) {
+func (i *arInvoker) Match(_ ipc.ServerContext, profiles []string) (application.Envelope, error) {
 	vlog.VI(1).Infof("Match()")
+	if want := []string{"test-profile"}; !reflect.DeepEqual(profiles, want) {
+		return application.Envelope{}, fmt.Errorf("Expected profiles %v, got %v", want, profiles)
+	}
 	return i.envelope, nil
 }
 
diff --git a/services/mgmt/device/impl/only_for_test.go b/services/mgmt/device/impl/only_for_test.go
index 62a69cb..a0fc4a2 100644
--- a/services/mgmt/device/impl/only_for_test.go
+++ b/services/mgmt/device/impl/only_for_test.go
@@ -5,6 +5,7 @@
 	"os"
 	"path/filepath"
 
+	"v.io/core/veyron2/services/mgmt/device"
 	"v.io/core/veyron2/vlog"
 )
 
@@ -40,6 +41,10 @@
 		}
 	}
 	isSetuid = possiblyMockIsSetuid
+
+	describe = func() (descr device.Description, err error) {
+		return device.Description{Profiles: map[string]struct{}{"test-profile": struct{}{}}}, nil
+	}
 }
 
 func possiblyMockIsSetuid(fileStat os.FileInfo) bool {
diff --git a/services/mgmt/device/impl/profile.go b/services/mgmt/device/impl/profile.go
index 275fc3d..4e784af 100644
--- a/services/mgmt/device/impl/profile.go
+++ b/services/mgmt/device/impl/profile.go
@@ -13,13 +13,13 @@
 	"v.io/core/veyron2/services/mgmt/device"
 )
 
-// computeDeviceProfile generates a description of the runtime
+// ComputeDeviceProfile generates a description of the runtime
 // environment (supported file format, OS, architecture, libraries) of
 // the host device.
 //
 // TODO(jsimsa): Avoid computing the host device description from
 // scratch if a recent cached copy exists.
-func computeDeviceProfile() (*profile.Specification, error) {
+func ComputeDeviceProfile() (*profile.Specification, error) {
 	result := profile.Specification{}
 
 	// Find out what the supported file format, operating system, and
@@ -52,8 +52,8 @@
 	switch runtime.GOOS {
 	case "linux":
 		// For Linux, we identify what dynamically linked libraries are
-		// install by parsing the output of "ldconfig -p".
-		command := exec.Command("ldconfig", "-p")
+		// installed by parsing the output of "ldconfig -p".
+		command := exec.Command("/sbin/ldconfig", "-p")
 		output, err := command.CombinedOutput()
 		if err != nil {
 			return nil, err
@@ -101,32 +101,43 @@
 // TODO(jsimsa): Avoid retrieving the list of known profiles from a
 // remote server if a recent cached copy exists.
 func getProfile(name string) (*profile.Specification, error) {
+	profiles, err := getKnownProfiles()
+	if err != nil {
+		return nil, err
+	}
+	for _, p := range profiles {
+		if p.Label == name {
+			return p, nil
+		}
+	}
+	return nil, nil
+
 	// TODO(jsimsa): This function assumes the existence of a profile
 	// server from which the profiles can be retrieved. The profile
 	// server is a work in progress. When it exists, the commented out
 	// code below should work.
-	var profile profile.Specification
 	/*
-			client, err := r.NewClient()
-			if err != nil {
-				vlog.Errorf("NewClient() failed: %v", err)
-				return nil, err
-			}
-			defer client.Close()
-		  server := // TODO
-			method := "Specification"
-			inputs := make([]interface{}, 0)
-			call, err := client.StartCall(server + "/" + name, method, inputs)
-			if err != nil {
-				vlog.Errorf("StartCall(%s, %q, %v) failed: %v\n", server + "/" + name, method, inputs, err)
-				return nil, err
-			}
-			if err := call.Finish(&profiles); err != nil {
-				vlog.Errorf("Finish(%v) failed: %v\n", &profiles, err)
-				return nil, err
-			}
+		var profile profile.Specification
+				client, err := r.NewClient()
+				if err != nil {
+					vlog.Errorf("NewClient() failed: %v", err)
+					return nil, err
+				}
+				defer client.Close()
+			  server := // TODO
+				method := "Specification"
+				inputs := make([]interface{}, 0)
+				call, err := client.StartCall(server + "/" + name, method, inputs)
+				if err != nil {
+					vlog.Errorf("StartCall(%s, %q, %v) failed: %v\n", server + "/" + name, method, inputs, err)
+					return nil, err
+				}
+				if err := call.Finish(&profiles); err != nil {
+					vlog.Errorf("Finish(%v) failed: %v\n", &profiles, err)
+					return nil, err
+				}
+		return &profile, nil
 	*/
-	return &profile, nil
 }
 
 // getKnownProfiles gets a list of description for all publicly known
@@ -134,39 +145,51 @@
 //
 // TODO(jsimsa): Avoid retrieving the list of known profiles from a
 // remote server if a recent cached copy exists.
-func getKnownProfiles() ([]profile.Specification, error) {
+func getKnownProfiles() ([]*profile.Specification, error) {
+	return []*profile.Specification{
+		{
+			Label:       "linux-amd64",
+			Description: "",
+			Arch:        build.AMD64,
+			OS:          build.Linux,
+			Format:      build.ELF,
+		},
+		// TODO(caprita): Add profiles for Mac, Pi, etc.
+	}, nil
+
 	// TODO(jsimsa): This function assumes the existence of a profile
 	// server from which a list of known profiles can be retrieved. The
 	// profile server is a work in progress. When it exists, the
 	// commented out code below should work.
-	knownProfiles := make([]profile.Specification, 0)
+
 	/*
-			client, err := r.NewClient()
-			if err != nil {
-				vlog.Errorf("NewClient() failed: %v\n", err)
-				return nil, err
-			}
-			defer client.Close()
-		  server := // TODO
-			method := "List"
-			inputs := make([]interface{}, 0)
-			call, err := client.StartCall(server, method, inputs)
-			if err != nil {
-				vlog.Errorf("StartCall(%s, %q, %v) failed: %v\n", server, method, inputs, err)
-				return nil, err
-			}
-			if err := call.Finish(&knownProfiles); err != nil {
-				vlog.Errorf("Finish(&knownProfile) failed: %v\n", err)
-				return nil, err
-			}
+		knownProfiles := make([]profile.Specification, 0)
+				client, err := r.NewClient()
+				if err != nil {
+					vlog.Errorf("NewClient() failed: %v\n", err)
+					return nil, err
+				}
+				defer client.Close()
+			  server := // TODO
+				method := "List"
+				inputs := make([]interface{}, 0)
+				call, err := client.StartCall(server, method, inputs)
+				if err != nil {
+					vlog.Errorf("StartCall(%s, %q, %v) failed: %v\n", server, method, inputs, err)
+					return nil, err
+				}
+				if err := call.Finish(&knownProfiles); err != nil {
+					vlog.Errorf("Finish(&knownProfile) failed: %v\n", err)
+					return nil, err
+				}
+		return knownProfiles, nil
 	*/
-	return knownProfiles, nil
 }
 
 // matchProfiles inputs a profile that describes the host device and a
 // set of publicly known profiles and outputs a device description that
 // identifies the publicly known profiles supported by the host device.
-func matchProfiles(p *profile.Specification, known []profile.Specification) device.Description {
+func matchProfiles(p *profile.Specification, known []*profile.Specification) device.Description {
 	result := device.Description{Profiles: make(map[string]struct{})}
 loop:
 	for _, profile := range known {
@@ -189,3 +212,29 @@
 	}
 	return result
 }
+
+// describe returns a Description containing the profile that matches the
+// current device.  It's declared as a variable so we can override it for
+// testing.
+var describe = func() (device.Description, error) {
+	empty := device.Description{}
+	deviceProfile, err := ComputeDeviceProfile()
+	if err != nil {
+		return empty, err
+	}
+	knownProfiles, err := getKnownProfiles()
+	if err != nil {
+		return empty, err
+	}
+	result := matchProfiles(deviceProfile, knownProfiles)
+	if len(result.Profiles) == 0 {
+		// For now, return "unknown" as the profile, if no known profile
+		// matches the device's profile.
+		//
+		// TODO(caprita): Get rid of this crutch once we have profiles
+		// defined for our supported systems; for now it helps us make
+		// the integration test work on e.g. Mac.
+		result.Profiles["unknown"] = struct{}{}
+	}
+	return result, nil
+}
diff --git a/services/mgmt/device/impl/proxy_invoker.go b/services/mgmt/device/impl/proxy_invoker.go
index 506d57f..9f82f88 100644
--- a/services/mgmt/device/impl/proxy_invoker.go
+++ b/services/mgmt/device/impl/proxy_invoker.go
@@ -17,19 +17,25 @@
 //
 // remote is the name of the remote object.
 // access is the access tag require to access the object.
-// sigStub is used to get the signature of the remote object.
+// desc is used to determine the number of results for a given method.
+func newProxyInvoker(remote string, access access.Tag, desc []ipc.InterfaceDesc) *proxyInvoker {
+	methodNumResults := make(map[string]int)
+	for _, iface := range desc {
+		for _, method := range iface.Methods {
+			methodNumResults[method.Name] = len(method.OutArgs)
+		}
+	}
+	return &proxyInvoker{remote, access, methodNumResults}
+}
+
 type proxyInvoker struct {
-	remote  string
-	access  access.Tag
-	sigStub signatureStub
+	remote           string
+	access           access.Tag
+	methodNumResults map[string]int
 }
 
 var _ ipc.Invoker = (*proxyInvoker)(nil)
 
-type signatureStub interface {
-	Signature(ipc.ServerContext) (ipc.ServiceSignature, error)
-}
-
 func (p *proxyInvoker) Prepare(method string, numArgs int) (argptrs, tags []interface{}, err error) {
 	argptrs = make([]interface{}, numArgs)
 	for i, _ := range argptrs {
@@ -218,21 +224,15 @@
 
 // numResults returns the number of result values for the given method.
 func (p *proxyInvoker) numResults(method string) (int, error) {
-	// TODO(toddw): Replace this mechanism when the new signature mechanism is
-	// complete.
 	switch method {
 	case ipc.GlobMethod:
 		return 1, nil
 	case ipc.ReservedSignature, ipc.ReservedMethodSignature:
 		return 2, nil
 	}
-	sig, err := p.sigStub.Signature(nil)
-	if err != nil {
-		return 0, err
-	}
-	m, ok := sig.Methods[method]
+	num, ok := p.methodNumResults[method]
 	if !ok {
 		return 0, fmt.Errorf("unknown method %q", method)
 	}
-	return len(m.OutArgs), nil
+	return num, nil
 }
diff --git a/services/mgmt/device/impl/proxy_invoker_test.go b/services/mgmt/device/impl/proxy_invoker_test.go
index 2da3bdc..2009a8c 100644
--- a/services/mgmt/device/impl/proxy_invoker_test.go
+++ b/services/mgmt/device/impl/proxy_invoker_test.go
@@ -53,7 +53,7 @@
 	disp := &proxyDispatcher{
 		runtime,
 		naming.JoinAddressName(eps1[0].String(), "__debug/stats"),
-		stats.StatsServer(nil),
+		stats.StatsServer(nil).Describe__(),
 	}
 	if err := server2.ServeDispatcher("", disp); err != nil {
 		t.Fatalf("server2.Serve: %v", err)
@@ -87,15 +87,10 @@
 type proxyDispatcher struct {
 	runtime veyron2.Runtime
 	remote  string
-	sigStub signatureStub
+	desc    []ipc.InterfaceDesc
 }
 
 func (d *proxyDispatcher) Lookup(suffix string) (interface{}, security.Authorizer, error) {
 	vlog.Infof("LOOKUP(%s): remote .... %s", suffix, d.remote)
-	invoker := &proxyInvoker{
-		remote:  naming.Join(d.remote, suffix),
-		access:  access.Debug,
-		sigStub: d.sigStub,
-	}
-	return invoker, nil, nil
+	return newProxyInvoker(naming.Join(d.remote, suffix), access.Debug, d.desc), nil, nil
 }
diff --git a/services/mgmt/device/impl/util.go b/services/mgmt/device/impl/util.go
index 50d892e..09fa70a 100644
--- a/services/mgmt/device/impl/util.go
+++ b/services/mgmt/device/impl/util.go
@@ -41,7 +41,15 @@
 	stub := repository.ApplicationClient(origin)
 	// TODO(jsimsa): Include logic that computes the set of supported
 	// profiles.
-	profiles := []string{"test"}
+	profilesSet, err := describe()
+	if err != nil {
+		vlog.Errorf("Failed to obtain profile labels: %v", err)
+		return nil, verror2.Make(ErrOperationFailed, ctx)
+	}
+	var profiles []string
+	for label := range profilesSet.Profiles {
+		profiles = append(profiles, label)
+	}
 	envelope, err := stub.Match(ctx, profiles)
 	if err != nil {
 		vlog.Errorf("Match(%v) failed: %v", profiles, err)
diff --git a/services/mgmt/device/impl/util_test.go b/services/mgmt/device/impl/util_test.go
index dd072de..4d8be6d 100644
--- a/services/mgmt/device/impl/util_test.go
+++ b/services/mgmt/device/impl/util_test.go
@@ -45,8 +45,8 @@
 
 // resolveExpectNotFound verifies that the given name is not in the mounttable.
 func resolveExpectNotFound(t *testing.T, name string) {
-	if results, err := veyron2.GetNamespace(globalCtx).Resolve(globalCtx, name); err == nil {
-		t.Fatalf(testutil.FormatLogLine(2, "Resolve(%v) succeeded with results %v when it was expected to fail", name, results))
+	if me, err := veyron2.GetNamespace(globalCtx).Resolve(globalCtx, name); err == nil {
+		t.Fatalf(testutil.FormatLogLine(2, "Resolve(%v) succeeded with results %v when it was expected to fail", name, me.Names()))
 	} else if expectErr := naming.ErrNoSuchName.ID; !verror2.Is(err, expectErr) {
 		t.Fatalf(testutil.FormatLogLine(2, "Resolve(%v) failed with error %v, expected error ID %v", name, err, expectErr))
 	}
@@ -54,13 +54,13 @@
 
 // resolve looks up the given name in the mounttable.
 func resolve(t *testing.T, name string, replicas int) []string {
-	results, err := veyron2.GetNamespace(globalCtx).Resolve(globalCtx, name)
+	me, err := veyron2.GetNamespace(globalCtx).Resolve(globalCtx, name)
 	if err != nil {
 		t.Fatalf("Resolve(%v) failed: %v", name, err)
 	}
 
 	filteredResults := []string{}
-	for _, r := range results {
+	for _, r := range me.Names() {
 		if strings.Index(r, "@tcp") != -1 {
 			filteredResults = append(filteredResults, r)
 		}
diff --git a/services/mgmt/inithelper/main.go b/services/mgmt/inithelper/main.go
new file mode 100644
index 0000000..a6f3fb4
--- /dev/null
+++ b/services/mgmt/inithelper/main.go
@@ -0,0 +1,98 @@
+package main
+
+// TODO(caprita): The separation of responsibilities between root/non-root code
+// can be shifted away from root a bit more, by having the init daemon files
+// created as non-root and root just installs files and runs a specific set of
+// commands.  Figure out if worth it.  Also consider combining with suidhelper.
+// For now they're separate since we don't always need both at the same time.
+
+// TODO(caprita): Add unit test.
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"os"
+
+	"v.io/core/veyron/services/mgmt/sysinit"
+)
+
+func usage() {
+	const usage = `Usage:
+%s [flags] [command]
+
+ Flags:
+%s
+ Command:
+  print: prints the file that would be installed
+  install: installs the service
+  uninstall: uninstalls the service
+  start: starts the service
+  stop: stops the service
+`
+	var flagDefaults bytes.Buffer
+	flag.CommandLine.SetOutput(&flagDefaults)
+	flag.CommandLine.PrintDefaults()
+	flag.CommandLine.SetOutput(nil)
+	fmt.Fprintf(os.Stderr, usage, os.Args[0], flagDefaults.String())
+}
+
+func main() {
+	flag.Usage = usage
+	sdFlag := flag.String("service_description", "", "File containing a JSON-encoded sysinit.ServiceDescription object.")
+	systemFlag := flag.String("system", sysinit.InitSystem(), "System label, to select the appropriate sysinit mechanism.")
+	flag.Parse()
+	if *sdFlag == "" {
+		fmt.Fprintf(os.Stderr, "--service_description must be set.\n")
+		flag.Usage()
+		os.Exit(1)
+	}
+	if *systemFlag == "" {
+		fmt.Fprintf(os.Stderr, "--system must be set.\n")
+		flag.Usage()
+		os.Exit(1)
+	}
+	var sd sysinit.ServiceDescription
+	if err := sd.LoadFrom(*sdFlag); err != nil {
+		fmt.Fprintf(os.Stderr, "LoadFrom(%v) failed: %v\n", *sdFlag, err)
+		os.Exit(2)
+	}
+	si := sysinit.New(*systemFlag, &sd)
+	args := flag.Args()
+	if len(args) != 1 {
+		fmt.Fprintf(os.Stderr, "Command must be specified.\n")
+		flag.Usage()
+		os.Exit(1)
+	}
+	switch args[0] {
+	case "print":
+		if err := si.Print(); err != nil {
+			fmt.Fprintf(os.Stderr, "Failed to print %v: %s\n", si, err)
+			os.Exit(2)
+		}
+	case "install":
+		if err := si.Install(); err != nil {
+			fmt.Fprintf(os.Stderr, "Failed to install %v: %s\n", si, err)
+			os.Exit(2)
+		}
+	case "uninstall":
+		if err := si.Uninstall(); err != nil {
+			fmt.Fprintf(os.Stderr, "Failed to uninstall %v: %s\n", si, err)
+			os.Exit(2)
+		}
+	case "start":
+		if err := si.Start(); err != nil {
+			fmt.Fprintf(os.Stderr, "Failed to start %v: %s\n", si, err)
+			os.Exit(2)
+		}
+	case "stop":
+		if err := si.Stop(); err != nil {
+			fmt.Fprintf(os.Stderr, "Failed to stop %v: %s\n", si, err)
+			os.Exit(2)
+		}
+	default:
+		fmt.Fprintf(os.Stderr, "Invalid command: %s\n", args[0])
+		flag.Usage()
+		os.Exit(1)
+	}
+}
diff --git a/services/mgmt/lib/acls/aclaccess.go b/services/mgmt/lib/acls/aclaccess.go
new file mode 100644
index 0000000..07e63a6
--- /dev/null
+++ b/services/mgmt/lib/acls/aclaccess.go
@@ -0,0 +1,157 @@
+// Package acls provides a library to assist servers implementing
+// GetACL/SetACL functions where there are path-specific ACLs
+// stored individually in files in the filesystem.
+// TODO(rjkroege): Add unit tests.
+package acls
+
+import (
+	"io/ioutil"
+	"os"
+	"path"
+	"sync"
+
+	"v.io/core/veyron2/security"
+	"v.io/core/veyron2/services/security/access"
+	verror "v.io/core/veyron2/verror2"
+	"v.io/core/veyron2/vlog"
+
+	"v.io/core/veyron/security/serialization"
+)
+
+const (
+	pkgPath = "v.io/core/veyron/services/mgmt/lib/acls"
+	sigName = "signature"
+	aclName = "data"
+)
+
+var (
+	ErrOperationFailed = verror.Register(pkgPath+".OperationFailed", verror.NoRetry, "{1:}{2:} operation failed{:_}")
+)
+
+// Locks provides a mutex lock for each acl file path.
+type Locks struct {
+	pthlks map[string]*sync.Mutex
+	lk     sync.Mutex
+}
+
+// NewLocks creates a new instance of the lock map.
+func NewLocks() *Locks {
+	return &Locks{pthlks: make(map[string]*sync.Mutex)}
+}
+
+// GetPathACL returns the TaggedACLMap from the data file in dir.
+func (locks Locks) GetPathACL(principal security.Principal, dir string) (access.TaggedACLMap, string, error) {
+	aclpath := path.Join(dir, aclName)
+	sigpath := path.Join(dir, sigName)
+	defer locks.lockPath(dir)()
+	return getCore(principal, aclpath, sigpath)
+}
+
+// TODO(rjkroege): Improve lock handling.
+func (locks Locks) lockPath(dir string) func() {
+	locks.lk.Lock()
+	lck, contains := locks.pthlks[dir]
+	if !contains {
+		lck = new(sync.Mutex)
+		locks.pthlks[dir] = lck
+	}
+	locks.lk.Unlock()
+	lck.Lock()
+	return lck.Unlock
+}
+
+func getCore(principal security.Principal, aclpath, sigpath string) (access.TaggedACLMap, string, error) {
+	f, err := os.Open(aclpath)
+	if err != nil {
+		// This path is rarely a fatal error so log informationally only.
+		vlog.VI(2).Infof("os.Open(%s) failed: %v", aclpath, err)
+		return nil, "", err
+	}
+	defer f.Close()
+
+	s, err := os.Open(sigpath)
+	if err != nil {
+		vlog.Errorf("Signatures for ACLs are required: %s unavailable: %v", aclpath, err)
+		return nil, "", verror.Make(ErrOperationFailed, nil)
+	}
+	defer s.Close()
+
+	// read and verify the signature of the acl file
+	vf, err := serialization.NewVerifyingReader(f, s, principal.PublicKey())
+	if err != nil {
+		vlog.Errorf("NewVerifyingReader() failed: %v", err)
+		return nil, "", verror.Make(ErrOperationFailed, nil)
+	}
+
+	acl, err := access.ReadTaggedACLMap(vf)
+	if err != nil {
+		vlog.Errorf("ReadTaggedACLMap(%s) failed: %v", aclpath, err)
+		return nil, "", err
+	}
+	etag, err := ComputeEtag(acl)
+	if err != nil {
+		vlog.Errorf("acls.ComputeEtag failed: %v", err)
+		return nil, "", err
+	}
+	return acl, etag, nil
+}
+
+// SetPathACL writes the specified TaggedACLMap to the provided
+// directory with enforcement of etag synchronization mechanism and
+// locking.
+func (locks Locks) SetPathACL(principal security.Principal, dir string, acl access.TaggedACLMap, etag string) error {
+	aclpath := path.Join(dir, aclName)
+	sigpath := path.Join(dir, sigName)
+	defer locks.lockPath(dir)()
+	_, oetag, err := getCore(principal, aclpath, sigpath)
+	if err != nil && !os.IsNotExist(err) {
+		return verror.Make(ErrOperationFailed, nil)
+	}
+	if len(etag) > 0 && etag != oetag {
+		return verror.Make(access.BadEtag, nil, etag, oetag)
+	}
+	return write(principal, aclpath, sigpath, dir, acl)
+}
+
+// write writes the specified TaggedACLMap to the aclFile with a
+// signature in sigFile.
+func write(principal security.Principal, aclFile, sigFile, dir string, acl access.TaggedACLMap) error {
+	// Create dir directory if it does not exist
+	os.MkdirAll(dir, os.FileMode(0700))
+	// Save the object to temporary data and signature files, and then move
+	// those files to the actual data and signature file.
+	data, err := ioutil.TempFile(dir, aclName)
+	if err != nil {
+		vlog.Errorf("Failed to open tmpfile data:%v", err)
+		return verror.Make(ErrOperationFailed, nil)
+	}
+	defer os.Remove(data.Name())
+	sig, err := ioutil.TempFile(dir, sigName)
+	if err != nil {
+		vlog.Errorf("Failed to open tmpfile sig:%v", err)
+		return verror.Make(ErrOperationFailed, nil)
+	}
+	defer os.Remove(sig.Name())
+	writer, err := serialization.NewSigningWriteCloser(data, sig, principal, nil)
+	if err != nil {
+		vlog.Errorf("Failed to create NewSigningWriteCloser:%v", err)
+		return verror.Make(ErrOperationFailed, nil)
+	}
+	if err = acl.WriteTo(writer); err != nil {
+		vlog.Errorf("Failed to SaveACL:%v", err)
+		return verror.Make(ErrOperationFailed, nil)
+	}
+	if err = writer.Close(); err != nil {
+		vlog.Errorf("Failed to Close() SigningWriteCloser:%v", err)
+		return verror.Make(ErrOperationFailed, nil)
+	}
+	if err := os.Rename(data.Name(), aclFile); err != nil {
+		vlog.Errorf("os.Rename() failed:%v", err)
+		return verror.Make(ErrOperationFailed, nil)
+	}
+	if err := os.Rename(sig.Name(), sigFile); err != nil {
+		vlog.Errorf("os.Rename() failed:%v", err)
+		return verror.Make(ErrOperationFailed, nil)
+	}
+	return nil
+}
diff --git a/services/mgmt/profile/profile.vdl b/services/mgmt/profile/profile.vdl
index 1e12ec8..63240ec 100644
--- a/services/mgmt/profile/profile.vdl
+++ b/services/mgmt/profile/profile.vdl
@@ -17,17 +17,17 @@
 // Specification is how we represent a profile internally. It should
 // provide enough information to allow matching of binaries to devices.
 type Specification struct {
-	// Arch is the target hardware architecture of the profile.
-	Arch        build.Architecture
+	// Label is a human-friendly concise label for the profile,
+	// e.g. "linux-media".
+	Label       string
 	// Description is a human-friendly description of the profile.
 	Description string
+	// Arch is the target hardware architecture of the profile.
+	Arch        build.Architecture
+	// OS is the target operating system of the profile.
+	OS          build.OperatingSystem
 	// Format is the file format supported by the profile.
 	Format      build.Format
 	// Libraries is a set of libraries the profile requires.
 	Libraries   set[Library]
-	// Label is a human-friendly concise label for the profile,
-	// e.g. "linux-media".
-	Label       string
-	// OS is the target operating system of the profile.
-	OS          build.OperatingSystem
 }
diff --git a/services/mgmt/profile/profile.vdl.go b/services/mgmt/profile/profile.vdl.go
index 8b50064..6db310d 100644
--- a/services/mgmt/profile/profile.vdl.go
+++ b/services/mgmt/profile/profile.vdl.go
@@ -30,19 +30,19 @@
 // Specification is how we represent a profile internally. It should
 // provide enough information to allow matching of binaries to devices.
 type Specification struct {
-	// Arch is the target hardware architecture of the profile.
-	Arch build.Architecture
+	// Label is a human-friendly concise label for the profile,
+	// e.g. "linux-media".
+	Label string
 	// Description is a human-friendly description of the profile.
 	Description string
+	// Arch is the target hardware architecture of the profile.
+	Arch build.Architecture
+	// OS is the target operating system of the profile.
+	OS build.OperatingSystem
 	// Format is the file format supported by the profile.
 	Format build.Format
 	// Libraries is a set of libraries the profile requires.
 	Libraries map[Library]struct{}
-	// Label is a human-friendly concise label for the profile,
-	// e.g. "linux-media".
-	Label string
-	// OS is the target operating system of the profile.
-	OS build.OperatingSystem
 }
 
 func (Specification) __VDLReflect(struct {
diff --git a/services/mgmt/profile/profiled/test.sh b/services/mgmt/profile/profiled/test.sh
index 756916d..685dfee 100755
--- a/services/mgmt/profile/profiled/test.sh
+++ b/services/mgmt/profile/profiled/test.sh
@@ -55,7 +55,7 @@
   OUTPUT=$(shell::tmp_file)
   "${PROFILE_BIN}" specification "${PROFILE}" | tee "${OUTPUT}" || shell_test::fail "line ${LINENO}: 'spec' failed"
   GOT=$(cat "${OUTPUT}")
-  WANT='profile.Specification{Arch:"amd64", Description:"Example profile to test the profile manager implementation.", Format:"ELF", Libraries:map[profile.Library]struct {}{profile.Library{Name:"foo", MajorVersion:"1", MinorVersion:"0"}:struct {}{}}, Label:"example", OS:"linux"}'
+  WANT='profile.Specification{Label:"example", Description:"Example profile to test the profile manager implementation.", Arch:"amd64", OS:"linux", Format:"ELF", Libraries:map[profile.Library]struct {}{profile.Library{Name:"foo", MajorVersion:"1", MinorVersion:"0"}:struct {}{}}}'
   shell_test::assert_eq "${GOT}" "${WANT}" "${LINENO}"
 
   # Remove the profile.
diff --git a/services/mgmt/repository/repository.vdl.go b/services/mgmt/repository/repository.vdl.go
index 75842f2..b320b6c 100644
--- a/services/mgmt/repository/repository.vdl.go
+++ b/services/mgmt/repository/repository.vdl.go
@@ -19,14 +19,8 @@
 	__context "v.io/core/veyron2/context"
 	__ipc "v.io/core/veyron2/ipc"
 	__vdlutil "v.io/core/veyron2/vdl/vdlutil"
-	__wiretype "v.io/core/veyron2/wiretype"
 )
 
-// TODO(toddw): Remove this line once the new signature support is done.
-// It corrects a bug where __wiretype is unused in VDL pacakges where only
-// bootstrap types are used on interfaces.
-const _ = __wiretype.TypeIDInvalid
-
 // ApplicationClientMethods is the client interface
 // containing Application methods.
 //
@@ -112,17 +106,6 @@
 	return
 }
 
-func (c implApplicationClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&o0, &err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
 // ApplicationServerMethods is the interface a server writer
 // implements for Application.
 //
@@ -166,8 +149,6 @@
 	ApplicationServerStubMethods
 	// Describe the Application interfaces.
 	Describe__() []__ipc.InterfaceDesc
-	// Signature will be replaced with Describe__.
-	Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
 }
 
 // ApplicationServer returns a server stub for Application.
@@ -248,97 +229,6 @@
 	},
 }
 
-func (s implApplicationServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
-	// TODO(toddw): Replace with new Describe__ implementation.
-	result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
-	result.Methods["Put"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "Profiles", Type: 61},
-			{Name: "Envelope", Type: 66},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 67},
-		},
-	}
-	result.Methods["Remove"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "Profile", Type: 3},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 67},
-		},
-	}
-
-	result.TypeDefs = []__vdlutil.Any{
-		__wiretype.MapType{Key: 0x3, Elem: 0x3, Name: "", Tags: []string(nil)}, __wiretype.StructType{
-			[]__wiretype.FieldType{
-				__wiretype.FieldType{Type: 0x3, Name: "Title"},
-				__wiretype.FieldType{Type: 0x3d, Name: "Args"},
-				__wiretype.FieldType{Type: 0x3, Name: "Binary"},
-				__wiretype.FieldType{Type: 0x3d, Name: "Env"},
-				__wiretype.FieldType{Type: 0x41, Name: "Packages"},
-			},
-			"v.io/core/veyron2/services/mgmt/application.Envelope", []string(nil)},
-		__wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
-	var ss __ipc.ServiceSignature
-	var firstAdded int
-	ss, _ = s.ApplicationServerStub.Signature(ctx)
-	firstAdded = len(result.TypeDefs)
-	for k, v := range ss.Methods {
-		for i, _ := range v.InArgs {
-			if v.InArgs[i].Type >= __wiretype.TypeIDFirst {
-				v.InArgs[i].Type += __wiretype.TypeID(firstAdded)
-			}
-		}
-		for i, _ := range v.OutArgs {
-			if v.OutArgs[i].Type >= __wiretype.TypeIDFirst {
-				v.OutArgs[i].Type += __wiretype.TypeID(firstAdded)
-			}
-		}
-		if v.InStream >= __wiretype.TypeIDFirst {
-			v.InStream += __wiretype.TypeID(firstAdded)
-		}
-		if v.OutStream >= __wiretype.TypeIDFirst {
-			v.OutStream += __wiretype.TypeID(firstAdded)
-		}
-		result.Methods[k] = v
-	}
-	//TODO(bprosnitz) combine type definitions from embeded interfaces in a way that doesn't cause duplication.
-	for _, d := range ss.TypeDefs {
-		switch wt := d.(type) {
-		case __wiretype.SliceType:
-			if wt.Elem >= __wiretype.TypeIDFirst {
-				wt.Elem += __wiretype.TypeID(firstAdded)
-			}
-			d = wt
-		case __wiretype.ArrayType:
-			if wt.Elem >= __wiretype.TypeIDFirst {
-				wt.Elem += __wiretype.TypeID(firstAdded)
-			}
-			d = wt
-		case __wiretype.MapType:
-			if wt.Key >= __wiretype.TypeIDFirst {
-				wt.Key += __wiretype.TypeID(firstAdded)
-			}
-			if wt.Elem >= __wiretype.TypeIDFirst {
-				wt.Elem += __wiretype.TypeID(firstAdded)
-			}
-			d = wt
-		case __wiretype.StructType:
-			for i, fld := range wt.Fields {
-				if fld.Type >= __wiretype.TypeIDFirst {
-					wt.Fields[i].Type += __wiretype.TypeID(firstAdded)
-				}
-			}
-			d = wt
-			// NOTE: other types are missing, but we are upgrading anyways.
-		}
-		result.TypeDefs = append(result.TypeDefs, d)
-	}
-
-	return result, nil
-}
-
 // ProfileClientMethods is the client interface
 // containing Profile methods.
 //
@@ -425,17 +315,6 @@
 	return
 }
 
-func (c implProfileClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&o0, &err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
 // ProfileServerMethods is the interface a server writer
 // implements for Profile.
 //
@@ -469,8 +348,6 @@
 	ProfileServerStubMethods
 	// Describe the Profile interfaces.
 	Describe__() []__ipc.InterfaceDesc
-	// Signature will be replaced with Describe__.
-	Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
 }
 
 // ProfileServer returns a server stub for Profile.
@@ -559,106 +436,3 @@
 		},
 	},
 }
-
-func (s implProfileServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
-	// TODO(toddw): Replace with new Describe__ implementation.
-	result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
-	result.Methods["Put"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "Specification", Type: 70},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 71},
-		},
-	}
-	result.Methods["Remove"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 71},
-		},
-	}
-	result.Methods["Specification"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 70},
-			{Name: "", Type: 71},
-		},
-	}
-
-	result.TypeDefs = []__vdlutil.Any{
-		__wiretype.NamedPrimitiveType{Type: 0x3, Name: "v.io/core/veyron2/services/mgmt/build.Architecture", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x3, Name: "v.io/core/veyron2/services/mgmt/build.Format", Tags: []string(nil)}, __wiretype.StructType{
-			[]__wiretype.FieldType{
-				__wiretype.FieldType{Type: 0x3, Name: "Name"},
-				__wiretype.FieldType{Type: 0x3, Name: "MajorVersion"},
-				__wiretype.FieldType{Type: 0x3, Name: "MinorVersion"},
-			},
-			"v.io/core/veyron/services/mgmt/profile.Library", []string(nil)},
-		__wiretype.MapType{Key: 0x43, Elem: 0x2, Name: "", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x3, Name: "v.io/core/veyron2/services/mgmt/build.OperatingSystem", Tags: []string(nil)}, __wiretype.StructType{
-			[]__wiretype.FieldType{
-				__wiretype.FieldType{Type: 0x41, Name: "Arch"},
-				__wiretype.FieldType{Type: 0x3, Name: "Description"},
-				__wiretype.FieldType{Type: 0x42, Name: "Format"},
-				__wiretype.FieldType{Type: 0x44, Name: "Libraries"},
-				__wiretype.FieldType{Type: 0x3, Name: "Label"},
-				__wiretype.FieldType{Type: 0x45, Name: "OS"},
-			},
-			"v.io/core/veyron/services/mgmt/profile.Specification", []string(nil)},
-		__wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
-	var ss __ipc.ServiceSignature
-	var firstAdded int
-	ss, _ = s.ProfileServerStub.Signature(ctx)
-	firstAdded = len(result.TypeDefs)
-	for k, v := range ss.Methods {
-		for i, _ := range v.InArgs {
-			if v.InArgs[i].Type >= __wiretype.TypeIDFirst {
-				v.InArgs[i].Type += __wiretype.TypeID(firstAdded)
-			}
-		}
-		for i, _ := range v.OutArgs {
-			if v.OutArgs[i].Type >= __wiretype.TypeIDFirst {
-				v.OutArgs[i].Type += __wiretype.TypeID(firstAdded)
-			}
-		}
-		if v.InStream >= __wiretype.TypeIDFirst {
-			v.InStream += __wiretype.TypeID(firstAdded)
-		}
-		if v.OutStream >= __wiretype.TypeIDFirst {
-			v.OutStream += __wiretype.TypeID(firstAdded)
-		}
-		result.Methods[k] = v
-	}
-	//TODO(bprosnitz) combine type definitions from embeded interfaces in a way that doesn't cause duplication.
-	for _, d := range ss.TypeDefs {
-		switch wt := d.(type) {
-		case __wiretype.SliceType:
-			if wt.Elem >= __wiretype.TypeIDFirst {
-				wt.Elem += __wiretype.TypeID(firstAdded)
-			}
-			d = wt
-		case __wiretype.ArrayType:
-			if wt.Elem >= __wiretype.TypeIDFirst {
-				wt.Elem += __wiretype.TypeID(firstAdded)
-			}
-			d = wt
-		case __wiretype.MapType:
-			if wt.Key >= __wiretype.TypeIDFirst {
-				wt.Key += __wiretype.TypeID(firstAdded)
-			}
-			if wt.Elem >= __wiretype.TypeIDFirst {
-				wt.Elem += __wiretype.TypeID(firstAdded)
-			}
-			d = wt
-		case __wiretype.StructType:
-			for i, fld := range wt.Fields {
-				if fld.Type >= __wiretype.TypeIDFirst {
-					wt.Fields[i].Type += __wiretype.TypeID(firstAdded)
-				}
-			}
-			d = wt
-			// NOTE: other types are missing, but we are upgrading anyways.
-		}
-		result.TypeDefs = append(result.TypeDefs, d)
-	}
-
-	return result, nil
-}
diff --git a/services/mgmt/sysinit/init_darwin.go b/services/mgmt/sysinit/init_darwin.go
new file mode 100644
index 0000000..e56e07f
--- /dev/null
+++ b/services/mgmt/sysinit/init_darwin.go
@@ -0,0 +1,11 @@
+package sysinit
+
+func InitSystem() string {
+	panic("Darwin not supported yet")
+	return ""
+}
+
+func New(system string, sd *ServiceDescription) InstallSystemInit {
+	panic("Darwin not supported yet")
+	return nil
+}
diff --git a/services/mgmt/sysinit/init_linux.go b/services/mgmt/sysinit/init_linux.go
index beacc8e..e6da324 100644
--- a/services/mgmt/sysinit/init_linux.go
+++ b/services/mgmt/sysinit/init_linux.go
@@ -1,6 +1,3 @@
-//
-// +build linux
-
 package sysinit
 
 // TODO(cnicolaou): will need to figure out a simple of way of handling the
@@ -13,22 +10,35 @@
 	"log"
 	"os"
 	"os/exec"
+	"syscall"
 )
 
 // action is a var so we can override it for testing.
 var action = func(command, action, service string) error {
-	output, err := exec.Command(command, action, service).CombinedOutput()
-	log.Printf("%s output: for %s %s: %s\n",
-		command, action, service, output)
+	cmd := exec.Command(command, action, service)
+	if os.Geteuid() == 0 && os.Getuid() > 0 {
+		// Set uid to root (e.g. when running from a suid binary),
+		// otherwise initctl doesn't work.
+		sysProcAttr := new(syscall.SysProcAttr)
+		sysProcAttr.Credential = new(syscall.Credential)
+		sysProcAttr.Credential.Gid = uint32(0)
+		sysProcAttr.Credential.Uid = uint32(0)
+		cmd.SysProcAttr = sysProcAttr
+	}
+	// Clear env.  In particular, initctl doesn't like USER being set to
+	// something other than root.
+	cmd.Env = []string{}
+	output, err := cmd.CombinedOutput()
+	log.Printf("%s output: for %s %s: %s\n", command, action, service, output)
 	return err
 }
 
 var (
 	upstartDir        = "/etc/init"
+	upstartBin        = "/sbin/initctl"
 	systemdDir        = "/usr/lib/systemd/system"
 	systemdTmpFileDir = "/usr/lib/tmpfiles.d"
 	dockerDir         = "/home/veyron/init"
-	logDir            = "/var/log/veyron"
 )
 
 // InitSystem attempts to determine what kind of init system is in use on
@@ -46,7 +56,7 @@
 	if fi, err := os.Stat("/home/veyron/init"); err == nil && fi.Mode().IsDir() {
 		return "docker"
 	}
-	if fi, err := os.Stat("/sbin/initctl"); err == nil {
+	if fi, err := os.Stat(upstartBin); err == nil {
 		if (fi.Mode() & os.ModePerm & 0100) != 0 {
 			return "upstart"
 		}
@@ -64,6 +74,21 @@
 	return ""
 }
 
+// New returns the appropriate implementation of InstallSystemInit for the
+// underlying system.
+func New(system string, sd *ServiceDescription) InstallSystemInit {
+	switch system {
+	case "docker":
+		return (*DockerService)(sd)
+	case "upstart":
+		return (*UpstartService)(sd)
+	case "systemd":
+		return (*SystemdService)(sd)
+	default:
+		return nil
+	}
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // Upstart support
 
@@ -101,19 +126,13 @@
 
 script
   set -e
-  #  setuid {{.User}} - causes the subsequent exec to fail for unknown reasons.
   echo '{{.Service}} starting'
-  exec{{range $cmd := .Command}} {{$cmd}}{{end}}
+  exec sudo -u {{.User}} {{range $cmd := .Command}} {{$cmd}}{{end}}
 end script
 `
 
-// Install implements the InstallSystemInit method.
+// Implements the InstallSystemInit method.
 func (u *UpstartService) Install() error {
-	if u.Setup != nil {
-		if err := u.Setup((*ServiceDescription)(u)); err != nil {
-			return err
-		}
-	}
 	file := fmt.Sprintf("%s/%s.conf", upstartDir, u.Service)
 	return (*ServiceDescription)(u).writeTemplate(upstartTemplate, file)
 }
@@ -123,23 +142,24 @@
 	return (*ServiceDescription)(u).writeTemplate(upstartTemplate, "")
 }
 
-// Uninstall implements the InstallSystemInit method.
+// Implements the InstallSystemInit method.
 func (u *UpstartService) Uninstall() error {
-	if err := u.Stop(); err != nil {
-		return err
-	}
+	// For now, ignore any errors returned by Stop, since Stop complains
+	// when there is no instance to stop.
+	// TODO(caprita): Only call Stop if there are running instances.
+	u.Stop()
 	file := fmt.Sprintf("%s/%s.conf", upstartDir, u.Service)
 	return os.Remove(file)
 }
 
 // Start implements the InstallSystemInit method.
 func (u *UpstartService) Start() error {
-	return action("initctl", "start", u.Service)
+	return action(upstartBin, "start", u.Service)
 }
 
 // Stop implements the InstallSystemInit method.
 func (u *UpstartService) Stop() error {
-	return action("initctl", "stop", u.Service)
+	return action(upstartBin, "stop", u.Service)
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -174,11 +194,6 @@
 
 // Install implements the InstallSystemInit method.
 func (s *SystemdService) Install() error {
-	if s.Setup != nil {
-		if err := s.Setup((*ServiceDescription)(s)); err != nil {
-			return err
-		}
-	}
 	file := fmt.Sprintf("%s/%s.service", systemdDir, s.Service)
 	if err := (*ServiceDescription)(s).writeTemplate(systemdTemplate, file); err != nil {
 		return err
@@ -253,11 +268,6 @@
 
 // Install implements the InstallSystemInit method.
 func (s *DockerService) Install() error {
-	if s.Setup != nil {
-		if err := s.Setup((*ServiceDescription)(s)); err != nil {
-			return err
-		}
-	}
 	file := fmt.Sprintf("%s/%s.sh", dockerDir, s.Service)
 	if err := (*ServiceDescription)(s).writeTemplate(dockerTemplate, file); err != nil {
 		return err
diff --git a/services/mgmt/sysinit/linux_test.go b/services/mgmt/sysinit/linux_test.go
index a926229..d21634e 100644
--- a/services/mgmt/sysinit/linux_test.go
+++ b/services/mgmt/sysinit/linux_test.go
@@ -30,23 +30,15 @@
 	}()
 
 	defer os.RemoveAll(upstartDir)
-	serviceName := ""
 	u := &UpstartService{
 		Service:     "tester",
 		Description: "my test",
 		Binary:      "/bin/echo",
 		Command:     []string{"/bin/echo -n foo"},
-		Setup: func(s *ServiceDescription) error {
-			serviceName = s.Service
-			return nil
-		},
 	}
 	if err := u.Install(); err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
-	if serviceName != "tester" {
-		t.Errorf("Setup was not called")
-	}
 	rc, _ := os.Open(upstartDir + "/tester.conf")
 	lines := bufio.NewScanner(rc)
 	lines.Scan()
diff --git a/services/mgmt/sysinit/service_description.go b/services/mgmt/sysinit/service_description.go
index 925c8c1..ba1150d 100644
--- a/services/mgmt/sysinit/service_description.go
+++ b/services/mgmt/sysinit/service_description.go
@@ -1,6 +1,9 @@
 package sysinit
 
 import (
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
 	"os"
 	"text/template"
 	"time"
@@ -11,14 +14,37 @@
 // ServiceDescription is a generic service description that represents the
 // common configuration details for specific systems.
 type ServiceDescription struct {
-	Service     string                          // The name of the Service
-	Description string                          // A description of the Service
-	Environment map[string]string               // Environment variables needed by the service
-	Binary      string                          // The binary to be run
-	Command     []string                        // The script/binary and command line options to use to start/stop the binary
-	User        string                          // The username this service is to run as
-	Setup       func(*ServiceDescription) error // Optional function to run before install.
-	SetupParams map[string]string               // Params for the Setup function.
+	Service     string            // The name of the Service
+	Description string            // A description of the Service
+	Environment map[string]string // Environment variables needed by the service
+	Binary      string            // The binary to be run
+	Command     []string          // The script/binary and command line options to use to start/stop the binary
+	User        string            // The username this service is to run as
+}
+
+// TODO(caprita): Unit test.
+
+// SaveTo serializes the service description object to a file.
+func (sd *ServiceDescription) SaveTo(fName string) error {
+	jsonSD, err := json.Marshal(sd)
+	if err != nil {
+		return fmt.Errorf("Marshal(%v) failed: %v", sd, err)
+	}
+	if err := ioutil.WriteFile(fName, jsonSD, 0600); err != nil {
+		return fmt.Errorf("WriteFile(%v) failed: %v", fName, err)
+	}
+	return nil
+}
+
+// LoadFrom de-serializes the service description object from a file created by
+// SaveTo.
+func (sd *ServiceDescription) LoadFrom(fName string) error {
+	if sdBytes, err := ioutil.ReadFile(fName); err != nil {
+		return fmt.Errorf("ReadFile(%v) failed: %v", fName, err)
+	} else if err := json.Unmarshal(sdBytes, sd); err != nil {
+		return fmt.Errorf("Unmarshal(%v) failed: %v", sdBytes, err)
+	}
+	return nil
 }
 
 func (sd *ServiceDescription) writeTemplate(templateContents, file string) error {
diff --git a/services/mounttable/lib/collection_test_interface.vdl.go b/services/mounttable/lib/collection_test_interface.vdl.go
index 621160f..612f212 100644
--- a/services/mounttable/lib/collection_test_interface.vdl.go
+++ b/services/mounttable/lib/collection_test_interface.vdl.go
@@ -8,15 +8,8 @@
 	__veyron2 "v.io/core/veyron2"
 	__context "v.io/core/veyron2/context"
 	__ipc "v.io/core/veyron2/ipc"
-	__vdlutil "v.io/core/veyron2/vdl/vdlutil"
-	__wiretype "v.io/core/veyron2/wiretype"
 )
 
-// TODO(toddw): Remove this line once the new signature support is done.
-// It corrects a bug where __wiretype is unused in VDL pacakges where only
-// bootstrap types are used on interfaces.
-const _ = __wiretype.TypeIDInvalid
-
 // CollectionClientMethods is the client interface
 // containing Collection methods.
 type CollectionClientMethods interface {
@@ -81,17 +74,6 @@
 	return
 }
 
-func (c implCollectionClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&o0, &err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
 // CollectionServerMethods is the interface a server writer
 // implements for Collection.
 type CollectionServerMethods interface {
@@ -116,8 +98,6 @@
 	CollectionServerStubMethods
 	// Describe the Collection interfaces.
 	Describe__() []__ipc.InterfaceDesc
-	// Signature will be replaced with Describe__.
-	Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
 }
 
 // CollectionServer returns a server stub for Collection.
@@ -187,29 +167,3 @@
 		},
 	},
 }
-
-func (s implCollectionServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
-	// TODO(toddw): Replace with new Describe__ implementation.
-	result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
-	result.Methods["Export"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "Val", Type: 3},
-			{Name: "Overwrite", Type: 2},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 65},
-		},
-	}
-	result.Methods["Lookup"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 67},
-			{Name: "", Type: 65},
-		},
-	}
-
-	result.TypeDefs = []__vdlutil.Any{
-		__wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x32, Name: "byte", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x42, Name: "", Tags: []string(nil)}}
-
-	return result, nil
-}
diff --git a/services/mounttable/lib/mounttable.go b/services/mounttable/lib/mounttable.go
index 335aa11..9280527 100644
--- a/services/mounttable/lib/mounttable.go
+++ b/services/mounttable/lib/mounttable.go
@@ -371,28 +371,13 @@
 
 // ResolveStep returns the next server in a resolution, the name remaining below that server,
 // and whether or not that server is another mount table.
-func (ms *mountContext) ResolveStep(ctx ipc.ServerContext) (servers []naming.VDLMountedServer, suffix string, err error) {
-	vlog.VI(2).Infof("ResolveStep %q", ms.name)
-	mt := ms.mt
-	// Find the next mount point for the name.
-	n, elems, err := mt.findMountPoint(ctx, ms.elems)
-	if err != nil {
-		return nil, "", err
-	}
-	if n == nil {
-		if len(ms.elems) == 0 {
-			return nil, ms.name, verror2.Make(naming.ErrNoSuchNameRoot, ctx.Context(), ms.name)
-		}
-		return nil, ms.name, verror2.Make(naming.ErrNoSuchName, ctx.Context(), ms.name)
-	}
-	n.parent.Unlock()
-	defer n.Unlock()
-	return n.mount.servers.copyToSlice(), strings.Join(elems, "/"), nil
+func (ms *mountContext) ResolveStepX(ctx ipc.ServerContext) (entry naming.VDLMountEntry, err error) {
+	return ms.ResolveStep(ctx)
 }
 
-// ResolveStepX returns the next server in a resolution in the form of a MountEntry.  The name
+// ResolveStep returns the next server in a resolution in the form of a MountEntry.  The name
 // in the mount entry is the name relative to the server's root.
-func (ms *mountContext) ResolveStepX(ctx ipc.ServerContext) (entry naming.VDLMountEntry, err error) {
+func (ms *mountContext) ResolveStep(ctx ipc.ServerContext) (entry naming.VDLMountEntry, err error) {
 	vlog.VI(2).Infof("ResolveStep %q", ms.name)
 	mt := ms.mt
 	// Find the next mount point for the name.
diff --git a/services/mounttable/lib/mounttable_test.go b/services/mounttable/lib/mounttable_test.go
index ba228b8..85cb3ff 100644
--- a/services/mounttable/lib/mounttable_test.go
+++ b/services/mounttable/lib/mounttable_test.go
@@ -185,7 +185,7 @@
 func resolve(ctx *context.T, name string) (string, error) {
 	// Resolve the name one level.
 	client := veyron2.GetClient(ctx)
-	call, err := client.StartCall(ctx, name, "ResolveStepX", nil, options.NoResolve{})
+	call, err := client.StartCall(ctx, name, "ResolveStep", nil, options.NoResolve{})
 	if err != nil {
 		return "", err
 	}
diff --git a/services/mounttable/lib/neighborhood.go b/services/mounttable/lib/neighborhood.go
index 32e6193..0f9103e 100644
--- a/services/mounttable/lib/neighborhood.go
+++ b/services/mounttable/lib/neighborhood.go
@@ -206,25 +206,13 @@
 	return neighbors
 }
 
-// ResolveStep implements ResolveStep
-func (ns *neighborhoodService) ResolveStep(ctx ipc.ServerContext) (servers []naming.VDLMountedServer, suffix string, err error) {
-	nh := ns.nh
-	vlog.VI(2).Infof("ResolveStep %v\n", ns.elems)
-	if len(ns.elems) == 0 {
-		//nothing can be mounted at the root
-		return nil, "", verror.Make(naming.ErrNoSuchNameRoot, ctx.Context(), ns.elems)
-	}
-
-	// We can only resolve the first element and it always refers to a mount table (for now).
-	neighbor := nh.neighbor(ns.elems[0])
-	if neighbor == nil {
-		return nil, "", verror.Make(naming.ErrNoSuchName, ctx.Context(), ns.elems)
-	}
-	return neighbor, naming.Join(ns.elems[1:]...), nil
-}
-
 // ResolveStepX implements ResolveStepX
 func (ns *neighborhoodService) ResolveStepX(ctx ipc.ServerContext) (entry naming.VDLMountEntry, err error) {
+	return ns.ResolveStep(ctx)
+}
+
+// ResolveStep implements ResolveStep
+func (ns *neighborhoodService) ResolveStep(ctx ipc.ServerContext) (entry naming.VDLMountEntry, err error) {
 	nh := ns.nh
 	vlog.VI(2).Infof("ResolveStep %v\n", ns.elems)
 	if len(ns.elems) == 0 {
diff --git a/services/mounttable/lib/neighborhood_test.go b/services/mounttable/lib/neighborhood_test.go
index 7b48e53..6f197d6 100644
--- a/services/mounttable/lib/neighborhood_test.go
+++ b/services/mounttable/lib/neighborhood_test.go
@@ -83,13 +83,13 @@
 
 	client := veyron2.GetClient(rootCtx)
 	name := naming.JoinAddressName(estr, serverName+"/"+expectedSuffix)
-	call, cerr := client.StartCall(rootCtx, name, "ResolveStepX", nil, options.NoResolve{})
+	call, cerr := client.StartCall(rootCtx, name, "ResolveStep", nil, options.NoResolve{})
 	if cerr != nil {
-		boom(t, "ResolveStepX.StartCall: %s", cerr)
+		boom(t, "ResolveStep.StartCall: %s", cerr)
 	}
 	var entry naming.VDLMountEntry
 	if cerr = call.Finish(&entry, &err); cerr != nil {
-		boom(t, "ResolveStepX: %s", cerr)
+		boom(t, "ResolveStep: %s", cerr)
 	}
 
 	// Resolution returned something.  Make sure its correct.
diff --git a/services/security/discharger.vdl.go b/services/security/discharger.vdl.go
index c98b9b6..46805eb 100644
--- a/services/security/discharger.vdl.go
+++ b/services/security/discharger.vdl.go
@@ -11,14 +11,8 @@
 	__context "v.io/core/veyron2/context"
 	__ipc "v.io/core/veyron2/ipc"
 	__vdlutil "v.io/core/veyron2/vdl/vdlutil"
-	__wiretype "v.io/core/veyron2/wiretype"
 )
 
-// TODO(toddw): Remove this line once the new signature support is done.
-// It corrects a bug where __wiretype is unused in VDL pacakges where only
-// bootstrap types are used on interfaces.
-const _ = __wiretype.TypeIDInvalid
-
 // DischargerClientMethods is the client interface
 // containing Discharger methods.
 //
@@ -75,17 +69,6 @@
 	return
 }
 
-func (c implDischargerClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&o0, &err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
 // DischargerServerMethods is the interface a server writer
 // implements for Discharger.
 //
@@ -113,8 +96,6 @@
 	DischargerServerStubMethods
 	// Describe the Discharger interfaces.
 	Describe__() []__ipc.InterfaceDesc
-	// Signature will be replaced with Describe__.
-	Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
 }
 
 // DischargerServer returns a server stub for Discharger.
@@ -174,30 +155,3 @@
 		},
 	},
 }
-
-func (s implDischargerServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
-	// TODO(toddw): Replace with new Describe__ implementation.
-	result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
-	result.Methods["Discharge"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "Caveat", Type: 65},
-			{Name: "Impetus", Type: 69},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "Discharge", Type: 65},
-			{Name: "err", Type: 70},
-		},
-	}
-
-	result.TypeDefs = []__vdlutil.Any{
-		__wiretype.NamedPrimitiveType{Type: 0x1, Name: "anydata", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x3, Name: "v.io/core/veyron2/security.BlessingPattern", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x42, Name: "", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x41, Name: "", Tags: []string(nil)}, __wiretype.StructType{
-			[]__wiretype.FieldType{
-				__wiretype.FieldType{Type: 0x43, Name: "Server"},
-				__wiretype.FieldType{Type: 0x3, Name: "Method"},
-				__wiretype.FieldType{Type: 0x44, Name: "Arguments"},
-			},
-			"v.io/core/veyron2/security.DischargeImpetus", []string(nil)},
-		__wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
-
-	return result, nil
-}
diff --git a/tools/mgmt/device/devicex b/tools/mgmt/device/devicex
index 813d842..17fc8ea 100755
--- a/tools/mgmt/device/devicex
+++ b/tools/mgmt/device/devicex
@@ -29,7 +29,7 @@
   echo "VANADIUM_DEVICE_DIR=<installation dir> ./devicex stop"
 }
 
-readonly BIN_NAMES=(deviced suidhelper agentd)
+readonly BIN_NAMES=(deviced suidhelper agentd inithelper)
 
 ###############################################################################
 # Copies one binary from source to destination.
@@ -153,25 +153,31 @@
   echo "Binaries are in ${BIN_INSTALL}."
 
   # Set up the suidhelper.
-  echo "Configuring suidhelper ..."
-  local -r SETUID_SCRIPT="${BIN_INSTALL}/suidhelper"
+  echo "Configuring helpers ..."
   local SINGLE_USER=false
+  local INIT_MODE=false
   for ARG in $*; do
     if [[ ${ARG} = "--" ]]; then
       break
-    elif [[ ${ARG} = "--single_user" ]]; then
+    elif [[ ${ARG} = "--single_user" || ${ARG} = "--single_user=true" ]]; then
       SINGLE_USER=true
-      break
+    elif [[ ${ARG} = "--init_mode" || ${ARG} = "--init_mode=true" ]]; then
+      INIT_MODE=true
     fi
   done
+  local -r SETUID_SCRIPT="${BIN_INSTALL}/suidhelper"
   if [[ ${SINGLE_USER} == false ]]; then
     sudo bash -c "chown root:root \"${SETUID_SCRIPT}\"; chmod 4551 \"${SETUID_SCRIPT}\""
   fi
-  echo "Suidhelper configured."
+  local -r INIT_SCRIPT="${BIN_INSTALL}/inithelper"
+  if [[ ${INIT_MODE} == true ]]; then
+    sudo bash -c "chown root:root \"${INIT_SCRIPT}\"; chmod 4551 \"${INIT_SCRIPT}\""
+  fi
+  echo "Helpers configured."
 
   # Install the device manager.
   echo "Installing device manager under ${VANADIUM_DEVICE_DIR} ..."
-  "${BIN_INSTALL}/deviced" install --suid_helper="${SETUID_SCRIPT}" --agent="${BIN_INSTALL}/agentd" "$@"
+  "${BIN_INSTALL}/deviced" install --suid_helper="${SETUID_SCRIPT}" --agent="${BIN_INSTALL}/agentd" --init_helper="${INIT_SCRIPT}" "$@"
   echo "Device manager installed."
 }
 
diff --git a/tools/mgmt/device/impl.go b/tools/mgmt/device/impl.go
index fced994..9a6aaf9 100644
--- a/tools/mgmt/device/impl.go
+++ b/tools/mgmt/device/impl.go
@@ -102,6 +102,29 @@
 	return nil
 }
 
+var cmdDescribe = &cmdline.Command{
+	Run:      runDescribe,
+	Name:     "describe",
+	Short:    "Describe the device.",
+	Long:     "Describe the device.",
+	ArgsName: "<device>",
+	ArgsLong: `
+<device> is the veyron object name of the device manager's app service.`,
+}
+
+func runDescribe(cmd *cmdline.Command, args []string) error {
+	if expected, got := 1, len(args); expected != got {
+		return cmd.UsageErrorf("describe: incorrect number of arguments, expected %d, got %d", expected, got)
+	}
+	deviceName := args[0]
+	if description, err := device.DeviceClient(deviceName).Describe(gctx); err != nil {
+		return fmt.Errorf("Describe failed: %v", err)
+	} else {
+		fmt.Fprintf(cmd.Stdout(), "%+v\n", description)
+	}
+	return nil
+}
+
 func root() *cmdline.Command {
 	return &cmdline.Command{
 		Name:  "device",
@@ -109,6 +132,6 @@
 		Long: `
 The device tool facilitates interaction with the veyron device manager.
 `,
-		Children: []*cmdline.Command{cmdInstall, cmdStart, associateRoot(), cmdClaim, cmdStop, cmdSuspend, cmdResume, aclRoot()},
+		Children: []*cmdline.Command{cmdInstall, cmdStart, associateRoot(), cmdDescribe, cmdClaim, cmdStop, cmdSuspend, cmdResume, aclRoot()},
 	}
 }
diff --git a/tools/mgmt/test.sh b/tools/mgmt/test.sh
index 7c52a27..c42fa1d 100755
--- a/tools/mgmt/test.sh
+++ b/tools/mgmt/test.sh
@@ -16,6 +16,7 @@
   APPLICATION_BIN="$(shell_test::build_go_binary 'v.io/core/veyron/tools/application')"
   AGENTD_BIN="$(shell_test::build_go_binary 'v.io/core/veyron/security/agent/agentd')"
   SUIDHELPER_BIN="$(shell_test::build_go_binary 'v.io/core/veyron/services/mgmt/suidhelper')"
+  INITHELPER_BIN="$(shell_test::build_go_binary 'v.io/core/veyron/services/mgmt/inithelper')"
   DEVICEMANAGER_BIN="$(shell_test::build_go_binary 'v.io/core/veyron/services/mgmt/device/deviced')"
   DEVICE_BIN="$(shell_test::build_go_binary 'v.io/core/veyron/tools/mgmt/device')"
   NAMESPACE_BIN="$(shell_test::build_go_binary 'v.io/core/veyron/tools/namespace')"
@@ -86,7 +87,7 @@
   build
 
   BIN_STAGING_DIR=$(shell::tmp_dir)
-  cp "${AGENTD_BIN}" "${SUIDHELPER_BIN}" "${DEVICEMANAGER_BIN}" "${BIN_STAGING_DIR}"
+  cp "${AGENTD_BIN}" "${SUIDHELPER_BIN}" "${INITHELPER_BIN}" "${DEVICEMANAGER_BIN}" "${BIN_STAGING_DIR}"
   shell_test::setup_server_test
 
   # TODO(caprita): Expose an option to turn --single_user off, so we can run
@@ -122,6 +123,9 @@
   shell_test::assert_eq "$("${DEBUG_BIN}" stats read "${DM_NAME}/__debug/stats/security/principal/blessingstore" | head -1 | sed -e 's/^.*Default blessings: '//)" \
     "alice/myworkstation" "${LINENO}"
 
+  # Get the device's profile.
+  local -r DEVICE_PROFILE=$("${DEVICE_BIN}" describe "${DM_NAME}/device" | sed -e 's/{Profiles:map\[\(.*\):{}]}/\1/')
+
   # Start a binary server under the blessing "alice/myworkstation/binaryd" so that
   # the device ("alice/myworkstation") can talk to it.
   local -r BINARYD_NAME="binaryd"
@@ -149,10 +153,10 @@
   local -r SAMPLE_APP_NAME="${APPLICATIOND_NAME}/testapp/v0"
   local -r APP_PUBLISH_NAME="testbinaryd"
   echo "{\"Title\":\"BINARYD\", \"Args\":[\"--name=${APP_PUBLISH_NAME}\", \"--root_dir=./binstore\", \"--veyron.tcp.address=127.0.0.1:0\"], \"Binary\":\"${SAMPLE_APP_BIN_NAME}\", \"Env\":[]}" > ./app.envelope && \
-    "${APPLICATION_BIN}" put "${SAMPLE_APP_NAME}" test ./app.envelope && rm ./app.envelope
+    "${APPLICATION_BIN}" put "${SAMPLE_APP_NAME}" "${DEVICE_PROFILE}" ./app.envelope && rm ./app.envelope
 
   # Verify that the envelope we uploaded shows up with glob.
-  shell_test::assert_eq "$("${APPLICATION_BIN}" match "${SAMPLE_APP_NAME}" test | grep Title | sed -e 's/^.*"Title": "'// | sed -e 's/",//')" \
+  shell_test::assert_eq "$("${APPLICATION_BIN}" match "${SAMPLE_APP_NAME}" "${DEVICE_PROFILE}" | grep Title | sed -e 's/^.*"Title": "'// | sed -e 's/",//')" \
     "BINARYD" "${LINENO}"
 
   # Install the app on the device.
diff --git a/tools/mgmt/vbash b/tools/mgmt/vbash
index ea5047f..92c5c4d 100755
--- a/tools/mgmt/vbash
+++ b/tools/mgmt/vbash
@@ -191,7 +191,6 @@
 default_blessing() {
   "${BIN_INSTALL}/principal" dump | grep "Default blessings" | sed -e 's/Default blessings: //'
 }
-export PATH="${PATH}:${BIN_INSTALL}"
 export PS1="\${PS1}(\${GREENBOLD}\$(default_blessing)\[\033[0m\])$ "
 EOF
 
diff --git a/tools/mounttable/impl.go b/tools/mounttable/impl.go
index be3df84..d949dab 100644
--- a/tools/mounttable/impl.go
+++ b/tools/mounttable/impl.go
@@ -172,7 +172,7 @@
 	ctx, cancel := context.WithTimeout(runtime.NewContext(), time.Minute)
 	defer cancel()
 	client := veyron2.GetClient(ctx)
-	call, err := client.StartCall(ctx, args[0], "ResolveStepX", []interface{}{}, options.NoResolve{})
+	call, err := client.StartCall(ctx, args[0], "ResolveStep", []interface{}{}, options.NoResolve{})
 	if err != nil {
 		return err
 	}
diff --git a/tools/mounttable/impl_test.go b/tools/mounttable/impl_test.go
index f4c6d75..d5026d8 100644
--- a/tools/mounttable/impl_test.go
+++ b/tools/mounttable/impl_test.go
@@ -41,10 +41,10 @@
 	return nil
 }
 
-func (s *server) ResolveStep(ipc.ServerContext) (servers []naming.VDLMountedServer, suffix string, err error) {
+func (s *server) ResolveStep(ipc.ServerContext) (entry naming.VDLMountEntry, err error) {
 	vlog.VI(2).Infof("ResolveStep() was called. suffix=%v", s.suffix)
-	servers = []naming.VDLMountedServer{{"server1", 123}}
-	suffix = s.suffix
+	entry.Servers = []naming.VDLMountedServer{{"server1", 123}}
+	entry.Name = s.suffix
 	return
 }
 
diff --git a/tools/namespace/impl.go b/tools/namespace/impl.go
index b2df4db..cae7c40 100644
--- a/tools/namespace/impl.go
+++ b/tools/namespace/impl.go
@@ -145,12 +145,12 @@
 
 	ns := veyron2.GetNamespace(ctx)
 
-	servers, err := ns.Resolve(ctx, name)
+	me, err := ns.Resolve(ctx, name)
 	if err != nil {
 		vlog.Infof("ns.Resolve(%q) failed: %v", name, err)
 		return err
 	}
-	for _, s := range servers {
+	for _, s := range me.Names() {
 		fmt.Fprintln(cmd.Stdout(), s)
 	}
 	return nil
@@ -176,9 +176,9 @@
 
 	ns := veyron2.GetNamespace(ctx)
 
-	e, err := ns.ResolveToMountTableX(ctx, name)
+	e, err := ns.ResolveToMountTable(ctx, name)
 	if err != nil {
-		vlog.Infof("ns.ResolveToMountTableX(%q) failed: %v", name, err)
+		vlog.Infof("ns.ResolveToMountTable(%q) failed: %v", name, err)
 		return err
 	}
 	for _, s := range e.Servers {
diff --git a/tools/naming/simulator/shell_functions.go b/tools/naming/simulator/shell_functions.go
index 396fe6d..552635b 100644
--- a/tools/naming/simulator/shell_functions.go
+++ b/tools/naming/simulator/shell_functions.go
@@ -87,18 +87,19 @@
 	return nil
 }
 
-type resolver func(ctx *context.T, name string, opts ...naming.ResolveOpt) (names []string, err error)
+type resolver func(ctx *context.T, name string, opts ...naming.ResolveOpt) (me *naming.MountEntry, err error)
 
 func resolve(fn resolver, stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
 	if err := checkArgs(args[1:], 1, "<name>"); err != nil {
 		return err
 	}
 	name := args[1]
-	servers, err := fn(ctx, name)
+	me, err := fn(ctx, name)
 	if err != nil {
 		fmt.Fprintf(stdout, "RN=0\n")
 		return err
 	}
+	servers := me.Names()
 	fmt.Fprintf(stdout, "RN=%d\n", len(servers))
 	for i, s := range servers {
 		fmt.Fprintf(stdout, "R%d=%s\n", i, s)
diff --git a/tools/vrpc/doc.go b/tools/vrpc/doc.go
index ffb250a..f5ff56d 100644
--- a/tools/vrpc/doc.go
+++ b/tools/vrpc/doc.go
@@ -2,16 +2,16 @@
 // DO NOT UPDATE MANUALLY
 
 /*
-The vrpc tool facilitates interaction with Veyron RPC servers. In particular, it
-can be used to 1) find out what API a Veyron RPC server exports and 2) send
-requests to a Veyron RPC server.
+The vrpc tool provides command-line access to Vanadium servers via Remote
+Procedure Call.
 
 Usage:
    vrpc <command>
 
 The vrpc commands are:
-   describe    Describe the API of an Veyron RPC server
-   invoke      Invoke a method of an Veyron RPC server
+   signature   Describe the interfaces of a Vanadium server
+   call        Call a method of a Vanadium server
+   identify    Reveal blessings presented by a Vanadium server
    help        Display help for commands or topics
 Run "vrpc help [command]" for command usage.
 
@@ -38,44 +38,73 @@
    local namespace root; can be repeated to provided multiple roots
  -veyron.vtrace.cache_size=1024
    The number of vtrace traces to store in memory.
- -veyron.vtrace.dump_on_shutdown=false
+ -veyron.vtrace.collect_regexp=
+   Spans and annotations that match this regular expression will trigger trace
+   collection.
+ -veyron.vtrace.dump_on_shutdown=true
    If true, dump all stored traces on runtime shutdown.
  -veyron.vtrace.sample_rate=0
    Rate (from 0.0 to 1.0) to sample vtrace traces.
  -vmodule=
    comma-separated list of pattern=N settings for file-filtered logging
 
-Vrpc Describe
+Vrpc Signature
 
-Describe connects to the Veyron RPC server identified by <server>, finds out
-what its API is, and outputs a succint summary of this API to the standard
-output.
+Signature connects to the Vanadium server identified by <server>.
+
+If no [method] is provided, returns all interfaces implemented by the server.
+
+If a [method] is provided, returns the signature of just that method.
 
 Usage:
-   vrpc describe <server>
+   vrpc signature <server> [method]
 
-<server> identifies the Veyron RPC server. It can either be the object address
-of the server or an Object name in which case the vrpc will use Veyron's name
-resolution to match this name to an end-point.
+<server> identifies a Vanadium server.  It can either be the object address of
+the server, or an object name that will be resolved to an end-point.
 
-Vrpc Invoke
+[method] is the optional server method name.
 
-Invoke connects to the Veyron RPC server identified by <server>, invokes the
-method identified by <method>, supplying the arguments identified by <args>, and
-outputs the results of the invocation to the standard output.
+Vrpc Call
+
+Call connects to the Vanadium server identified by <server> and calls the
+<method> with the given positional [args...], returning results on stdout.
+
+TODO(toddw): stdin is read for streaming arguments sent to the server.  An EOF
+on stdin (e.g. via ^D) causes the send stream to be closed.
+
+Regardless of whether the call is streaming, the main goroutine blocks for
+streaming and positional results received from the server.
+
+All input arguments (both positional and streaming) are specified as VDL
+expressions, with commas separating multiple expressions.  Positional arguments
+may also be specified as separate command-line arguments.  Streaming arguments
+may also be specified as separate newline-terminated expressions.
+
+The method signature is always retrieved from the server as a first step.  This
+makes it easier to input complex typed arguments, since the top-level type for
+each argument is implicit and doesn't need to be specified.
 
 Usage:
-   vrpc invoke <server> <method> <args>
+   vrpc call <server> <method> [args...]
 
-<server> identifies the Veyron RPC server. It can either be the object address
-of the server or an Object name in which case the vrpc will use Veyron's name
-resolution to match this name to an end-point.
+<server> identifies a Vanadium server.  It can either be the object address of
+the server, or an object name that will be resolved to an end-point.
 
-<method> identifies the name of the method to be invoked.
+<method> is the server method to call.
 
-<args> identifies the arguments of the method to be invoked. It should be a list
-of values in a VOM JSON format that can be reflected to the correct type using
-Go's reflection.
+[args...] are the positional input arguments, specified as VDL expressions.
+
+Vrpc Identify
+
+Identify connects to the Vanadium server identified by <server> and dumps out
+the blessings presented by that server (and the subset of those that are
+considered valid by the principal running this tool) to standard output.
+
+Usage:
+   vrpc identify <server>
+
+<server> identifies a Vanadium server.  It can either be the object address of
+the server, or an object name that will be resolved to an end-point.
 
 Vrpc Help
 
diff --git a/tools/vrpc/impl.go b/tools/vrpc/impl.go
deleted file mode 100644
index 9c672f4..0000000
--- a/tools/vrpc/impl.go
+++ /dev/null
@@ -1,348 +0,0 @@
-package main
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"time"
-
-	idl_test_base "v.io/core/veyron/tools/vrpc/test_base"
-	"v.io/core/veyron2"
-	"v.io/core/veyron2/context"
-	"v.io/core/veyron2/ipc"
-	"v.io/core/veyron2/naming"
-	"v.io/core/veyron2/vdl/vdlutil"
-	"v.io/core/veyron2/vom"
-	"v.io/core/veyron2/wiretype"
-	"v.io/lib/cmdline"
-
-	idl_binary "v.io/core/veyron2/services/mgmt/binary"
-	idl_device "v.io/core/veyron2/services/mgmt/device"
-)
-
-const serverDesc = `
-<server> identifies the Veyron RPC server. It can either be the object address of
-the server or an Object name in which case the vrpc will use Veyron's name
-resolution to match this name to an end-point.
-`
-const methodDesc = `
-<method> identifies the name of the method to be invoked.
-`
-const argsDesc = `
-<args> identifies the arguments of the method to be invoked. It should be a list
-of values in a VOM JSON format that can be reflected to the correct type
-using Go's reflection.
-`
-
-var cmdDescribe = &cmdline.Command{
-	Run:   runDescribe,
-	Name:  "describe",
-	Short: "Describe the API of an Veyron RPC server",
-	Long: `
-Describe connects to the Veyron RPC server identified by <server>, finds out what
-its API is, and outputs a succint summary of this API to the standard output.
-`,
-	ArgsName: "<server>",
-	ArgsLong: serverDesc,
-}
-
-func runDescribe(cmd *cmdline.Command, args []string) error {
-	if len(args) != 1 {
-		return cmd.UsageErrorf("describe: incorrect number of arguments, expected 1, got %d", len(args))
-	}
-	ctx, cancel := context.WithTimeout(runtime.NewContext(), time.Minute)
-	defer cancel()
-	signature, err := getSignature(ctx, cmd, args[0])
-	if err != nil {
-		return err
-	}
-
-	for methodName, methodSignature := range signature.Methods {
-		fmt.Fprintf(cmd.Stdout(), "%s\n", formatSignature(methodName, methodSignature, signature.TypeDefs))
-	}
-	return nil
-}
-
-var cmdInvoke = &cmdline.Command{
-	Run:   runInvoke,
-	Name:  "invoke",
-	Short: "Invoke a method of an Veyron RPC server",
-	Long: `
-Invoke connects to the Veyron RPC server identified by <server>, invokes the method
-identified by <method>, supplying the arguments identified by <args>, and outputs
-the results of the invocation to the standard output.
-`,
-	ArgsName: "<server> <method> <args>",
-	ArgsLong: serverDesc + methodDesc + argsDesc,
-}
-
-func runInvoke(cmd *cmdline.Command, args []string) error {
-	if len(args) < 2 {
-		return cmd.UsageErrorf("invoke: incorrect number of arguments, expected at least 2, got %d", len(args))
-	}
-	server, method, args := args[0], args[1], args[2:]
-
-	ctx, cancel := context.WithTimeout(runtime.NewContext(), time.Minute)
-	defer cancel()
-	signature, err := getSignature(ctx, cmd, server)
-	if err != nil {
-		return fmt.Errorf("invoke: failed to get signature for %v: %v", server, err)
-	}
-	if len(signature.Methods) == 0 {
-		return fmt.Errorf("invoke: empty signature for %v", server)
-	}
-
-	methodSignature, found := signature.Methods[method]
-	if !found {
-		return fmt.Errorf("invoke: method %s not found", method)
-	}
-
-	if len(args) != len(methodSignature.InArgs) {
-		return cmd.UsageErrorf("invoke: incorrect number of arguments, expected %d, got %d", len(methodSignature.InArgs), len(args))
-	}
-
-	// Register all user-defined types you would like to use.
-	//
-	// TODO(jsimsa): This is a temporary hack to get vrpc to work. When
-	// Benj implements support for decoding arbitrary structs to an
-	// empty interface, this will no longer be needed.
-	var x1 idl_test_base.Struct
-	vdlutil.Register(x1)
-	var x2 idl_device.Description
-	vdlutil.Register(x2)
-	var x3 idl_binary.Description
-	vdlutil.Register(x3)
-	var x4 naming.VDLMountedServer
-	vdlutil.Register(x4)
-	var x5 naming.VDLMountEntry
-	vdlutil.Register(x5)
-
-	// Decode the inputs from vomJSON-formatted command-line arguments.
-	inputs := make([]interface{}, len(args))
-	for i := range args {
-		var buf bytes.Buffer
-		buf.WriteString(args[i])
-		buf.WriteByte(0)
-		decoder := vom.NewDecoder(&buf)
-		if err := decoder.Decode(&inputs[i]); err != nil {
-			return fmt.Errorf("decoder.Decode() failed for %s with %v", args[i], err)
-		}
-	}
-
-	// Initiate the method invocation.
-	client := veyron2.GetClient(ctx)
-	call, err := client.StartCall(ctx, server, method, inputs)
-	if err != nil {
-		return fmt.Errorf("client.StartCall(%q, %q, %v) failed with %v", server, method, inputs, err)
-	}
-
-	fmt.Fprintf(cmd.Stdout(), "%s = ", formatInput(method, inputs))
-
-	// Handle streaming results, if the method happens to be streaming.
-	var item interface{}
-	nStream := 0
-forloop:
-	for ; ; nStream++ {
-		switch err := call.Recv(&item); err {
-		case io.EOF:
-			break forloop
-		case nil:
-			if nStream == 0 {
-				fmt.Fprintln(cmd.Stdout(), "<<")
-			}
-			fmt.Fprintf(cmd.Stdout(), "%d: %v\n", nStream, item)
-		default:
-			return fmt.Errorf("call.Recv failed with %v", err)
-		}
-	}
-	if nStream > 0 {
-		fmt.Fprintf(cmd.Stdout(), ">> ")
-	}
-
-	// Receive the outputs of the method invocation.
-	outputs := make([]interface{}, len(methodSignature.OutArgs))
-	outputPtrs := make([]interface{}, len(methodSignature.OutArgs))
-	for i := range outputs {
-		outputPtrs[i] = &outputs[i]
-	}
-	if err := call.Finish(outputPtrs...); err != nil {
-		return fmt.Errorf("call.Finish() failed with %v", err)
-	}
-	fmt.Fprintf(cmd.Stdout(), "%s\n", formatOutput(outputs))
-
-	return nil
-}
-
-var cmdIdentify = &cmdline.Command{
-	Run:   runIdentify,
-	Name:  "identify",
-	Short: "Reveal blessings presented by a Veyron RPC server",
-	Long: `
-Identify connects to the Veyron RPC server identified by <server> and dumps
-out the blessings presented by that server (and the subset of those that are
-considered valid by the principal running this tool) to standard output.
-`,
-	ArgsName: "[<server>]",
-	ArgsLong: serverDesc,
-}
-
-func runIdentify(cmd *cmdline.Command, args []string) error {
-	if len(args) > 1 {
-		return cmd.UsageErrorf("identify: incorrect number of arguments, expected at most 1, got %d", len(args))
-	}
-	ctx, cancel := context.WithTimeout(runtime.NewContext(), time.Minute)
-	defer cancel()
-	client := veyron2.GetClient(ctx)
-	var server string
-	if len(args) > 0 {
-		server = args[0]
-	}
-	// The method name does not matter - only interested in authentication,
-	// not in actually making an RPC.
-	call, err := client.StartCall(ctx, server, "", nil)
-	if err != nil {
-		return fmt.Errorf("client.StartCall(%q, \"\", nil) failed with %v", server, err)
-	}
-	valid, presented := call.RemoteBlessings()
-	fmt.Fprintf(cmd.Stdout(), "PRESENTED:  %v\nVALID:      %v\n", presented, valid)
-	return nil
-}
-
-// root returns the root command for the vrpc tool.
-func root() *cmdline.Command {
-	return &cmdline.Command{
-		Name:  "vrpc",
-		Short: "Tool for interacting with Veyron RPC servers.",
-		Long: `
-The vrpc tool facilitates interaction with Veyron RPC servers. In particular,
-it can be used to 1) find out what API a Veyron RPC server exports and
-2) send requests to a Veyron RPC server.
-`,
-		Children: []*cmdline.Command{cmdDescribe, cmdInvoke, cmdIdentify},
-	}
-}
-
-func getSignature(ctx *context.T, cmd *cmdline.Command, server string) (ipc.ServiceSignature, error) {
-	client := veyron2.GetClient(ctx)
-	call, err := client.StartCall(ctx, server, "Signature", nil)
-	if err != nil {
-		return ipc.ServiceSignature{}, fmt.Errorf("client.StartCall(%q, \"Signature\", nil) failed with %v", server, err)
-	}
-	var signature ipc.ServiceSignature
-	var sigerr error
-	if err = call.Finish(&signature, &sigerr); err != nil {
-		return ipc.ServiceSignature{}, fmt.Errorf("client.Finish(&signature, &sigerr) failed with %v", err)
-	}
-	return signature, sigerr
-}
-
-// formatWiretype generates a string representation of the specified type.
-func formatWiretype(td []vdlutil.Any, tid wiretype.TypeID) string {
-	var wt vdlutil.Any
-	if tid >= wiretype.TypeIDFirst {
-		wt = td[tid-wiretype.TypeIDFirst]
-	} else {
-		for _, pair := range wiretype.BootstrapTypes {
-			if pair.TID == tid {
-				wt = pair.WT
-			}
-		}
-		if wt == nil {
-			return fmt.Sprintf("UNKNOWN_TYPE[%v]", tid)
-		}
-	}
-
-	switch t := wt.(type) {
-	case wiretype.NamedPrimitiveType:
-		if t.Name != "" {
-			return t.Name
-		}
-		return tid.Name()
-	case wiretype.SliceType:
-		return fmt.Sprintf("[]%s", formatWiretype(td, t.Elem))
-	case wiretype.ArrayType:
-		return fmt.Sprintf("[%d]%s", t.Len, formatWiretype(td, t.Elem))
-	case wiretype.MapType:
-		return fmt.Sprintf("map[%s]%s", formatWiretype(td, t.Key), formatWiretype(td, t.Elem))
-	case wiretype.StructType:
-		var buf bytes.Buffer
-		buf.WriteString("struct{")
-		for i, fld := range t.Fields {
-			if i > 0 {
-				buf.WriteString(", ")
-			}
-			buf.WriteString(fld.Name)
-			buf.WriteString(" ")
-			buf.WriteString(formatWiretype(td, fld.Type))
-		}
-		buf.WriteString("}")
-		return buf.String()
-	default:
-		panic(fmt.Sprintf("unknown writetype: %T", wt))
-	}
-}
-
-func formatSignature(name string, ms ipc.MethodSignature, defs []vdlutil.Any) string {
-	var buf bytes.Buffer
-	fmt.Fprintf(&buf, "func %s(", name)
-	for index, arg := range ms.InArgs {
-		if index > 0 {
-			buf.WriteString(", ")
-		}
-		fmt.Fprintf(&buf, "%s %s", arg.Name, formatWiretype(defs, arg.Type))
-	}
-	buf.WriteString(") ")
-	if ms.InStream != wiretype.TypeIDInvalid || ms.OutStream != wiretype.TypeIDInvalid {
-		buf.WriteString("stream<")
-		if ms.InStream == wiretype.TypeIDInvalid {
-			buf.WriteString("_")
-		} else {
-			fmt.Fprintf(&buf, "%s", formatWiretype(defs, ms.InStream))
-		}
-		buf.WriteString(", ")
-		if ms.OutStream == wiretype.TypeIDInvalid {
-			buf.WriteString("_")
-		} else {
-			fmt.Fprintf(&buf, "%s", formatWiretype(defs, ms.OutStream))
-		}
-		buf.WriteString("> ")
-	}
-	buf.WriteString("(")
-	for index, arg := range ms.OutArgs {
-		if index > 0 {
-			buf.WriteString(", ")
-		}
-		if arg.Name != "" {
-			fmt.Fprintf(&buf, "%s ", arg.Name)
-		}
-		fmt.Fprintf(&buf, "%s", formatWiretype(defs, arg.Type))
-	}
-	buf.WriteString(")")
-	return buf.String()
-}
-
-func formatInput(name string, inputs []interface{}) string {
-	var buf bytes.Buffer
-	fmt.Fprintf(&buf, "%s(", name)
-	for index, value := range inputs {
-		if index > 0 {
-			buf.WriteString(", ")
-		}
-		fmt.Fprintf(&buf, "%v", value)
-	}
-	buf.WriteString(")")
-	return buf.String()
-}
-
-func formatOutput(outputs []interface{}) string {
-	var buf bytes.Buffer
-	buf.WriteString("[")
-	for index, value := range outputs {
-		if index > 0 {
-			buf.WriteString(", ")
-		}
-		fmt.Fprintf(&buf, "%v", value)
-	}
-	buf.WriteString("]")
-	return buf.String()
-}
diff --git a/tools/vrpc/impl_test.go b/tools/vrpc/impl_test.go
deleted file mode 100644
index 6f32b71..0000000
--- a/tools/vrpc/impl_test.go
+++ /dev/null
@@ -1,293 +0,0 @@
-package main
-
-import (
-	"bytes"
-	"sort"
-	"strings"
-	"testing"
-
-	"v.io/core/veyron2"
-	"v.io/core/veyron2/context"
-	"v.io/core/veyron2/ipc"
-	"v.io/core/veyron2/naming"
-	"v.io/core/veyron2/rt"
-	"v.io/core/veyron2/vlog"
-
-	"v.io/core/veyron/profiles"
-	"v.io/core/veyron/tools/vrpc/test_base"
-	"v.io/lib/cmdline"
-)
-
-type server struct{}
-
-// TypeTester interface implementation
-
-func (*server) EchoBool(call ipc.ServerContext, i1 bool) (bool, error) {
-	vlog.VI(2).Info("EchoBool(%v) was called.", i1)
-	return i1, nil
-}
-
-func (*server) EchoFloat32(call ipc.ServerContext, i1 float32) (float32, error) {
-	vlog.VI(2).Info("EchoFloat32(%u) was called.", i1)
-	return i1, nil
-}
-
-func (*server) EchoFloat64(call ipc.ServerContext, i1 float64) (float64, error) {
-	vlog.VI(2).Info("EchoFloat64(%u) was called.", i1)
-	return i1, nil
-}
-
-func (*server) EchoInt32(call ipc.ServerContext, i1 int32) (int32, error) {
-	vlog.VI(2).Info("EchoInt32(%v) was called.", i1)
-	return i1, nil
-}
-
-func (*server) EchoInt64(call ipc.ServerContext, i1 int64) (int64, error) {
-	vlog.VI(2).Info("EchoInt64(%v) was called.", i1)
-	return i1, nil
-}
-
-func (*server) EchoString(call ipc.ServerContext, i1 string) (string, error) {
-	vlog.VI(2).Info("EchoString(%v) was called.", i1)
-	return i1, nil
-}
-
-func (*server) EchoByte(call ipc.ServerContext, i1 byte) (byte, error) {
-	vlog.VI(2).Info("EchoByte(%v) was called.", i1)
-	return i1, nil
-}
-
-func (*server) EchoUInt32(call ipc.ServerContext, i1 uint32) (uint32, error) {
-	vlog.VI(2).Info("EchoUInt32(%u) was called.", i1)
-	return i1, nil
-}
-
-func (*server) EchoUInt64(call ipc.ServerContext, i1 uint64) (uint64, error) {
-	vlog.VI(2).Info("EchoUInt64(%u) was called.", i1)
-	return i1, nil
-}
-
-func (*server) InputArray(call ipc.ServerContext, i1 [2]uint8) error {
-	vlog.VI(2).Info("CInputArray(%v) was called.", i1)
-	return nil
-}
-
-func (*server) OutputArray(call ipc.ServerContext) ([2]uint8, error) {
-	vlog.VI(2).Info("COutputArray() was called.")
-	return [2]uint8{1, 2}, nil
-}
-
-func (*server) InputMap(call ipc.ServerContext, i1 map[uint8]uint8) error {
-	vlog.VI(2).Info("CInputMap(%v) was called.", i1)
-	return nil
-}
-
-func (*server) OutputMap(call ipc.ServerContext) (map[uint8]uint8, error) {
-	vlog.VI(2).Info("COutputMap() was called.")
-	return map[uint8]uint8{1: 2}, nil
-}
-
-func (*server) InputSlice(call ipc.ServerContext, i1 []uint8) error {
-	vlog.VI(2).Info("CInputSlice(%v) was called.", i1)
-	return nil
-}
-
-func (*server) OutputSlice(call ipc.ServerContext) ([]uint8, error) {
-	vlog.VI(2).Info("COutputSlice() was called.")
-	return []uint8{1, 2}, nil
-}
-
-func (*server) InputStruct(call ipc.ServerContext, i1 test_base.Struct) error {
-	vlog.VI(2).Info("CInputStruct(%v) was called.", i1)
-	return nil
-}
-
-func (*server) OutputStruct(call ipc.ServerContext) (test_base.Struct, error) {
-	vlog.VI(2).Info("COutputStruct() was called.")
-	return test_base.Struct{X: 1, Y: 2}, nil
-}
-
-func (*server) NoArguments(call ipc.ServerContext) error {
-	vlog.VI(2).Info("NoArguments() was called.")
-	return nil
-}
-
-func (*server) MultipleArguments(call ipc.ServerContext, i1, i2 int32) (int32, int32, error) {
-	vlog.VI(2).Info("MultipleArguments(%v,%v) was called.", i1, i2)
-	return i1, i2, nil
-}
-
-func (*server) StreamingOutput(ctx test_base.TypeTesterStreamingOutputContext, nStream int32, item bool) error {
-	vlog.VI(2).Info("StreamingOutput(%v,%v) was called.", nStream, item)
-	sender := ctx.SendStream()
-	for i := int32(0); i < nStream; i++ {
-		sender.Send(item)
-	}
-	return nil
-}
-
-func startServer(t *testing.T, ctx *context.T) (ipc.Server, naming.Endpoint, error) {
-	obj := test_base.TypeTesterServer(&server{})
-	server, err := veyron2.NewServer(ctx)
-	if err != nil {
-		t.Errorf("NewServer failed: %v", err)
-		return nil, nil, err
-	}
-
-	endpoints, err := server.Listen(profiles.LocalListenSpec)
-	if err != nil {
-		t.Errorf("Listen failed: %v", err)
-		return nil, nil, err
-	}
-	if err := server.Serve("", obj, nil); err != nil {
-		t.Errorf("Serve failed: %v", err)
-		return nil, nil, err
-	}
-	return server, endpoints[0], nil
-}
-
-func stopServer(t *testing.T, server ipc.Server) {
-	if err := server.Stop(); err != nil {
-		t.Errorf("server.Stop failed: %v", err)
-	}
-}
-
-func testInvocation(t *testing.T, buffer *bytes.Buffer, cmd *cmdline.Command, args []string, expected string) {
-	buffer.Reset()
-	if err := cmd.Execute(args); err != nil {
-		t.Errorf("%v", err)
-		return
-	}
-	if output := strings.Trim(buffer.String(), "\n"); output != expected {
-		t.Errorf("Incorrect invoke output: expected %s, got %s", expected, output)
-		return
-	}
-}
-
-func testError(t *testing.T, cmd *cmdline.Command, args []string, expected string) {
-	if err := cmd.Execute(args); err == nil || !strings.Contains(err.Error(), expected) {
-		t.Errorf("Expected error: ...%v..., got: %v", expected, err)
-	}
-}
-
-func TestVRPC(t *testing.T) {
-	var err error
-	runtime, err = rt.New()
-	if err != nil {
-		t.Fatalf("Unexpected error initializing runtime: %s", err)
-	}
-	defer runtime.Cleanup()
-	ctx := runtime.NewContext()
-
-	// Skip defer runtime.Cleanup() to avoid messing up other tests in the
-	// same process.
-	server, endpoint, err := startServer(t, ctx)
-	if err != nil {
-		return
-	}
-	defer stopServer(t, server)
-
-	// Setup the command-line.
-	cmd := root()
-	var stdout, stderr bytes.Buffer
-	cmd.Init(nil, &stdout, &stderr)
-
-	name := endpoint.Name()
-	// Test the 'describe' command.
-	if err := cmd.Execute([]string{"describe", name}); err != nil {
-		t.Errorf("%v", err)
-		return
-	}
-
-	// TODO(toddw): Switch VRPC to new __Signature, and update these tests.
-	expectedSignature := []string{
-		"func EchoBool(I1 bool) (O1 bool, err error)",
-		"func EchoFloat32(I1 float32) (O1 float32, err error)",
-		"func EchoFloat64(I1 float64) (O1 float64, err error)",
-		"func EchoInt32(I1 int32) (O1 int32, err error)",
-		"func EchoInt64(I1 int64) (O1 int64, err error)",
-		"func EchoString(I1 string) (O1 string, err error)",
-		"func EchoByte(I1 byte) (O1 byte, err error)",
-		"func EchoUInt32(I1 uint32) (O1 uint32, err error)",
-		"func EchoUInt64(I1 uint64) (O1 uint64, err error)",
-		"func InputArray(I1 [2]byte) (error)",
-		"func InputMap(I1 map[byte]byte) (error)",
-		"func InputSlice(I1 []byte) (error)",
-		"func InputStruct(I1 struct{X int32, Y int32}) (error)",
-		"func OutputArray() (O1 [2]byte, err error)",
-		"func OutputMap() (O1 map[byte]byte, err error)",
-		"func OutputSlice() (O1 []byte, err error)",
-		"func OutputStruct() (O1 struct{X int32, Y int32}, err error)",
-		"func NoArguments() (error)",
-		"func MultipleArguments(I1 int32, I2 int32) (O1 int32, O2 int32, err error)",
-		"func StreamingOutput(NumStreamItems int32, StreamItem bool) stream<_, bool> (error)",
-	}
-
-	signature := make([]string, 0, len(expectedSignature))
-	line, err := stdout.ReadBytes('\n')
-	for err == nil {
-		signature = append(signature, strings.Trim(string(line), "\n"))
-		line, err = stdout.ReadBytes('\n')
-	}
-
-	sort.Strings(signature)
-	sort.Strings(expectedSignature)
-
-	if len(signature) != len(expectedSignature) {
-		t.Fatalf("signature lengths don't match %v and %v.", len(signature), len(expectedSignature))
-	}
-
-	for i, expectedSig := range expectedSignature {
-		if expectedSig != signature[i] {
-			t.Errorf("signature line doesn't match: %v and %v\n", expectedSig, signature[i])
-		}
-	}
-
-	// Test the 'invoke' command.
-
-	tests := [][]string{
-		[]string{"EchoBool", "EchoBool(true) = [true, <nil>]", "[\"bool\",true]"},
-		[]string{"EchoFloat32", "EchoFloat32(3.2) = [3.2, <nil>]", "[\"float32\",3.2]"},
-		[]string{"EchoFloat64", "EchoFloat64(6.4) = [6.4, <nil>]", "[\"float64\",6.4]"},
-		[]string{"EchoInt32", "EchoInt32(-32) = [-32, <nil>]", "[\"int32\",-32]"},
-		[]string{"EchoInt64", "EchoInt64(-64) = [-64, <nil>]", "[\"int64\",-64]"},
-		[]string{"EchoString", "EchoString(Hello World!) = [Hello World!, <nil>]", "[\"string\",\"Hello World!\"]"},
-		[]string{"EchoByte", "EchoByte(8) = [8, <nil>]", "[\"byte\",8]"},
-		[]string{"EchoUInt32", "EchoUInt32(32) = [32, <nil>]", "[\"uint32\",32]"},
-		[]string{"EchoUInt64", "EchoUInt64(64) = [64, <nil>]", "[\"uint64\",64]"},
-		// TODO(jsimsa): The InputArray currently triggers an error in the
-		// vom decoder. Benj is looking into this.
-		//
-		// []string{"InputArray", "InputArray([1 2]) = []", "[\"[2]uint\",[1,2]]"},
-		[]string{"InputMap", "InputMap(map[1:2]) = [<nil>]", "[\"map[uint]uint\",{\"1\":\"2\"}]"},
-		// TODO(jsimsa): The InputSlice currently triggers an error in the
-		// vom decoder. Benj is looking into this.
-		//
-		// []string{"InputSlice", "InputSlice([1 2]) = []", "[\"[]uint\",[1,2]]"},
-		[]string{"InputStruct", "InputStruct({1 2}) = [<nil>]",
-			"[\"type\",\"v.io/core/veyron2/vrpc/test_base.Struct struct{X int32;Y int32}\"] [\"Struct\",{\"X\":1,\"Y\":2}]"},
-		// TODO(jsimsa): The OutputArray currently triggers an error in the
-		// vom decoder. Benj is looking into this.
-		//
-		// []string{"OutputArray", "OutputArray() = [1 2]"}
-		[]string{"OutputMap", "OutputMap() = [map[1:2], <nil>]"},
-		[]string{"OutputSlice", "OutputSlice() = [[1 2], <nil>]"},
-		[]string{"OutputStruct", "OutputStruct() = [{1 2}, <nil>]"},
-		[]string{"NoArguments", "NoArguments() = [<nil>]"},
-		[]string{"MultipleArguments", "MultipleArguments(1, 2) = [1, 2, <nil>]", "[\"uint32\",1]", "[\"uint32\",2]"},
-		[]string{"StreamingOutput", "StreamingOutput(3, true) = <<\n0: true\n1: true\n2: true\n>> [<nil>]", "[\"int8\",3]", "[\"bool\",true ]"},
-		[]string{"StreamingOutput", "StreamingOutput(0, true) = [<nil>]", "[\"int8\",0]", "[\"bool\",true ]"},
-	}
-
-	for _, test := range tests {
-		testInvocation(t, &stdout, cmd, append([]string{"invoke", name, test[0]}, test[2:]...), test[1])
-	}
-
-	testErrors := [][]string{
-		[]string{"EchoBool", "exit code 1"},
-		[]string{"DoesNotExist", "invoke: method DoesNotExist not found"},
-	}
-	for _, test := range testErrors {
-		testError(t, cmd, append([]string{"invoke", name, test[0]}, test[2:]...), test[1])
-	}
-}
diff --git a/tools/vrpc/main.go b/tools/vrpc/main.go
deleted file mode 100644
index 7368a9c..0000000
--- a/tools/vrpc/main.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// The following enables go generate to generate the doc.go file.
-//go:generate go run $VANADIUM_ROOT/release/go/src/v.io/lib/cmdline/testdata/gendoc.go .
-
-package main
-
-import (
-	"v.io/core/veyron2"
-	"v.io/core/veyron2/rt"
-
-	_ "v.io/core/veyron/profiles"
-)
-
-var runtime veyron2.Runtime
-
-func main() {
-	var err error
-	runtime, err = rt.New()
-	if err != nil {
-		panic(err)
-	}
-	defer runtime.Cleanup()
-	root().Main()
-}
diff --git a/tools/vrpc/test_base/test_base.vdl b/tools/vrpc/test_base/test_base.vdl
index 8f6b15e..e0406da 100644
--- a/tools/vrpc/test_base/test_base.vdl
+++ b/tools/vrpc/test_base/test_base.vdl
@@ -4,32 +4,31 @@
   X,Y int32
 }
 
+// TypeTester methods are listed in alphabetical order, to make it easier to
+// test Signature output, which sorts methods alphabetically.
 type TypeTester interface {
-  // Methods to test support for generic types.
-  EchoBool(I1 bool) (O1 bool | error)
-  EchoFloat32(I1 float32) (O1 float32 | error)
-  EchoFloat64(I1 float64) (O1 float64 | error)
-  EchoInt32(I1 int32) (O1 int32 | error)
-  EchoInt64(I1 int64) (O1 int64 | error)
-  EchoString(I1 string) (O1 string | error)
-  EchoByte(I1 byte) (O1 byte | error)
-  EchoUInt32(I1 uint32) (O1 uint32 | error)
-  EchoUInt64(I1 uint64) (O1 uint64 | error)
+	// Methods to test support for primitive types.
+	EchoBool(I1 bool) (O1 bool | error)
+	EchoFloat32(I1 float32) (O1 float32 | error)
+	EchoFloat64(I1 float64) (O1 float64 | error)
+	EchoInt32(I1 int32) (O1 int32 | error)
+	EchoInt64(I1 int64) (O1 int64 | error)
+	EchoString(I1 string) (O1 string | error)
+	EchoByte(I1 byte) (O1 byte | error)
+	EchoUint32(I1 uint32) (O1 uint32 | error)
+	EchoUint64(I1 uint64) (O1 uint64 | error)
 
-  // Methods to test support for composite types.
-  InputArray(I1 [2]byte) error
-  InputMap(I1 map[byte]byte) error
-  InputSlice(I1 []byte) error
-  InputStruct(I1 Struct) error
-  OutputArray() (O1 [2]byte | error)
-  OutputMap() (O1 map[byte]byte | error)
-  OutputSlice() (O1 []byte | error)
-  OutputStruct() (O1 Struct | error)
+	// Methods to test support for composite types.
+	XEchoArray(I1 [2]int32) (O1 [2]int32 | error)
+	XEchoMap(I1 map[int32]string) (O1 map[int32]string | error)
+	XEchoSet(I1 set[int32]) (O1 set[int32] | error)
+	XEchoSlice(I1 []int32) (O1 []int32 | error)
+	XEchoStruct(I1 Struct) (O1 Struct | error)
 
-  // Methods to test support for different number of arguments.
-  NoArguments() error
-  MultipleArguments(I1, I2 int32) (O1, O2 int32 | error)
+	// Methods to test support for different number of arguments.
+	YMultiArg(I1, I2 int32) (O1, O2 int32 | error)
+	YNoArgs() error
 
-  // Methods to test support for streaming.
-  StreamingOutput(NumStreamItems int32, StreamItem bool) stream<_, bool> error
+	// Methods to test support for streaming.
+	ZStream(NumStreamItems int32, StreamItem bool) stream<_, bool> error
 }
diff --git a/tools/vrpc/test_base/test_base.vdl.go b/tools/vrpc/test_base/test_base.vdl.go
index 87a4708..af0e095 100644
--- a/tools/vrpc/test_base/test_base.vdl.go
+++ b/tools/vrpc/test_base/test_base.vdl.go
@@ -10,15 +10,8 @@
 	__context "v.io/core/veyron2/context"
 	__ipc "v.io/core/veyron2/ipc"
 	__vdl "v.io/core/veyron2/vdl"
-	__vdlutil "v.io/core/veyron2/vdl/vdlutil"
-	__wiretype "v.io/core/veyron2/wiretype"
 )
 
-// TODO(toddw): Remove this line once the new signature support is done.
-// It corrects a bug where __wiretype is unused in VDL pacakges where only
-// bootstrap types are used on interfaces.
-const _ = __wiretype.TypeIDInvalid
-
 type Struct struct {
 	X int32
 	Y int32
@@ -35,8 +28,11 @@
 
 // TypeTesterClientMethods is the client interface
 // containing TypeTester methods.
+//
+// TypeTester methods are listed in alphabetical order, to make it easier to
+// test Signature output, which sorts methods alphabetically.
 type TypeTesterClientMethods interface {
-	// Methods to test support for generic types.
+	// Methods to test support for primitive types.
 	EchoBool(ctx *__context.T, I1 bool, opts ...__ipc.CallOpt) (O1 bool, err error)
 	EchoFloat32(ctx *__context.T, I1 float32, opts ...__ipc.CallOpt) (O1 float32, err error)
 	EchoFloat64(ctx *__context.T, I1 float64, opts ...__ipc.CallOpt) (O1 float64, err error)
@@ -44,22 +40,19 @@
 	EchoInt64(ctx *__context.T, I1 int64, opts ...__ipc.CallOpt) (O1 int64, err error)
 	EchoString(ctx *__context.T, I1 string, opts ...__ipc.CallOpt) (O1 string, err error)
 	EchoByte(ctx *__context.T, I1 byte, opts ...__ipc.CallOpt) (O1 byte, err error)
-	EchoUInt32(ctx *__context.T, I1 uint32, opts ...__ipc.CallOpt) (O1 uint32, err error)
-	EchoUInt64(ctx *__context.T, I1 uint64, opts ...__ipc.CallOpt) (O1 uint64, err error)
+	EchoUint32(ctx *__context.T, I1 uint32, opts ...__ipc.CallOpt) (O1 uint32, err error)
+	EchoUint64(ctx *__context.T, I1 uint64, opts ...__ipc.CallOpt) (O1 uint64, err error)
 	// Methods to test support for composite types.
-	InputArray(ctx *__context.T, I1 [2]byte, opts ...__ipc.CallOpt) error
-	InputMap(ctx *__context.T, I1 map[byte]byte, opts ...__ipc.CallOpt) error
-	InputSlice(ctx *__context.T, I1 []byte, opts ...__ipc.CallOpt) error
-	InputStruct(ctx *__context.T, I1 Struct, opts ...__ipc.CallOpt) error
-	OutputArray(*__context.T, ...__ipc.CallOpt) (O1 [2]byte, err error)
-	OutputMap(*__context.T, ...__ipc.CallOpt) (O1 map[byte]byte, err error)
-	OutputSlice(*__context.T, ...__ipc.CallOpt) (O1 []byte, err error)
-	OutputStruct(*__context.T, ...__ipc.CallOpt) (O1 Struct, err error)
+	XEchoArray(ctx *__context.T, I1 [2]int32, opts ...__ipc.CallOpt) (O1 [2]int32, err error)
+	XEchoMap(ctx *__context.T, I1 map[int32]string, opts ...__ipc.CallOpt) (O1 map[int32]string, err error)
+	XEchoSet(ctx *__context.T, I1 map[int32]struct{}, opts ...__ipc.CallOpt) (O1 map[int32]struct{}, err error)
+	XEchoSlice(ctx *__context.T, I1 []int32, opts ...__ipc.CallOpt) (O1 []int32, err error)
+	XEchoStruct(ctx *__context.T, I1 Struct, opts ...__ipc.CallOpt) (O1 Struct, err error)
 	// Methods to test support for different number of arguments.
-	NoArguments(*__context.T, ...__ipc.CallOpt) error
-	MultipleArguments(ctx *__context.T, I1 int32, I2 int32, opts ...__ipc.CallOpt) (O1 int32, O2 int32, err error)
+	YMultiArg(ctx *__context.T, I1 int32, I2 int32, opts ...__ipc.CallOpt) (O1 int32, O2 int32, err error)
+	YNoArgs(*__context.T, ...__ipc.CallOpt) error
 	// Methods to test support for streaming.
-	StreamingOutput(ctx *__context.T, NumStreamItems int32, StreamItem bool, opts ...__ipc.CallOpt) (TypeTesterStreamingOutputCall, error)
+	ZStream(ctx *__context.T, NumStreamItems int32, StreamItem bool, opts ...__ipc.CallOpt) (TypeTesterZStreamCall, error)
 }
 
 // TypeTesterClientStub adds universal methods to TypeTesterClientMethods.
@@ -168,9 +161,9 @@
 	return
 }
 
-func (c implTypeTesterClientStub) EchoUInt32(ctx *__context.T, i0 uint32, opts ...__ipc.CallOpt) (o0 uint32, err error) {
+func (c implTypeTesterClientStub) EchoUint32(ctx *__context.T, i0 uint32, opts ...__ipc.CallOpt) (o0 uint32, err error) {
 	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "EchoUInt32", []interface{}{i0}, opts...); err != nil {
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "EchoUint32", []interface{}{i0}, opts...); err != nil {
 		return
 	}
 	if ierr := call.Finish(&o0, &err); ierr != nil {
@@ -179,9 +172,9 @@
 	return
 }
 
-func (c implTypeTesterClientStub) EchoUInt64(ctx *__context.T, i0 uint64, opts ...__ipc.CallOpt) (o0 uint64, err error) {
+func (c implTypeTesterClientStub) EchoUint64(ctx *__context.T, i0 uint64, opts ...__ipc.CallOpt) (o0 uint64, err error) {
 	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "EchoUInt64", []interface{}{i0}, opts...); err != nil {
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "EchoUint64", []interface{}{i0}, opts...); err != nil {
 		return
 	}
 	if ierr := call.Finish(&o0, &err); ierr != nil {
@@ -190,53 +183,9 @@
 	return
 }
 
-func (c implTypeTesterClientStub) InputArray(ctx *__context.T, i0 [2]byte, opts ...__ipc.CallOpt) (err error) {
+func (c implTypeTesterClientStub) XEchoArray(ctx *__context.T, i0 [2]int32, opts ...__ipc.CallOpt) (o0 [2]int32, err error) {
 	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "InputArray", []interface{}{i0}, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
-func (c implTypeTesterClientStub) InputMap(ctx *__context.T, i0 map[byte]byte, opts ...__ipc.CallOpt) (err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "InputMap", []interface{}{i0}, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
-func (c implTypeTesterClientStub) InputSlice(ctx *__context.T, i0 []byte, opts ...__ipc.CallOpt) (err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "InputSlice", []interface{}{i0}, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
-func (c implTypeTesterClientStub) InputStruct(ctx *__context.T, i0 Struct, opts ...__ipc.CallOpt) (err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "InputStruct", []interface{}{i0}, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
-func (c implTypeTesterClientStub) OutputArray(ctx *__context.T, opts ...__ipc.CallOpt) (o0 [2]byte, err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "OutputArray", nil, opts...); err != nil {
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "XEchoArray", []interface{}{i0}, opts...); err != nil {
 		return
 	}
 	if ierr := call.Finish(&o0, &err); ierr != nil {
@@ -245,9 +194,9 @@
 	return
 }
 
-func (c implTypeTesterClientStub) OutputMap(ctx *__context.T, opts ...__ipc.CallOpt) (o0 map[byte]byte, err error) {
+func (c implTypeTesterClientStub) XEchoMap(ctx *__context.T, i0 map[int32]string, opts ...__ipc.CallOpt) (o0 map[int32]string, err error) {
 	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "OutputMap", nil, opts...); err != nil {
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "XEchoMap", []interface{}{i0}, opts...); err != nil {
 		return
 	}
 	if ierr := call.Finish(&o0, &err); ierr != nil {
@@ -256,9 +205,9 @@
 	return
 }
 
-func (c implTypeTesterClientStub) OutputSlice(ctx *__context.T, opts ...__ipc.CallOpt) (o0 []byte, err error) {
+func (c implTypeTesterClientStub) XEchoSet(ctx *__context.T, i0 map[int32]struct{}, opts ...__ipc.CallOpt) (o0 map[int32]struct{}, err error) {
 	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "OutputSlice", nil, opts...); err != nil {
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "XEchoSet", []interface{}{i0}, opts...); err != nil {
 		return
 	}
 	if ierr := call.Finish(&o0, &err); ierr != nil {
@@ -267,9 +216,9 @@
 	return
 }
 
-func (c implTypeTesterClientStub) OutputStruct(ctx *__context.T, opts ...__ipc.CallOpt) (o0 Struct, err error) {
+func (c implTypeTesterClientStub) XEchoSlice(ctx *__context.T, i0 []int32, opts ...__ipc.CallOpt) (o0 []int32, err error) {
 	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "OutputStruct", nil, opts...); err != nil {
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "XEchoSlice", []interface{}{i0}, opts...); err != nil {
 		return
 	}
 	if ierr := call.Finish(&o0, &err); ierr != nil {
@@ -278,20 +227,20 @@
 	return
 }
 
-func (c implTypeTesterClientStub) NoArguments(ctx *__context.T, opts ...__ipc.CallOpt) (err error) {
+func (c implTypeTesterClientStub) XEchoStruct(ctx *__context.T, i0 Struct, opts ...__ipc.CallOpt) (o0 Struct, err error) {
 	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "NoArguments", nil, opts...); err != nil {
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "XEchoStruct", []interface{}{i0}, opts...); err != nil {
 		return
 	}
-	if ierr := call.Finish(&err); ierr != nil {
+	if ierr := call.Finish(&o0, &err); ierr != nil {
 		err = ierr
 	}
 	return
 }
 
-func (c implTypeTesterClientStub) MultipleArguments(ctx *__context.T, i0 int32, i1 int32, opts ...__ipc.CallOpt) (o0 int32, o1 int32, err error) {
+func (c implTypeTesterClientStub) YMultiArg(ctx *__context.T, i0 int32, i1 int32, opts ...__ipc.CallOpt) (o0 int32, o1 int32, err error) {
 	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "MultipleArguments", []interface{}{i0, i1}, opts...); err != nil {
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "YMultiArg", []interface{}{i0, i1}, opts...); err != nil {
 		return
 	}
 	if ierr := call.Finish(&o0, &o1, &err); ierr != nil {
@@ -300,29 +249,29 @@
 	return
 }
 
-func (c implTypeTesterClientStub) StreamingOutput(ctx *__context.T, i0 int32, i1 bool, opts ...__ipc.CallOpt) (ocall TypeTesterStreamingOutputCall, err error) {
+func (c implTypeTesterClientStub) YNoArgs(ctx *__context.T, opts ...__ipc.CallOpt) (err error) {
 	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "StreamingOutput", []interface{}{i0, i1}, opts...); err != nil {
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "YNoArgs", nil, opts...); err != nil {
 		return
 	}
-	ocall = &implTypeTesterStreamingOutputCall{Call: call}
-	return
-}
-
-func (c implTypeTesterClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&o0, &err); ierr != nil {
+	if ierr := call.Finish(&err); ierr != nil {
 		err = ierr
 	}
 	return
 }
 
-// TypeTesterStreamingOutputClientStream is the client stream for TypeTester.StreamingOutput.
-type TypeTesterStreamingOutputClientStream interface {
-	// RecvStream returns the receiver side of the TypeTester.StreamingOutput client stream.
+func (c implTypeTesterClientStub) ZStream(ctx *__context.T, i0 int32, i1 bool, opts ...__ipc.CallOpt) (ocall TypeTesterZStreamCall, err error) {
+	var call __ipc.Call
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "ZStream", []interface{}{i0, i1}, opts...); err != nil {
+		return
+	}
+	ocall = &implTypeTesterZStreamCall{Call: call}
+	return
+}
+
+// TypeTesterZStreamClientStream is the client stream for TypeTester.ZStream.
+type TypeTesterZStreamClientStream interface {
+	// RecvStream returns the receiver side of the TypeTester.ZStream client stream.
 	RecvStream() interface {
 		// Advance stages an item so that it may be retrieved via Value.  Returns
 		// true iff there is an item to retrieve.  Advance must be called before
@@ -336,9 +285,9 @@
 	}
 }
 
-// TypeTesterStreamingOutputCall represents the call returned from TypeTester.StreamingOutput.
-type TypeTesterStreamingOutputCall interface {
-	TypeTesterStreamingOutputClientStream
+// TypeTesterZStreamCall represents the call returned from TypeTester.ZStream.
+type TypeTesterZStreamCall interface {
+	TypeTesterZStreamClientStream
 	// Finish blocks until the server is done, and returns the positional return
 	// values for call.
 	//
@@ -352,38 +301,38 @@
 	Finish() error
 }
 
-type implTypeTesterStreamingOutputCall struct {
+type implTypeTesterZStreamCall struct {
 	__ipc.Call
 	valRecv bool
 	errRecv error
 }
 
-func (c *implTypeTesterStreamingOutputCall) RecvStream() interface {
+func (c *implTypeTesterZStreamCall) RecvStream() interface {
 	Advance() bool
 	Value() bool
 	Err() error
 } {
-	return implTypeTesterStreamingOutputCallRecv{c}
+	return implTypeTesterZStreamCallRecv{c}
 }
 
-type implTypeTesterStreamingOutputCallRecv struct {
-	c *implTypeTesterStreamingOutputCall
+type implTypeTesterZStreamCallRecv struct {
+	c *implTypeTesterZStreamCall
 }
 
-func (c implTypeTesterStreamingOutputCallRecv) Advance() bool {
+func (c implTypeTesterZStreamCallRecv) Advance() bool {
 	c.c.errRecv = c.c.Recv(&c.c.valRecv)
 	return c.c.errRecv == nil
 }
-func (c implTypeTesterStreamingOutputCallRecv) Value() bool {
+func (c implTypeTesterZStreamCallRecv) Value() bool {
 	return c.c.valRecv
 }
-func (c implTypeTesterStreamingOutputCallRecv) Err() error {
+func (c implTypeTesterZStreamCallRecv) Err() error {
 	if c.c.errRecv == __io.EOF {
 		return nil
 	}
 	return c.c.errRecv
 }
-func (c *implTypeTesterStreamingOutputCall) Finish() (err error) {
+func (c *implTypeTesterZStreamCall) Finish() (err error) {
 	if ierr := c.Call.Finish(&err); ierr != nil {
 		err = ierr
 	}
@@ -392,8 +341,11 @@
 
 // TypeTesterServerMethods is the interface a server writer
 // implements for TypeTester.
+//
+// TypeTester methods are listed in alphabetical order, to make it easier to
+// test Signature output, which sorts methods alphabetically.
 type TypeTesterServerMethods interface {
-	// Methods to test support for generic types.
+	// Methods to test support for primitive types.
 	EchoBool(ctx __ipc.ServerContext, I1 bool) (O1 bool, err error)
 	EchoFloat32(ctx __ipc.ServerContext, I1 float32) (O1 float32, err error)
 	EchoFloat64(ctx __ipc.ServerContext, I1 float64) (O1 float64, err error)
@@ -401,22 +353,19 @@
 	EchoInt64(ctx __ipc.ServerContext, I1 int64) (O1 int64, err error)
 	EchoString(ctx __ipc.ServerContext, I1 string) (O1 string, err error)
 	EchoByte(ctx __ipc.ServerContext, I1 byte) (O1 byte, err error)
-	EchoUInt32(ctx __ipc.ServerContext, I1 uint32) (O1 uint32, err error)
-	EchoUInt64(ctx __ipc.ServerContext, I1 uint64) (O1 uint64, err error)
+	EchoUint32(ctx __ipc.ServerContext, I1 uint32) (O1 uint32, err error)
+	EchoUint64(ctx __ipc.ServerContext, I1 uint64) (O1 uint64, err error)
 	// Methods to test support for composite types.
-	InputArray(ctx __ipc.ServerContext, I1 [2]byte) error
-	InputMap(ctx __ipc.ServerContext, I1 map[byte]byte) error
-	InputSlice(ctx __ipc.ServerContext, I1 []byte) error
-	InputStruct(ctx __ipc.ServerContext, I1 Struct) error
-	OutputArray(__ipc.ServerContext) (O1 [2]byte, err error)
-	OutputMap(__ipc.ServerContext) (O1 map[byte]byte, err error)
-	OutputSlice(__ipc.ServerContext) (O1 []byte, err error)
-	OutputStruct(__ipc.ServerContext) (O1 Struct, err error)
+	XEchoArray(ctx __ipc.ServerContext, I1 [2]int32) (O1 [2]int32, err error)
+	XEchoMap(ctx __ipc.ServerContext, I1 map[int32]string) (O1 map[int32]string, err error)
+	XEchoSet(ctx __ipc.ServerContext, I1 map[int32]struct{}) (O1 map[int32]struct{}, err error)
+	XEchoSlice(ctx __ipc.ServerContext, I1 []int32) (O1 []int32, err error)
+	XEchoStruct(ctx __ipc.ServerContext, I1 Struct) (O1 Struct, err error)
 	// Methods to test support for different number of arguments.
-	NoArguments(__ipc.ServerContext) error
-	MultipleArguments(ctx __ipc.ServerContext, I1 int32, I2 int32) (O1 int32, O2 int32, err error)
+	YMultiArg(ctx __ipc.ServerContext, I1 int32, I2 int32) (O1 int32, O2 int32, err error)
+	YNoArgs(__ipc.ServerContext) error
 	// Methods to test support for streaming.
-	StreamingOutput(ctx TypeTesterStreamingOutputContext, NumStreamItems int32, StreamItem bool) error
+	ZStream(ctx TypeTesterZStreamContext, NumStreamItems int32, StreamItem bool) error
 }
 
 // TypeTesterServerStubMethods is the server interface containing
@@ -424,7 +373,7 @@
 // The only difference between this interface and TypeTesterServerMethods
 // is the streaming methods.
 type TypeTesterServerStubMethods interface {
-	// Methods to test support for generic types.
+	// Methods to test support for primitive types.
 	EchoBool(ctx __ipc.ServerContext, I1 bool) (O1 bool, err error)
 	EchoFloat32(ctx __ipc.ServerContext, I1 float32) (O1 float32, err error)
 	EchoFloat64(ctx __ipc.ServerContext, I1 float64) (O1 float64, err error)
@@ -432,22 +381,19 @@
 	EchoInt64(ctx __ipc.ServerContext, I1 int64) (O1 int64, err error)
 	EchoString(ctx __ipc.ServerContext, I1 string) (O1 string, err error)
 	EchoByte(ctx __ipc.ServerContext, I1 byte) (O1 byte, err error)
-	EchoUInt32(ctx __ipc.ServerContext, I1 uint32) (O1 uint32, err error)
-	EchoUInt64(ctx __ipc.ServerContext, I1 uint64) (O1 uint64, err error)
+	EchoUint32(ctx __ipc.ServerContext, I1 uint32) (O1 uint32, err error)
+	EchoUint64(ctx __ipc.ServerContext, I1 uint64) (O1 uint64, err error)
 	// Methods to test support for composite types.
-	InputArray(ctx __ipc.ServerContext, I1 [2]byte) error
-	InputMap(ctx __ipc.ServerContext, I1 map[byte]byte) error
-	InputSlice(ctx __ipc.ServerContext, I1 []byte) error
-	InputStruct(ctx __ipc.ServerContext, I1 Struct) error
-	OutputArray(__ipc.ServerContext) (O1 [2]byte, err error)
-	OutputMap(__ipc.ServerContext) (O1 map[byte]byte, err error)
-	OutputSlice(__ipc.ServerContext) (O1 []byte, err error)
-	OutputStruct(__ipc.ServerContext) (O1 Struct, err error)
+	XEchoArray(ctx __ipc.ServerContext, I1 [2]int32) (O1 [2]int32, err error)
+	XEchoMap(ctx __ipc.ServerContext, I1 map[int32]string) (O1 map[int32]string, err error)
+	XEchoSet(ctx __ipc.ServerContext, I1 map[int32]struct{}) (O1 map[int32]struct{}, err error)
+	XEchoSlice(ctx __ipc.ServerContext, I1 []int32) (O1 []int32, err error)
+	XEchoStruct(ctx __ipc.ServerContext, I1 Struct) (O1 Struct, err error)
 	// Methods to test support for different number of arguments.
-	NoArguments(__ipc.ServerContext) error
-	MultipleArguments(ctx __ipc.ServerContext, I1 int32, I2 int32) (O1 int32, O2 int32, err error)
+	YMultiArg(ctx __ipc.ServerContext, I1 int32, I2 int32) (O1 int32, O2 int32, err error)
+	YNoArgs(__ipc.ServerContext) error
 	// Methods to test support for streaming.
-	StreamingOutput(ctx *TypeTesterStreamingOutputContextStub, NumStreamItems int32, StreamItem bool) error
+	ZStream(ctx *TypeTesterZStreamContextStub, NumStreamItems int32, StreamItem bool) error
 }
 
 // TypeTesterServerStub adds universal methods to TypeTesterServerStubMethods.
@@ -455,8 +401,6 @@
 	TypeTesterServerStubMethods
 	// Describe the TypeTester interfaces.
 	Describe__() []__ipc.InterfaceDesc
-	// Signature will be replaced with Describe__.
-	Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
 }
 
 // TypeTesterServer returns a server stub for TypeTester.
@@ -509,56 +453,44 @@
 	return s.impl.EchoByte(ctx, i0)
 }
 
-func (s implTypeTesterServerStub) EchoUInt32(ctx __ipc.ServerContext, i0 uint32) (uint32, error) {
-	return s.impl.EchoUInt32(ctx, i0)
+func (s implTypeTesterServerStub) EchoUint32(ctx __ipc.ServerContext, i0 uint32) (uint32, error) {
+	return s.impl.EchoUint32(ctx, i0)
 }
 
-func (s implTypeTesterServerStub) EchoUInt64(ctx __ipc.ServerContext, i0 uint64) (uint64, error) {
-	return s.impl.EchoUInt64(ctx, i0)
+func (s implTypeTesterServerStub) EchoUint64(ctx __ipc.ServerContext, i0 uint64) (uint64, error) {
+	return s.impl.EchoUint64(ctx, i0)
 }
 
-func (s implTypeTesterServerStub) InputArray(ctx __ipc.ServerContext, i0 [2]byte) error {
-	return s.impl.InputArray(ctx, i0)
+func (s implTypeTesterServerStub) XEchoArray(ctx __ipc.ServerContext, i0 [2]int32) ([2]int32, error) {
+	return s.impl.XEchoArray(ctx, i0)
 }
 
-func (s implTypeTesterServerStub) InputMap(ctx __ipc.ServerContext, i0 map[byte]byte) error {
-	return s.impl.InputMap(ctx, i0)
+func (s implTypeTesterServerStub) XEchoMap(ctx __ipc.ServerContext, i0 map[int32]string) (map[int32]string, error) {
+	return s.impl.XEchoMap(ctx, i0)
 }
 
-func (s implTypeTesterServerStub) InputSlice(ctx __ipc.ServerContext, i0 []byte) error {
-	return s.impl.InputSlice(ctx, i0)
+func (s implTypeTesterServerStub) XEchoSet(ctx __ipc.ServerContext, i0 map[int32]struct{}) (map[int32]struct{}, error) {
+	return s.impl.XEchoSet(ctx, i0)
 }
 
-func (s implTypeTesterServerStub) InputStruct(ctx __ipc.ServerContext, i0 Struct) error {
-	return s.impl.InputStruct(ctx, i0)
+func (s implTypeTesterServerStub) XEchoSlice(ctx __ipc.ServerContext, i0 []int32) ([]int32, error) {
+	return s.impl.XEchoSlice(ctx, i0)
 }
 
-func (s implTypeTesterServerStub) OutputArray(ctx __ipc.ServerContext) ([2]byte, error) {
-	return s.impl.OutputArray(ctx)
+func (s implTypeTesterServerStub) XEchoStruct(ctx __ipc.ServerContext, i0 Struct) (Struct, error) {
+	return s.impl.XEchoStruct(ctx, i0)
 }
 
-func (s implTypeTesterServerStub) OutputMap(ctx __ipc.ServerContext) (map[byte]byte, error) {
-	return s.impl.OutputMap(ctx)
+func (s implTypeTesterServerStub) YMultiArg(ctx __ipc.ServerContext, i0 int32, i1 int32) (int32, int32, error) {
+	return s.impl.YMultiArg(ctx, i0, i1)
 }
 
-func (s implTypeTesterServerStub) OutputSlice(ctx __ipc.ServerContext) ([]byte, error) {
-	return s.impl.OutputSlice(ctx)
+func (s implTypeTesterServerStub) YNoArgs(ctx __ipc.ServerContext) error {
+	return s.impl.YNoArgs(ctx)
 }
 
-func (s implTypeTesterServerStub) OutputStruct(ctx __ipc.ServerContext) (Struct, error) {
-	return s.impl.OutputStruct(ctx)
-}
-
-func (s implTypeTesterServerStub) NoArguments(ctx __ipc.ServerContext) error {
-	return s.impl.NoArguments(ctx)
-}
-
-func (s implTypeTesterServerStub) MultipleArguments(ctx __ipc.ServerContext, i0 int32, i1 int32) (int32, int32, error) {
-	return s.impl.MultipleArguments(ctx, i0, i1)
-}
-
-func (s implTypeTesterServerStub) StreamingOutput(ctx *TypeTesterStreamingOutputContextStub, i0 int32, i1 bool) error {
-	return s.impl.StreamingOutput(ctx, i0, i1)
+func (s implTypeTesterServerStub) ZStream(ctx *TypeTesterZStreamContextStub, i0 int32, i1 bool) error {
+	return s.impl.ZStream(ctx, i0, i1)
 }
 
 func (s implTypeTesterServerStub) Globber() *__ipc.GlobState {
@@ -576,10 +508,11 @@
 var descTypeTester = __ipc.InterfaceDesc{
 	Name:    "TypeTester",
 	PkgPath: "v.io/core/veyron/tools/vrpc/test_base",
+	Doc:     "// TypeTester methods are listed in alphabetical order, to make it easier to\n// test Signature output, which sorts methods alphabetically.",
 	Methods: []__ipc.MethodDesc{
 		{
 			Name: "EchoBool",
-			Doc:  "// Methods to test support for generic types.",
+			Doc:  "// Methods to test support for primitive types.",
 			InArgs: []__ipc.ArgDesc{
 				{"I1", ``}, // bool
 			},
@@ -649,7 +582,7 @@
 			},
 		},
 		{
-			Name: "EchoUInt32",
+			Name: "EchoUint32",
 			InArgs: []__ipc.ArgDesc{
 				{"I1", ``}, // uint32
 			},
@@ -659,7 +592,7 @@
 			},
 		},
 		{
-			Name: "EchoUInt64",
+			Name: "EchoUint64",
 			InArgs: []__ipc.ArgDesc{
 				{"I1", ``}, // uint64
 			},
@@ -669,79 +602,59 @@
 			},
 		},
 		{
-			Name: "InputArray",
+			Name: "XEchoArray",
 			Doc:  "// Methods to test support for composite types.",
 			InArgs: []__ipc.ArgDesc{
-				{"I1", ``}, // [2]byte
+				{"I1", ``}, // [2]int32
 			},
 			OutArgs: []__ipc.ArgDesc{
-				{"", ``}, // error
+				{"O1", ``},  // [2]int32
+				{"err", ``}, // error
 			},
 		},
 		{
-			Name: "InputMap",
+			Name: "XEchoMap",
 			InArgs: []__ipc.ArgDesc{
-				{"I1", ``}, // map[byte]byte
+				{"I1", ``}, // map[int32]string
 			},
 			OutArgs: []__ipc.ArgDesc{
-				{"", ``}, // error
+				{"O1", ``},  // map[int32]string
+				{"err", ``}, // error
 			},
 		},
 		{
-			Name: "InputSlice",
+			Name: "XEchoSet",
 			InArgs: []__ipc.ArgDesc{
-				{"I1", ``}, // []byte
+				{"I1", ``}, // map[int32]struct{}
 			},
 			OutArgs: []__ipc.ArgDesc{
-				{"", ``}, // error
+				{"O1", ``},  // map[int32]struct{}
+				{"err", ``}, // error
 			},
 		},
 		{
-			Name: "InputStruct",
+			Name: "XEchoSlice",
+			InArgs: []__ipc.ArgDesc{
+				{"I1", ``}, // []int32
+			},
+			OutArgs: []__ipc.ArgDesc{
+				{"O1", ``},  // []int32
+				{"err", ``}, // error
+			},
+		},
+		{
+			Name: "XEchoStruct",
 			InArgs: []__ipc.ArgDesc{
 				{"I1", ``}, // Struct
 			},
 			OutArgs: []__ipc.ArgDesc{
-				{"", ``}, // error
-			},
-		},
-		{
-			Name: "OutputArray",
-			OutArgs: []__ipc.ArgDesc{
-				{"O1", ``},  // [2]byte
-				{"err", ``}, // error
-			},
-		},
-		{
-			Name: "OutputMap",
-			OutArgs: []__ipc.ArgDesc{
-				{"O1", ``},  // map[byte]byte
-				{"err", ``}, // error
-			},
-		},
-		{
-			Name: "OutputSlice",
-			OutArgs: []__ipc.ArgDesc{
-				{"O1", ``},  // []byte
-				{"err", ``}, // error
-			},
-		},
-		{
-			Name: "OutputStruct",
-			OutArgs: []__ipc.ArgDesc{
 				{"O1", ``},  // Struct
 				{"err", ``}, // error
 			},
 		},
 		{
-			Name: "NoArguments",
+			Name: "YMultiArg",
 			Doc:  "// Methods to test support for different number of arguments.",
-			OutArgs: []__ipc.ArgDesc{
-				{"", ``}, // error
-			},
-		},
-		{
-			Name: "MultipleArguments",
 			InArgs: []__ipc.ArgDesc{
 				{"I1", ``}, // int32
 				{"I2", ``}, // int32
@@ -753,7 +666,13 @@
 			},
 		},
 		{
-			Name: "StreamingOutput",
+			Name: "YNoArgs",
+			OutArgs: []__ipc.ArgDesc{
+				{"", ``}, // error
+			},
+		},
+		{
+			Name: "ZStream",
 			Doc:  "// Methods to test support for streaming.",
 			InArgs: []__ipc.ArgDesc{
 				{"NumStreamItems", ``}, // int32
@@ -766,194 +685,9 @@
 	},
 }
 
-func (s implTypeTesterServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
-	// TODO(toddw): Replace with new Describe__ implementation.
-	result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
-	result.Methods["EchoBool"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "I1", Type: 2},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "O1", Type: 2},
-			{Name: "err", Type: 65},
-		},
-	}
-	result.Methods["EchoByte"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "I1", Type: 66},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "O1", Type: 66},
-			{Name: "err", Type: 65},
-		},
-	}
-	result.Methods["EchoFloat32"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "I1", Type: 25},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "O1", Type: 25},
-			{Name: "err", Type: 65},
-		},
-	}
-	result.Methods["EchoFloat64"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "I1", Type: 26},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "O1", Type: 26},
-			{Name: "err", Type: 65},
-		},
-	}
-	result.Methods["EchoInt32"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "I1", Type: 36},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "O1", Type: 36},
-			{Name: "err", Type: 65},
-		},
-	}
-	result.Methods["EchoInt64"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "I1", Type: 37},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "O1", Type: 37},
-			{Name: "err", Type: 65},
-		},
-	}
-	result.Methods["EchoString"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "I1", Type: 3},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "O1", Type: 3},
-			{Name: "err", Type: 65},
-		},
-	}
-	result.Methods["EchoUInt32"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "I1", Type: 52},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "O1", Type: 52},
-			{Name: "err", Type: 65},
-		},
-	}
-	result.Methods["EchoUInt64"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "I1", Type: 53},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "O1", Type: 53},
-			{Name: "err", Type: 65},
-		},
-	}
-	result.Methods["InputArray"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "I1", Type: 67},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 65},
-		},
-	}
-	result.Methods["InputMap"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "I1", Type: 68},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 65},
-		},
-	}
-	result.Methods["InputSlice"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "I1", Type: 69},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 65},
-		},
-	}
-	result.Methods["InputStruct"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "I1", Type: 70},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 65},
-		},
-	}
-	result.Methods["MultipleArguments"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "I1", Type: 36},
-			{Name: "I2", Type: 36},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "O1", Type: 36},
-			{Name: "O2", Type: 36},
-			{Name: "err", Type: 65},
-		},
-	}
-	result.Methods["NoArguments"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 65},
-		},
-	}
-	result.Methods["OutputArray"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "O1", Type: 67},
-			{Name: "err", Type: 65},
-		},
-	}
-	result.Methods["OutputMap"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "O1", Type: 68},
-			{Name: "err", Type: 65},
-		},
-	}
-	result.Methods["OutputSlice"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "O1", Type: 69},
-			{Name: "err", Type: 65},
-		},
-	}
-	result.Methods["OutputStruct"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "O1", Type: 70},
-			{Name: "err", Type: 65},
-		},
-	}
-	result.Methods["StreamingOutput"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{
-			{Name: "NumStreamItems", Type: 36},
-			{Name: "StreamItem", Type: 2},
-		},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 65},
-		},
-
-		OutStream: 2,
-	}
-
-	result.TypeDefs = []__vdlutil.Any{
-		__wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x32, Name: "byte", Tags: []string(nil)}, __wiretype.ArrayType{Elem: 0x42, Len: 0x2, Name: "", Tags: []string(nil)}, __wiretype.MapType{Key: 0x42, Elem: 0x42, Name: "", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x42, Name: "", Tags: []string(nil)}, __wiretype.StructType{
-			[]__wiretype.FieldType{
-				__wiretype.FieldType{Type: 0x24, Name: "X"},
-				__wiretype.FieldType{Type: 0x24, Name: "Y"},
-			},
-			"v.io/core/veyron/tools/vrpc/test_base.Struct", []string(nil)},
-	}
-
-	return result, nil
-}
-
-// TypeTesterStreamingOutputServerStream is the server stream for TypeTester.StreamingOutput.
-type TypeTesterStreamingOutputServerStream interface {
-	// SendStream returns the send side of the TypeTester.StreamingOutput server stream.
+// TypeTesterZStreamServerStream is the server stream for TypeTester.ZStream.
+type TypeTesterZStreamServerStream interface {
+	// SendStream returns the send side of the TypeTester.ZStream server stream.
 	SendStream() interface {
 		// Send places the item onto the output stream.  Returns errors encountered
 		// while sending.  Blocks if there is no buffer space; will unblock when
@@ -962,34 +696,34 @@
 	}
 }
 
-// TypeTesterStreamingOutputContext represents the context passed to TypeTester.StreamingOutput.
-type TypeTesterStreamingOutputContext interface {
+// TypeTesterZStreamContext represents the context passed to TypeTester.ZStream.
+type TypeTesterZStreamContext interface {
 	__ipc.ServerContext
-	TypeTesterStreamingOutputServerStream
+	TypeTesterZStreamServerStream
 }
 
-// TypeTesterStreamingOutputContextStub is a wrapper that converts ipc.ServerCall into
-// a typesafe stub that implements TypeTesterStreamingOutputContext.
-type TypeTesterStreamingOutputContextStub struct {
+// TypeTesterZStreamContextStub is a wrapper that converts ipc.ServerCall into
+// a typesafe stub that implements TypeTesterZStreamContext.
+type TypeTesterZStreamContextStub struct {
 	__ipc.ServerCall
 }
 
-// Init initializes TypeTesterStreamingOutputContextStub from ipc.ServerCall.
-func (s *TypeTesterStreamingOutputContextStub) Init(call __ipc.ServerCall) {
+// Init initializes TypeTesterZStreamContextStub from ipc.ServerCall.
+func (s *TypeTesterZStreamContextStub) Init(call __ipc.ServerCall) {
 	s.ServerCall = call
 }
 
-// SendStream returns the send side of the TypeTester.StreamingOutput server stream.
-func (s *TypeTesterStreamingOutputContextStub) SendStream() interface {
+// SendStream returns the send side of the TypeTester.ZStream server stream.
+func (s *TypeTesterZStreamContextStub) SendStream() interface {
 	Send(item bool) error
 } {
-	return implTypeTesterStreamingOutputContextSend{s}
+	return implTypeTesterZStreamContextSend{s}
 }
 
-type implTypeTesterStreamingOutputContextSend struct {
-	s *TypeTesterStreamingOutputContextStub
+type implTypeTesterZStreamContextSend struct {
+	s *TypeTesterZStreamContextStub
 }
 
-func (s implTypeTesterStreamingOutputContextSend) Send(item bool) error {
+func (s implTypeTesterZStreamContextSend) Send(item bool) error {
 	return s.s.Send(item)
 }
diff --git a/tools/vrpc/vrpc.go b/tools/vrpc/vrpc.go
new file mode 100644
index 0000000..5c025d3
--- /dev/null
+++ b/tools/vrpc/vrpc.go
@@ -0,0 +1,276 @@
+// The following enables go generate to generate the doc.go file.
+//go:generate go run $VANADIUM_ROOT/release/go/src/v.io/lib/cmdline/testdata/gendoc.go .
+
+package main
+
+import (
+	"fmt"
+	"io"
+	"strings"
+	"time"
+
+	"v.io/core/veyron2"
+	"v.io/core/veyron2/context"
+	"v.io/core/veyron2/ipc/reserved"
+	"v.io/core/veyron2/rt"
+	"v.io/core/veyron2/vdl"
+	"v.io/core/veyron2/vdl/build"
+	"v.io/core/veyron2/vdl/codegen/vdlgen"
+	"v.io/core/veyron2/vdl/compile"
+	"v.io/core/veyron2/vdl/vdlroot/src/signature"
+	"v.io/lib/cmdline"
+
+	_ "v.io/core/veyron/profiles"
+)
+
+var runtime veyron2.Runtime
+
+func main() {
+	var err error
+	runtime, err = rt.New()
+	if err != nil {
+		panic(err)
+	}
+	defer runtime.Cleanup()
+	cmdVRPC.Main()
+}
+
+var cmdVRPC = &cmdline.Command{
+	Name:  "vrpc",
+	Short: "Vanadium Remote Procedure Call tool",
+	Long: `
+The vrpc tool provides command-line access to Vanadium servers via Remote
+Procedure Call.
+`,
+	// TODO(toddw): Add cmdServe, which will take an interface as input, and set
+	// up a server capable of handling the given methods.  When a request is
+	// received, it'll allow the user to respond via stdin.
+	Children: []*cmdline.Command{cmdSignature, cmdCall, cmdIdentify},
+}
+
+const serverDesc = `
+<server> identifies a Vanadium server.  It can either be the object address of
+the server, or an object name that will be resolved to an end-point.
+`
+
+var cmdSignature = &cmdline.Command{
+	Run:   runSignature,
+	Name:  "signature",
+	Short: "Describe the interfaces of a Vanadium server",
+	Long: `
+Signature connects to the Vanadium server identified by <server>.
+
+If no [method] is provided, returns all interfaces implemented by the server.
+
+If a [method] is provided, returns the signature of just that method.
+`,
+	ArgsName: "<server> [method]",
+	ArgsLong: serverDesc + `
+[method] is the optional server method name.
+`,
+}
+
+var cmdCall = &cmdline.Command{
+	Run:   runCall,
+	Name:  "call",
+	Short: "Call a method of a Vanadium server",
+	Long: `
+Call connects to the Vanadium server identified by <server> and calls the
+<method> with the given positional [args...], returning results on stdout.
+
+TODO(toddw): stdin is read for streaming arguments sent to the server.  An EOF
+on stdin (e.g. via ^D) causes the send stream to be closed.
+
+Regardless of whether the call is streaming, the main goroutine blocks for
+streaming and positional results received from the server.
+
+All input arguments (both positional and streaming) are specified as VDL
+expressions, with commas separating multiple expressions.  Positional arguments
+may also be specified as separate command-line arguments.  Streaming arguments
+may also be specified as separate newline-terminated expressions.
+
+The method signature is always retrieved from the server as a first step.  This
+makes it easier to input complex typed arguments, since the top-level type for
+each argument is implicit and doesn't need to be specified.
+`,
+	ArgsName: "<server> <method> [args...]",
+	ArgsLong: serverDesc + `
+<method> is the server method to call.
+
+[args...] are the positional input arguments, specified as VDL expressions.
+`,
+}
+
+var cmdIdentify = &cmdline.Command{
+	Run:   runIdentify,
+	Name:  "identify",
+	Short: "Reveal blessings presented by a Vanadium server",
+	Long: `
+Identify connects to the Vanadium server identified by <server> and dumps out
+the blessings presented by that server (and the subset of those that are
+considered valid by the principal running this tool) to standard output.
+`,
+	ArgsName: "<server>",
+	ArgsLong: serverDesc,
+}
+
+func runSignature(cmd *cmdline.Command, args []string) error {
+	// Error-check args.
+	var server, method string
+	switch len(args) {
+	case 1:
+		server = args[0]
+	case 2:
+		server, method = args[0], args[1]
+	default:
+		return cmd.UsageErrorf("wrong number of arguments")
+	}
+	// Get the interface or method signature, and pretty-print.  We print the
+	// named types after the signatures, to aid in readability.
+	ctx, cancel := context.WithTimeout(runtime.NewContext(), time.Minute)
+	defer cancel()
+	var types signature.NamedTypes
+	if method != "" {
+		methodSig, err := reserved.MethodSignature(ctx, server, method)
+		if err != nil {
+			return fmt.Errorf("MethodSignature failed: %v", err)
+		}
+		methodSig.Print(cmd.Stdout(), &types)
+		fmt.Fprintln(cmd.Stdout())
+		types.Print(cmd.Stdout())
+		return nil
+	}
+	ifacesSig, err := reserved.Signature(ctx, server)
+	if err != nil {
+		return fmt.Errorf("Signature failed: %v", err)
+	}
+	for i, iface := range ifacesSig {
+		if i > 0 {
+			fmt.Fprintln(cmd.Stdout())
+		}
+		iface.Print(cmd.Stdout(), &types)
+		fmt.Fprintln(cmd.Stdout())
+	}
+	types.Print(cmd.Stdout())
+	return nil
+}
+
+func runCall(cmd *cmdline.Command, args []string) error {
+	// Error-check args, and set up argsdata with a comma-separated list of
+	// arguments, allowing each individual arg to already be comma-separated.
+	//
+	// TODO(toddw): Should we just space-separate the args instead?
+	if len(args) < 2 {
+		return cmd.UsageErrorf("must specify <server> and <method>")
+	}
+	server, method := args[0], args[1]
+	var argsdata string
+	for _, arg := range args[2:] {
+		arg := strings.TrimSpace(arg)
+		if argsdata == "" || strings.HasSuffix(argsdata, ",") || strings.HasPrefix(arg, ",") {
+			argsdata += arg
+		} else {
+			argsdata += "," + arg
+		}
+	}
+	// Get the method signature and parse args.
+	ctx, cancel := context.WithTimeout(runtime.NewContext(), time.Minute)
+	defer cancel()
+	methodSig, err := reserved.MethodSignature(ctx, server, method)
+	if err != nil {
+		return fmt.Errorf("MethodSignature failed: %v", err)
+	}
+	inargs, err := parseInArgs(argsdata, methodSig)
+	if err != nil {
+		// TODO: Print signature and example.
+		return err
+	}
+	// Start the method call.
+	call, err := veyron2.GetClient(ctx).StartCall(ctx, server, method, inargs)
+	if err != nil {
+		return fmt.Errorf("StartCall failed: %v", err)
+	}
+	// TODO(toddw): Fire off a goroutine to handle streaming inputs.
+	// Handle streaming results.
+StreamingResultsLoop:
+	for {
+		var item *vdl.Value
+		switch err := call.Recv(&item); {
+		case err == io.EOF:
+			break StreamingResultsLoop
+		case err != nil:
+			return fmt.Errorf("call.Recv failed: %v", err)
+		}
+		fmt.Fprintf(cmd.Stdout(), "<< %v\n", vdlgen.TypedConst(item, "", nil))
+	}
+	// Finish the method call.
+	outargs := make([]*vdl.Value, len(methodSig.OutArgs))
+	outptrs := make([]interface{}, len(outargs))
+	for i := range outargs {
+		outptrs[i] = &outargs[i]
+	}
+	if err := call.Finish(outptrs...); err != nil {
+		return fmt.Errorf("call.Finish failed: %v", err)
+	}
+	// Handle application errors, reported as a final error out-arg.
+	//
+	// TODO(toddw): Change call.Finish to report the error directly.
+	outlen := len(outargs)
+	if outlen > 0 && methodSig.OutArgs[outlen-1].Type == vdl.ErrorType {
+		if errarg := outargs[outlen-1]; !errarg.IsNil() {
+			return fmt.Errorf(vdlgen.TypedConst(errarg, "", nil))
+		}
+		outargs = outargs[:outlen-1]
+	}
+	// Pretty-print results.
+	for i, arg := range outargs {
+		if i > 0 {
+			fmt.Fprint(cmd.Stdout(), " ")
+		}
+		fmt.Fprint(cmd.Stdout(), vdlgen.TypedConst(arg, "", nil))
+	}
+	fmt.Fprintln(cmd.Stdout())
+	return nil
+}
+
+func parseInArgs(argsdata string, methodSig signature.Method) ([]interface{}, error) {
+	if len(methodSig.InArgs) == 0 {
+		return nil, nil
+	}
+	var intypes []*vdl.Type
+	for _, inarg := range methodSig.InArgs {
+		intypes = append(intypes, inarg.Type)
+	}
+	env := compile.NewEnv(-1)
+	inargs := build.BuildExprs(argsdata, intypes, env)
+	if err := env.Errors.ToError(); err != nil {
+		return nil, fmt.Errorf("can't parse in-args:\n%v", err)
+	}
+	if got, want := len(inargs), len(methodSig.InArgs); got != want {
+		return nil, fmt.Errorf("got %d args, want %d", got, want)
+	}
+	// Translate []*vdl.Value to []interface, with each item still *vdl.Value.
+	var ret []interface{}
+	for _, arg := range inargs {
+		ret = append(ret, arg)
+	}
+	return ret, nil
+}
+
+func runIdentify(cmd *cmdline.Command, args []string) error {
+	if len(args) != 1 {
+		return cmd.UsageErrorf("wrong number of arguments")
+	}
+	server := args[0]
+	ctx, cancel := context.WithTimeout(runtime.NewContext(), time.Minute)
+	defer cancel()
+	// The method name does not matter - only interested in authentication,
+	// not in actually making an RPC.
+	call, err := veyron2.GetClient(ctx).StartCall(ctx, server, "", nil)
+	if err != nil {
+		return fmt.Errorf(`client.StartCall(%q, "", nil) failed with %v`, server, err)
+	}
+	valid, presented := call.RemoteBlessings()
+	fmt.Fprintf(cmd.Stdout(), "PRESENTED:  %v\nVALID:      %v\n", presented, valid)
+	return nil
+}
diff --git a/tools/vrpc/vrpc_test.go b/tools/vrpc/vrpc_test.go
new file mode 100644
index 0000000..3b71012
--- /dev/null
+++ b/tools/vrpc/vrpc_test.go
@@ -0,0 +1,311 @@
+package main
+
+import (
+	"bytes"
+	"strings"
+	"testing"
+
+	"v.io/core/veyron2"
+	"v.io/core/veyron2/ipc"
+	"v.io/core/veyron2/rt"
+	"v.io/core/veyron2/vlog"
+
+	"v.io/core/veyron/profiles"
+	"v.io/core/veyron/tools/vrpc/test_base"
+)
+
+type server struct{}
+
+// TypeTester interface implementation
+
+func (*server) EchoBool(call ipc.ServerContext, i1 bool) (bool, error) {
+	vlog.VI(2).Info("EchoBool(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoFloat32(call ipc.ServerContext, i1 float32) (float32, error) {
+	vlog.VI(2).Info("EchoFloat32(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoFloat64(call ipc.ServerContext, i1 float64) (float64, error) {
+	vlog.VI(2).Info("EchoFloat64(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoInt32(call ipc.ServerContext, i1 int32) (int32, error) {
+	vlog.VI(2).Info("EchoInt32(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoInt64(call ipc.ServerContext, i1 int64) (int64, error) {
+	vlog.VI(2).Info("EchoInt64(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoString(call ipc.ServerContext, i1 string) (string, error) {
+	vlog.VI(2).Info("EchoString(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoByte(call ipc.ServerContext, i1 byte) (byte, error) {
+	vlog.VI(2).Info("EchoByte(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoUint32(call ipc.ServerContext, i1 uint32) (uint32, error) {
+	vlog.VI(2).Info("EchoUint32(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoUint64(call ipc.ServerContext, i1 uint64) (uint64, error) {
+	vlog.VI(2).Info("EchoUint64(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) XEchoArray(call ipc.ServerContext, i1 [2]int32) ([2]int32, error) {
+	vlog.VI(2).Info("XEchoArray(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) XEchoMap(call ipc.ServerContext, i1 map[int32]string) (map[int32]string, error) {
+	vlog.VI(2).Info("XEchoMap(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) XEchoSet(call ipc.ServerContext, i1 map[int32]struct{}) (map[int32]struct{}, error) {
+	vlog.VI(2).Info("XEchoSet(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) XEchoSlice(call ipc.ServerContext, i1 []int32) ([]int32, error) {
+	vlog.VI(2).Info("XEchoSlice(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) XEchoStruct(call ipc.ServerContext, i1 test_base.Struct) (test_base.Struct, error) {
+	vlog.VI(2).Info("XEchoStruct(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) YMultiArg(call ipc.ServerContext, i1, i2 int32) (int32, int32, error) {
+	vlog.VI(2).Info("YMultiArg(%v,%v) was called.", i1, i2)
+	return i1, i2, nil
+}
+
+func (*server) YNoArgs(call ipc.ServerContext) error {
+	vlog.VI(2).Info("YNoArgs() was called.")
+	return nil
+}
+
+func (*server) ZStream(ctx test_base.TypeTesterZStreamContext, nStream int32, item bool) error {
+	vlog.VI(2).Info("ZStream(%v,%v) was called.", nStream, item)
+	sender := ctx.SendStream()
+	for i := int32(0); i < nStream; i++ {
+		sender.Send(item)
+	}
+	return nil
+}
+
+func initTest(t *testing.T) (name string, cleanup func()) {
+	// The runtime initialized here is the global runtime defined in vrpc.go.
+	var ipcServer ipc.Server
+	cleanup = func() {
+		if ipcServer != nil {
+			if err := ipcServer.Stop(); err != nil {
+				t.Errorf("server.Stop failed: %v", err)
+			}
+		}
+		if runtime != nil {
+			runtime.Cleanup()
+		}
+	}
+	var err error
+	if runtime, err = rt.New(); err != nil {
+		t.Fatalf("rt.New() failed: %v", err)
+		return
+	}
+	if ipcServer, err = veyron2.NewServer(runtime.NewContext()); err != nil {
+		t.Fatalf("NewServer failed: %v", err)
+		return
+	}
+	endpoints, err := ipcServer.Listen(profiles.LocalListenSpec)
+	if err != nil {
+		t.Fatalf("Listen failed: %v", err)
+		return
+	}
+	name = endpoints[0].Name()
+	obj := test_base.TypeTesterServer(&server{})
+	if err := ipcServer.Serve("", obj, nil); err != nil {
+		t.Fatalf("Serve failed: %v", err)
+		return
+	}
+	return
+}
+
+func TestSignature(t *testing.T) {
+	name, cleanup := initTest(t)
+	defer cleanup()
+	var stdout, stderr bytes.Buffer
+	cmdVRPC.Init(nil, &stdout, &stderr)
+
+	if err := cmdVRPC.Execute([]string{"signature", name}); err != nil {
+		t.Errorf("%v", err)
+		return
+	}
+	wantSig := `// TypeTester methods are listed in alphabetical order, to make it easier to
+// test Signature output, which sorts methods alphabetically.
+type "v.io/core/veyron/tools/vrpc/test_base".TypeTester interface {
+	// Methods to test support for primitive types.
+	EchoBool(I1 bool) (O1 bool | error)
+	EchoByte(I1 byte) (O1 byte | error)
+	EchoFloat32(I1 float32) (O1 float32 | error)
+	EchoFloat64(I1 float64) (O1 float64 | error)
+	EchoInt32(I1 int32) (O1 int32 | error)
+	EchoInt64(I1 int64) (O1 int64 | error)
+	EchoString(I1 string) (O1 string | error)
+	EchoUint32(I1 uint32) (O1 uint32 | error)
+	EchoUint64(I1 uint64) (O1 uint64 | error)
+	// Methods to test support for composite types.
+	XEchoArray(I1 [2]int32) (O1 [2]int32 | error)
+	XEchoMap(I1 map[int32]string) (O1 map[int32]string | error)
+	XEchoSet(I1 set[int32]) (O1 set[int32] | error)
+	XEchoSlice(I1 []int32) (O1 []int32 | error)
+	XEchoStruct(I1 "v.io/core/veyron/tools/vrpc/test_base".Struct) (O1 "v.io/core/veyron/tools/vrpc/test_base".Struct | error)
+	// Methods to test support for different number of arguments.
+	YMultiArg(I1 int32, I2 int32) (O1 int32, O2 int32 | error)
+	YNoArgs() error
+	// Methods to test support for streaming.
+	ZStream(NumStreamItems int32, StreamItem bool) stream<_, bool> error
+}
+
+// Reserved methods implemented by the IPC framework.  Each method name is prefixed with a double underscore "__".
+type __Reserved interface {
+	// Glob returns all entries matching the pattern.
+	__Glob(pattern string) stream<any, any> error
+	// MethodSignature returns the signature for the given method.
+	__MethodSignature(method string) ("signature".Method | error)
+	// Signature returns all interface signatures implemented by the object.
+	__Signature() ([]"signature".Interface | error)
+}
+
+type "signature".Arg struct {
+	Name string
+	Doc string
+	Type typeobject
+}
+
+type "signature".Embed struct {
+	Name string
+	PkgPath string
+	Doc string
+}
+
+type "signature".Interface struct {
+	Name string
+	PkgPath string
+	Doc string
+	Embeds []"signature".Embed
+	Methods []"signature".Method
+}
+
+type "signature".Method struct {
+	Name string
+	Doc string
+	InArgs []"signature".Arg
+	OutArgs []"signature".Arg
+	InStream ?"signature".Arg
+	OutStream ?"signature".Arg
+	Tags []any
+}
+
+type "v.io/core/veyron/tools/vrpc/test_base".Struct struct {
+	X int32
+	Y int32
+}
+`
+	if got, want := stdout.String(), wantSig; got != want {
+		t.Errorf("got stdout %q, want %q", got, want)
+	}
+	if got, want := stderr.String(), ""; got != want {
+		t.Errorf("got stderr %q, want %q", got, want)
+	}
+}
+
+func TestMethodSignature(t *testing.T) {
+	name, cleanup := initTest(t)
+	defer cleanup()
+
+	tests := []struct {
+		Method, Want string
+	}{
+		// Spot-check some individual methods.
+		{"EchoByte", `EchoByte(I1 byte) (O1 byte | error)`},
+		{"EchoFloat32", `EchoFloat32(I1 float32) (O1 float32 | error)`},
+		{"XEchoStruct", `
+XEchoStruct(I1 "v.io/core/veyron/tools/vrpc/test_base".Struct) (O1 "v.io/core/veyron/tools/vrpc/test_base".Struct | error)
+
+type "v.io/core/veyron/tools/vrpc/test_base".Struct struct {
+	X int32
+	Y int32
+}
+`},
+	}
+	for _, test := range tests {
+		var stdout, stderr bytes.Buffer
+		cmdVRPC.Init(nil, &stdout, &stderr)
+		if err := cmdVRPC.Execute([]string{"signature", name, test.Method}); err != nil {
+			t.Errorf("%q failed: %v", test.Method, err)
+			continue
+		}
+		if got, want := strings.TrimSpace(stdout.String()), strings.TrimSpace(test.Want); got != want {
+			t.Errorf("got stdout %q, want %q", got, want)
+		}
+		if got, want := stderr.String(), ""; got != want {
+			t.Errorf("got stderr %q, want %q", got, want)
+		}
+	}
+}
+
+func TestCall(t *testing.T) {
+	name, cleanup := initTest(t)
+	defer cleanup()
+
+	tests := []struct {
+		Method, InArgs, Want string
+	}{
+		{"EchoBool", `true`, `true`},
+		{"EchoBool", `false`, `false`},
+		{"EchoFloat32", `1.2`, `float32(1.2)`},
+		{"EchoFloat64", `-3.4`, `float64(-3.4)`},
+		{"EchoInt32", `11`, `int32(11)`},
+		{"EchoInt64", `-22`, `int64(-22)`},
+		{"EchoString", `"abc"`, `"abc"`},
+		{"EchoByte", `33`, `byte(33)`},
+		{"EchoUint32", `44`, `uint32(44)`},
+		{"EchoUint64", `55`, `uint64(55)`},
+		{"XEchoArray", `{1,2}`, `[2]int32{1, 2}`},
+		{"XEchoMap", `{1:"a"}`, `map[int32]string{1: "a"}`},
+		{"XEchoSet", `{1}`, `set[int32]{1}`},
+		{"XEchoSlice", `{1,2}`, `[]int32{1, 2}`},
+		{"XEchoStruct", `{1,2}`, `"v.io/core/veyron/tools/vrpc/test_base".Struct{X: 1, Y: 2}`},
+		{"YMultiArg", `1,2`, `int32(1) int32(2)`},
+		{"YNoArgs", ``, ``},
+		{"ZStream", `2,true`, `<< true
+<< true`},
+	}
+	for _, test := range tests {
+		var stdout, stderr bytes.Buffer
+		cmdVRPC.Init(nil, &stdout, &stderr)
+		if err := cmdVRPC.Execute([]string{"call", name, test.Method, test.InArgs}); err != nil {
+			t.Errorf("%q(%s) failed: %v", test.Method, test.InArgs, err)
+			continue
+		}
+		if got, want := strings.TrimSpace(stdout.String()), strings.TrimSpace(test.Want); got != want {
+			t.Errorf("got stdout %q, want %q", got, want)
+		}
+		if got, want := stderr.String(), ""; got != want {
+			t.Errorf("got stderr %q, want %q", got, want)
+		}
+	}
+}
diff --git a/tools/vrun/vrun.go b/tools/vrun/vrun.go
index cefeebd..8ebdf7c 100644
--- a/tools/vrun/vrun.go
+++ b/tools/vrun/vrun.go
@@ -134,7 +134,7 @@
 		return nil, nil, err
 	}
 	syscall.CloseOnExec(fd)
-	principal, err := agent.NewAgentPrincipal(ctx, fd)
+	principal, err := agent.NewAgentPrincipal(ctx, fd, veyron2.GetClient(ctx))
 	if err != nil {
 		vlog.Errorf("Couldn't connect to principal")
 		return nil, nil, err