Merge "veyron/lib/modules: adding an option to pass Config to a child process"
diff --git a/lib/flags/flags.go b/lib/flags/flags.go
index b8a1473..cb9dde9 100644
--- a/lib/flags/flags.go
+++ b/lib/flags/flags.go
@@ -25,12 +25,12 @@
 	// --veyron.proxy
 	Listen
 	// --veyron.acl (which may be repeated to supply multiple values)
+	// ACL files are named - i.e. --veyron.acl=<name>:<file> with the
+	// name <runtime> reserved for use by the runtime.
 	ACL
 )
 
 const defaultNamespaceRoot = "/proxy.envyor.com:8101"
-const defaultACLName = "veyron"
-const defaultACLFile = "acl.json"
 
 // Flags represents the set of flag groups created by a call to
 // CreateAndRegister.
@@ -132,7 +132,6 @@
 
 func createAndRegisterACLFlags(fs *flag.FlagSet) *ACLFlags {
 	f := &ACLFlags{}
-	f.flag.files = map[string]string{defaultACLName: defaultACLFile}
 	fs.Var(&f.flag, "veyron.acl", "specify an acl file as <name>:<aclfile>")
 	return f
 }
diff --git a/lib/flags/flags_test.go b/lib/flags/flags_test.go
index ee9c32a..3514776 100644
--- a/lib/flags/flags_test.go
+++ b/lib/flags/flags_test.go
@@ -45,10 +45,10 @@
 func TestACLFlags(t *testing.T) {
 	fs := flag.NewFlagSet("test", flag.ContinueOnError)
 	fl := flags.CreateAndRegister(fs, flags.Runtime, flags.ACL)
-	args := []string{"--veyron.acl=veyron:foo.json", "--veyron.acl=bar:bar.json", "--veyron.acl=baz:bar:baz.json"}
+	args := []string{"--veyron.acl=runtime:foo.json", "--veyron.acl=bar:bar.json", "--veyron.acl=baz:bar:baz.json"}
 	fl.Parse(args)
 	aclf := fl.ACLFlags()
-	if got, want := aclf.ACLFile("veyron"), "foo.json"; got != want {
+	if got, want := aclf.ACLFile("runtime"), "foo.json"; got != want {
 		t.Errorf("got %t, want %t", got, want)
 	}
 	if got, want := aclf.ACLFile("bar"), "bar.json"; got != want {
@@ -77,7 +77,7 @@
 	}
 
 	fs = flag.NewFlagSet("test", flag.ContinueOnError)
-	fs.SetOutput(ioutil.Discard)
+	//fs.SetOutput(ioutil.Discard)
 	fl = flags.CreateAndRegister(fs, flags.ACL)
 	args = []string{"--veyron.acl=noname"}
 	err = fl.Parse(args)
@@ -176,7 +176,7 @@
 		t.Errorf("got %q, want %q", got, want)
 	}
 	aclf := fl.ACLFlags()
-	if got, want := aclf.ACLFile("veyron"), "acl.json"; got != want {
+	if got, want := aclf.ACLFile(""), ""; got != want {
 		t.Errorf("got %q, want %q", got, want)
 	}
 }
diff --git a/lib/modules/core/core_test.go b/lib/modules/core/core_test.go
index 23037c0..d8a2a1d 100644
--- a/lib/modules/core/core_test.go
+++ b/lib/modules/core/core_test.go
@@ -241,7 +241,7 @@
 	srvSession := expect.NewSession(t, srv.Stdout(), time.Minute)
 	srvSession.ExpectVar("NAME")
 	addr := srvSession.ExpectVar("ADDR")
-	addr = naming.JoinAddressName(addr, "//")
+	addr = naming.JoinAddressName(addr, "")
 
 	// Resolve an object
 	resolver, err := sh.Start(core.ResolveCommand, nil, rootName+"/"+echoName)
@@ -260,7 +260,7 @@
 	}
 
 	// Resolve to a mount table using a rooted name.
-	addr = naming.JoinAddressName(mountAddrs[mtName], "//echo")
+	addr = naming.JoinAddressName(mountAddrs[mtName], "echo")
 	resolver, err = sh.Start(core.ResolveMTCommand, nil, rootName+"/"+echoName)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
diff --git a/lib/modules/core/echo.go b/lib/modules/core/echo.go
index 8cc7b33..b1b8877 100644
--- a/lib/modules/core/echo.go
+++ b/lib/modules/core/echo.go
@@ -56,10 +56,10 @@
 	if err != nil {
 		return err
 	}
-	if err := server.Serve(mp, disp); err != nil {
+	if err := server.ServeDispatcher(mp, disp); err != nil {
 		return err
 	}
-	fmt.Fprintf(stdout, "NAME=%s\n", naming.MakeTerminal(naming.JoinAddressName(ep.String(), "")))
+	fmt.Fprintf(stdout, "NAME=%s\n", naming.JoinAddressName(ep.String(), ""))
 	fmt.Fprintf(stdout, "ADDR=%s\n", ep.String())
 	fmt.Fprintf(stdout, "PID=%d\n", os.Getpid())
 	modules.WaitForEOF(stdin)
diff --git a/lib/modules/core/mounttable.go b/lib/modules/core/mounttable.go
index b0104d5..7d5d7f8 100644
--- a/lib/modules/core/mounttable.go
+++ b/lib/modules/core/mounttable.go
@@ -58,7 +58,7 @@
 	if err != nil {
 		return fmt.Errorf("server.Listen failed: %s", err)
 	}
-	if err := server.Serve(mp, mt); err != nil {
+	if err := server.ServeDispatcher(mp, mt); err != nil {
 		return fmt.Errorf("root failed: %s", err)
 	}
 	name := naming.JoinAddressName(ep.String(), "")
diff --git a/lib/netstate/netstate.go b/lib/netstate/netstate.go
index 68ee679..ff276b8 100644
--- a/lib/netstate/netstate.go
+++ b/lib/netstate/netstate.go
@@ -10,7 +10,7 @@
 // A simple usage would be:
 //
 //   state, _ := netstate.GetAccessibleIPs()
-//   ipv4 := state.Filter(netstate.IsPublicIPv4)
+//   ipv4 := state.Filter(netstate.IsPublicUnicastIPv4)
 //   // ipv4 will contain all of the public IPv4 addresses, if any.
 //
 // The example policy described above would be implemented using a
diff --git a/lib/signals/signals_test.go b/lib/signals/signals_test.go
index a34c0db..cfe3f16 100644
--- a/lib/signals/signals_test.go
+++ b/lib/signals/signals_test.go
@@ -317,7 +317,7 @@
 	if ep, err = server.Listen(profiles.LocalListenSpec); err != nil {
 		t.Fatalf("Got error: %v", err)
 	}
-	if err := server.Serve("", ipc.LeafDispatcher(node.NewServerConfig(&configServer{ch}), vflag.NewAuthorizerOrDie())); err != nil {
+	if err := server.Serve("", node.NewServerConfig(&configServer{ch}), vflag.NewAuthorizerOrDie()); err != nil {
 		t.Fatalf("Got error: %v", err)
 	}
 	return server, naming.JoinAddressName(ep.String(), ""), ch
diff --git a/profiles/roaming/roaming.go b/profiles/roaming/roaming.go
index a28feea..4aa190f 100644
--- a/profiles/roaming/roaming.go
+++ b/profiles/roaming/roaming.go
@@ -72,7 +72,7 @@
 func (p *profile) Init(rt veyron2.Runtime, publisher *config.Publisher) error {
 	log := rt.Logger()
 
-	rt.ConfigureReservedName("__debug", debug.NewDispatcher(log.LogDir(), sflag.NewAuthorizerOrDie()))
+	rt.ConfigureReservedName(debug.NewDispatcher(log.LogDir(), sflag.NewAuthorizerOrDie()))
 
 	lf := commonFlags.ListenFlags()
 	ListenSpec = ipc.ListenSpec{
diff --git a/profiles/static/static.go b/profiles/static/static.go
index 18b7625..87b1780 100644
--- a/profiles/static/static.go
+++ b/profiles/static/static.go
@@ -58,7 +58,7 @@
 func (p *static) Init(rt veyron2.Runtime, _ *config.Publisher) error {
 	log := rt.Logger()
 
-	rt.ConfigureReservedName("debug", debug.NewDispatcher(log.LogDir(), sflag.NewAuthorizerOrDie()))
+	rt.ConfigureReservedName(debug.NewDispatcher(log.LogDir(), sflag.NewAuthorizerOrDie()))
 
 	lf := commonFlags.ListenFlags()
 	ListenSpec = ipc.ListenSpec{
diff --git a/runtimes/google/ipc/benchmarks/server.go b/runtimes/google/ipc/benchmarks/server.go
index aca9f60..0c41a9b 100644
--- a/runtimes/google/ipc/benchmarks/server.go
+++ b/runtimes/google/ipc/benchmarks/server.go
@@ -1,6 +1,8 @@
 package benchmarks
 
 import (
+	"io"
+
 	sflag "veyron.io/veyron/veyron/security/flag"
 
 	"veyron.io/veyron/veyron2"
@@ -12,21 +14,24 @@
 type impl struct {
 }
 
-func (i *impl) Echo(ctx ipc.ServerContext, payload []byte) ([]byte, error) {
+func (i *impl) Echo(ctx ipc.ServerCall, payload []byte) ([]byte, error) {
 	return payload, nil
 }
 
-func (i *impl) EchoStream(ctx ipc.ServerContext, stream BenchmarkServiceEchoStreamStream) error {
-	rStream := stream.RecvStream()
-	sender := stream.SendStream()
-	for rStream.Advance() {
-		chunk := rStream.Value()
-		if err := sender.Send(chunk); err != nil {
+func (i *impl) EchoStream(ctx ipc.ServerCall) error {
+	for {
+		var chunk []byte
+		if err := ctx.Recv(&chunk); err != nil {
+			if err == io.EOF {
+				break
+			}
+			return err
+		}
+		if err := ctx.Send(chunk); err != nil {
 			return err
 		}
 	}
-
-	return rStream.Err()
+	return nil
 }
 
 // StartServer starts a server that implements the Benchmark service. The
@@ -41,7 +46,7 @@
 	if err != nil {
 		vlog.Fatalf("Listen failed: %v", err)
 	}
-	if err := server.Serve("", ipc.LeafDispatcher(NewServerBenchmark(&impl{}), sflag.NewAuthorizerOrDie())); err != nil {
+	if err := server.Serve("", &impl{}, sflag.NewAuthorizerOrDie()); err != nil {
 		vlog.Fatalf("Serve failed: %v", err)
 	}
 	return naming.JoinAddressName(ep.String(), ""), func() {
diff --git a/runtimes/google/ipc/benchmarks/service.vdl.go b/runtimes/google/ipc/benchmarks/service.vdl.go
index 806dd55..646f0b0 100644
--- a/runtimes/google/ipc/benchmarks/service.vdl.go
+++ b/runtimes/google/ipc/benchmarks/service.vdl.go
@@ -294,9 +294,27 @@
 // It takes a regular server implementing the BenchmarkService
 // interface, and returns a new server stub.
 func NewServerBenchmark(server BenchmarkService) interface{} {
-	return &ServerStubBenchmark{
+	stub := &ServerStubBenchmark{
 		service: server,
 	}
+	var gs _gen_ipc.GlobState
+	var self interface{} = stub
+	// VAllGlobber is implemented by the server object, which is wrapped in
+	// a VDL generated server stub.
+	if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VAllGlobber is implemented by the server object without using a VDL
+	// generated stub.
+	if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VChildrenGlobber is implemented in the server object.
+	if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+		gs.VChildrenGlobber = x
+	}
+	stub.gs = &gs
+	return stub
 }
 
 // clientStubBenchmark implements Benchmark.
@@ -370,6 +388,7 @@
 // the requirements of veyron2/ipc.ReflectInvoker.
 type ServerStubBenchmark struct {
 	service BenchmarkService
+	gs      *_gen_ipc.GlobState
 }
 
 func (__gen_s *ServerStubBenchmark) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -430,6 +449,10 @@
 	return
 }
 
+func (__gen_s *ServerStubBenchmark) VGlob() *_gen_ipc.GlobState {
+	return __gen_s.gs
+}
+
 func (__gen_s *ServerStubBenchmark) Echo(call _gen_ipc.ServerCall, Payload []byte) (reply []byte, err error) {
 	reply, err = __gen_s.service.Echo(call, Payload)
 	return
diff --git a/runtimes/google/ipc/cancel_test.go b/runtimes/google/ipc/cancel_test.go
index cc30a2f..0ad572c 100644
--- a/runtimes/google/ipc/cancel_test.go
+++ b/runtimes/google/ipc/cancel_test.go
@@ -73,7 +73,7 @@
 		stop:      s.Stop,
 	}
 
-	if err := s.Serve(name, ipc.LeafDispatcher(c, fakeAuthorizer(0))); err != nil {
+	if err := s.Serve(name, c, fakeAuthorizer(0)); err != nil {
 		return nil, err
 	}
 
diff --git a/runtimes/google/ipc/client.go b/runtimes/google/ipc/client.go
index 4e12fb9..e828b51 100644
--- a/runtimes/google/ipc/client.go
+++ b/runtimes/google/ipc/client.go
@@ -233,7 +233,7 @@
 
 // tryCall makes a single attempt at a call.
 func (c *client) tryCall(ctx context.T, name, method string, args []interface{}, opts []ipc.CallOpt) (ipc.Call, verror.E) {
-	ctx, _ = vtrace.WithNewSpan(ctx, fmt.Sprintf("Client Call: %s.%s", name, method))
+	ctx, _ = vtrace.WithNewSpan(ctx, fmt.Sprintf("<client>\"%s\".%s", name, method))
 
 	_, serverPattern, name := splitObjectName(name)
 
diff --git a/runtimes/google/ipc/debug_test.go b/runtimes/google/ipc/debug_test.go
index e05c185..8286463 100644
--- a/runtimes/google/ipc/debug_test.go
+++ b/runtimes/google/ipc/debug_test.go
@@ -36,12 +36,12 @@
 	defer sm.Shutdown()
 	ns := tnaming.NewSimpleNamespace()
 
-	server, err := InternalNewServer(testContext(), sm, ns, options.ReservedNameDispatcher{"__debug", debugDisp}, vc.LocalPrincipal{pserver})
+	server, err := InternalNewServer(testContext(), sm, ns, options.ReservedNameDispatcher{debugDisp}, vc.LocalPrincipal{pserver})
 	if err != nil {
 		t.Fatalf("InternalNewServer failed: %v", err)
 	}
 	defer server.Stop()
-	server.Serve("", ipc.LeafDispatcher(&testObject{}, nil))
+	server.Serve("", &testObject{}, nil)
 	ep, err := server.Listen(listenSpec)
 	if err != nil {
 		t.Fatalf("server.Listen failed: %v", err)
diff --git a/runtimes/google/ipc/flow_test.go b/runtimes/google/ipc/flow_test.go
index f121968..0d608bb 100644
--- a/runtimes/google/ipc/flow_test.go
+++ b/runtimes/google/ipc/flow_test.go
@@ -82,6 +82,10 @@
 	return nil, errors.New(inv.suffix)
 }
 
+func (inv closureInvoker) VGlob() *ipc.GlobState {
+	return nil
+}
+
 // echoInvoker serves a method that takes a string and echoes it:
 //    func(_ ServerCall, arg string) (string, error)
 type echoInvoker struct{ suffix string }
@@ -100,6 +104,10 @@
 	return []interface{}{result}, nil
 }
 
+func (inv echoInvoker) VGlob() *ipc.GlobState {
+	return nil
+}
+
 func TestFlowClientServer(t *testing.T) {
 	type v []interface{}
 	type testcase struct {
diff --git a/runtimes/google/ipc/full_test.go b/runtimes/google/ipc/full_test.go
index cd83055..2c721d9 100644
--- a/runtimes/google/ipc/full_test.go
+++ b/runtimes/google/ipc/full_test.go
@@ -180,10 +180,10 @@
 	}
 	vlog.VI(1).Info("server.Serve")
 	disp := testServerDisp{ts}
-	if err := server.Serve("mountpoint/server", disp); err != nil {
+	if err := server.ServeDispatcher("mountpoint/server", disp); err != nil {
 		t.Errorf("server.Publish failed: %v", err)
 	}
-	if err := server.Serve("mountpoint/discharger", disp); err != nil {
+	if err := server.AddName("mountpoint/discharger"); err != nil {
 		t.Errorf("server.Publish for discharger failed: %v", err)
 	}
 	return ep, server
@@ -208,7 +208,7 @@
 	verifyMount(t, ns, n1)
 
 	// publish a second name
-	if err := server.Serve(n2, nil); err != nil {
+	if err := server.AddName(n2); err != nil {
 		t.Errorf("server.Serve failed: %v", err)
 	}
 	verifyMount(t, ns, n2)
@@ -221,7 +221,7 @@
 	verifyMountMissing(t, ns, n2)
 
 	// Check that we can no longer serve after Stop.
-	err := server.Serve("name doesn't matter", nil)
+	err := server.AddName("name doesn't matter")
 	if err == nil || err.Error() != "ipc: server is stopped" {
 		t.Errorf("either no error, or a wrong error was returned: %v", err)
 	}
@@ -267,7 +267,7 @@
 	return err == nil || strings.Index(err.Error(), pattern) >= 0
 }
 
-func TestMultipleCallsToServe(t *testing.T) {
+func TestMultipleCallsToServeAndName(t *testing.T) {
 	sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
 	ns := tnaming.NewSimpleNamespace()
 	server, err := InternalNewServer(testContext(), sm, ns, vc.LocalPrincipal{sectest.NewPrincipal()})
@@ -280,8 +280,8 @@
 	}
 
 	disp := &testServerDisp{&testServer{}}
-	if err := server.Serve("mountpoint/server", disp); err != nil {
-		t.Errorf("server.Publish failed: %v", err)
+	if err := server.ServeDispatcher("mountpoint/server", disp); err != nil {
+		t.Errorf("server.ServeDispatcher failed: %v", err)
 	}
 
 	n1 := "mountpoint/server"
@@ -291,17 +291,35 @@
 
 	verifyMount(t, ns, n1)
 
-	if err := server.Serve(n2, disp); err != nil {
-		t.Errorf("server.Serve failed: %v", err)
+	if server.ServeDispatcher(n2, disp) == nil {
+		t.Errorf("server.ServeDispatcher should have failed")
 	}
-	if err := server.Serve(n3, nil); err != nil {
-		t.Errorf("server.Serve failed: %v", err)
+
+	if err := server.Serve(n2, &testServer{}, nil); err == nil {
+		t.Errorf("server.Serve should have failed")
+	}
+
+	if err := server.AddName(n3); err != nil {
+		t.Errorf("server.AddName failed: %v", err)
+	}
+
+	if err := server.AddName(n3); err != nil {
+		t.Errorf("server.AddName failed: %v", err)
 	}
 	verifyMount(t, ns, n2)
 	verifyMount(t, ns, n3)
 
-	if err := server.Serve(n4, &testServerDisp{&testServer{}}); err == nil {
-		t.Errorf("server.Serve should have failed")
+	if err := server.RemoveName(n1); err != nil {
+		t.Errorf("server.RemoveName failed: %v", err)
+	}
+	verifyMountMissing(t, ns, n1)
+
+	if err := server.RemoveName("some randome name"); err == nil {
+		t.Errorf("server.RemoveName should have failed")
+	}
+
+	if err := server.ServeDispatcher(n4, &testServerDisp{&testServer{}}); err == nil {
+		t.Errorf("server.ServeDispatcher should have failed")
 	}
 	verifyMountMissing(t, ns, n4)
 
@@ -602,7 +620,7 @@
 	}
 
 	var tester dischargeImpetusTester
-	if err := server.Serve("mountpoint", &tester); err != nil {
+	if err := server.ServeDispatcher("mountpoint", &tester); err != nil {
 		t.Fatal(err)
 	}
 
@@ -1048,7 +1066,7 @@
 		t.Fatalf("server.Listen failed: %v", err)
 	}
 	disp := &testServerDisp{&testServer{}}
-	if err := server.Serve("mp/server", disp); err != nil {
+	if err := server.ServeDispatcher("mp/server", disp); err != nil {
 		t.Fatalf("server.Serve failed: %v", err)
 	}
 	client, err := InternalNewClient(sm, ns, options.VCSecurityNone)
@@ -1094,8 +1112,6 @@
 	}{
 		{"[foo/bar]", "", "foo/bar", ""},
 		{"[x/y/...]/", "x/y/...", "", "/"},
-		{"[foo/...]//", "", "foo/...", "//"},
-		{"[foo]//abc@@/foo", "", "foo", "//abc@@/foo"},
 		{"[foo]a", "", "foo", "a"},
 		{"[foo]/a", "foo", "", "/a"},
 		{"[foo]/a/[bar]", "foo", "bar", "/a"},
diff --git a/runtimes/google/ipc/server.go b/runtimes/google/ipc/server.go
index 44ae7ab..18d8684 100644
--- a/runtimes/google/ipc/server.go
+++ b/runtimes/google/ipc/server.go
@@ -9,7 +9,6 @@
 	"sync"
 	"time"
 
-	"veyron.io/veyron/veyron2"
 	"veyron.io/veyron/veyron2/config"
 	"veyron.io/veyron/veyron2/context"
 	"veyron.io/veyron/veyron2/ipc"
@@ -47,7 +46,11 @@
 	stoppedChan      chan struct{}                     // closed when the server has been stopped.
 	ns               naming.Namespace
 	servesMountTable bool
-	reservedOpt      options.ReservedNameDispatcher
+	// TODO(cnicolaou): remove this when the publisher tracks published names
+	// and can return an appropriate error for RemoveName on a name that
+	// wasn't 'Added' for this server.
+	names       map[string]struct{}
+	reservedOpt options.ReservedNameDispatcher
 	// TODO(cnicolaou): add roaming stats to ipcStats
 	stats *ipcStats // stats for this server.
 }
@@ -388,13 +391,9 @@
 	return ep, nil
 }
 
+// TODO(cnicolaou): Take this out or make the ServesMountTable bit work in the endpoint.
 func (s *server) publishEP(ep *inaming.Endpoint, servesMountTable bool) string {
 	var name string
-	if !s.servesMountTable {
-		// Make sure that client MountTable code doesn't try and
-		// ResolveStep past this final address.
-		name = "//"
-	}
 	ep.IsMountTable = servesMountTable
 	return naming.JoinAddressName(ep.String(), name)
 }
@@ -533,51 +532,66 @@
 	}
 }
 
-func (s *server) Serve(name string, obj interface{}) error {
+func (s *server) Serve(name string, obj interface{}, authorizer security.Authorizer) error {
 	if obj == nil {
-		// nil is an allowed value for obj.
-		return s.ServeDispatcher(name, ipc.Dispatcher(nil))
+		// The ReflectInvoker inside the LeafDispatcher will panic
+		// if called for a nil value.
+		return fmt.Errorf("A nil object is not allowed")
 	}
-	// TRANSITION: this will be disallowed when the transition is complete.
-	if disp, ok := obj.(ipc.Dispatcher); ok {
-		return s.ServeDispatcher(name, disp)
-	}
-	// TRANSITION: We may fail the dispatcher type test, but still be a
-	// dispatcher becase our Lookup method returns ipc.Invoker and not a
-	// raw object. This code here will detect that case and panic as an aid
-	// to catching these cases early.
-	typ := reflect.TypeOf(obj)
-	if lookup, found := typ.MethodByName("Lookup"); found {
-		if lookup.Type.NumIn() == 3 && lookup.Type.NumOut() == 3 {
-			inv := lookup.Type.Out(0)
-			if inv.Name() == "Invoker" {
-				panic(fmt.Sprintf("%q has a Lookup that returns an Invoker", lookup.Name))
-			}
-		}
-	}
-	// TRANSITION: this will go away in the transition.
-	panic("should never get here")
+	return s.ServeDispatcher(name, ipc.LeafDispatcher(obj, authorizer))
 }
 
 func (s *server) ServeDispatcher(name string, disp ipc.Dispatcher) error {
-	defer vlog.LogCall()()
 	s.Lock()
 	defer s.Unlock()
 	if s.stopped {
 		return errServerStopped
 	}
-	if s.disp != nil && disp != nil && s.disp != disp {
-		return fmt.Errorf("attempt to change dispatcher")
+	if disp == nil {
+		return fmt.Errorf("A nil dispacther is not allowed")
 	}
-	if disp != nil {
-		s.disp = disp
+	if s.disp != nil {
+		return fmt.Errorf("Serve or ServeDispatcher has already been called")
 	}
+	s.disp = disp
+	s.names = make(map[string]struct{})
 	if len(name) > 0 {
 		s.publisher.AddName(name)
+		s.names[name] = struct{}{}
 	}
 	return nil
 }
 
+func (s *server) AddName(name string) error {
+	s.Lock()
+	defer s.Unlock()
+	if s.stopped {
+		return errServerStopped
+	}
+	if len(name) == 0 {
+		return fmt.Errorf("empty name")
+	}
+	s.publisher.AddName(name)
+	// TODO(cnicolaou): remove this map when the publisher's RemoveName
+	// method returns an error.
+	s.names[name] = struct{}{}
+	return nil
+}
+
+func (s *server) RemoveName(name string) error {
+	s.Lock()
+	defer s.Unlock()
+	if s.stopped {
+		return errServerStopped
+	}
+	if _, present := s.names[name]; !present {
+		return fmt.Errorf("%q has not been previously used for this server", name)
+	}
+	s.publisher.RemoveName(name)
+	delete(s.names, name)
+	return nil
+}
+
 func (s *server) Stop() error {
 	defer vlog.LogCall()()
 	s.Lock()
@@ -667,11 +681,10 @@
 func newFlowServer(flow stream.Flow, server *server) *flowServer {
 	server.Lock()
 	disp := server.disp
-	runtime := veyron2.RuntimeFromContext(server.ctx)
 	server.Unlock()
 
 	return &flowServer{
-		T:      InternalNewContext(runtime),
+		T:      server.ctx,
 		server: server,
 		disp:   disp,
 		// TODO(toddw): Support different codecs
@@ -792,15 +805,15 @@
 	if verr != nil {
 		// We don't know what the ipc call was supposed to be, but we'll create
 		// a placeholder span so we can capture annotations.
-		fs.T, _ = ivtrace.WithNewSpan(fs, "Failed IPC Call")
+		fs.T, _ = ivtrace.WithNewSpan(fs, fmt.Sprintf("\"%s\".UNKNOWN", fs.Name()))
 		return nil, verr
 	}
 	fs.method = req.Method
 
 	// TODO(mattr): Currently this allows users to trigger trace collection
 	// on the server even if they will not be allowed to collect the
-	// results later.  This might be consider a DOS vector.
-	spanName := fmt.Sprintf("Server Call: %s.%s", fs.Name(), fs.Method())
+	// results later.  This might be considered a DOS vector.
+	spanName := fmt.Sprintf("\"%s\".%s", fs.Name(), fs.Method())
 	fs.T, _ = ivtrace.WithContinuedSpan(fs, spanName, req.TraceRequest)
 
 	var cancel context.CancelFunc
@@ -890,17 +903,19 @@
 // with ipc.DebugKeyword, we use the internal debug dispatcher to look up the
 // invoker. Otherwise, and we use the server's dispatcher. The (stripped) name
 // and dispatch suffix are also returned.
-// TODO(cnicolaou): change this back returning in ipc.Invoker in the pt2 CL.
 func (fs *flowServer) lookup(name, method string) (ipc.Invoker, security.Authorizer, string, verror.E) {
 	name = strings.TrimLeft(name, "/")
 	if method == "Glob" && len(name) == 0 {
-		return ipc.ReflectInvoker(&globInvoker{fs.reservedOpt.Prefix, fs}), &acceptAllAuthorizer{}, name, nil
+		return ipc.ReflectInvoker(&globInvoker{"__debug", fs}), &acceptAllAuthorizer{}, name, nil
 	}
 	disp := fs.disp
-	prefix := fs.reservedOpt.Prefix
-	if len(prefix) > 0 && (name == prefix || strings.HasPrefix(name, prefix+"/")) {
-		name = strings.TrimPrefix(name, prefix)
-		name = strings.TrimLeft(name, "/")
+	if strings.HasPrefix(name, naming.ReservedNamePrefix) {
+		parts := strings.SplitN(name, "/", 2)
+		if len(parts) > 1 {
+			name = parts[1]
+		} else {
+			name = ""
+		}
 		disp = fs.reservedOpt.Dispatcher
 	}
 
diff --git a/runtimes/google/ipc/server_test.go b/runtimes/google/ipc/server_test.go
index 8a8020f..11959f0 100644
--- a/runtimes/google/ipc/server_test.go
+++ b/runtimes/google/ipc/server_test.go
@@ -153,7 +153,7 @@
 	if _, err := server.Listen(spec); err != nil {
 		t.Fatal(err)
 	}
-	if err := server.Serve("mountpoint/server", testServerDisp{&testServer{}}); err != nil {
+	if err := server.ServeDispatcher("mountpoint/server", testServerDisp{&testServer{}}); err != nil {
 		t.Fatal(err)
 	}
 	verifyMount(t, ns, name)
@@ -200,7 +200,7 @@
 		return fmt.Errorf("InternalNewServer failed: %v", err)
 	}
 	disp := testServerDisp{new(testServer)}
-	if err := server.Serve("server", disp); err != nil {
+	if err := server.ServeDispatcher("server", disp); err != nil {
 		return fmt.Errorf("server.Register failed: %v", err)
 	}
 	spec := listenSpec
diff --git a/runtimes/google/lib/publisher/publisher.go b/runtimes/google/lib/publisher/publisher.go
index 63fad95..eece0f7 100644
--- a/runtimes/google/lib/publisher/publisher.go
+++ b/runtimes/google/lib/publisher/publisher.go
@@ -13,6 +13,9 @@
 	"veyron.io/veyron/veyron2/vlog"
 )
 
+// TODO(cnicolaou): have the done channel return an error so
+// that the publisher calls can return errors also.
+
 // Publisher manages the publishing of servers in mounttable.
 type Publisher interface {
 	// AddServer adds a new server to be mounted.
@@ -21,6 +24,8 @@
 	RemoveServer(server string)
 	// AddName adds a new name for all servers to be mounted as.
 	AddName(name string)
+	// RemoveName removes a name.
+	RemoveName(name string)
 	// Published returns the published names rooted at the mounttable.
 	Published() []string
 	// DebugString returns a string representation of the publisher
@@ -58,11 +63,16 @@
 	done   chan struct{} // closed when the cmd is done
 }
 
-type nameCmd struct {
+type addNameCmd struct {
 	name string        // name to add
 	done chan struct{} // closed when the cmd is done
 }
 
+type removeNameCmd struct {
+	name string        // name to remove
+	done chan struct{} // closed when the cmd is done
+}
+
 type debugCmd chan string // debug string is sent when the cmd is done
 
 type publishedCmd chan []string // published names are sent when cmd is done
@@ -104,7 +114,14 @@
 
 func (p *publisher) AddName(name string) {
 	done := make(chan struct{})
-	if p.sendCmd(nameCmd{name, done}) {
+	if p.sendCmd(addNameCmd{name, done}) {
+		<-done
+	}
+}
+
+func (p *publisher) RemoveName(name string) {
+	done := make(chan struct{})
+	if p.sendCmd(removeNameCmd{name, done}) {
 		<-done
 	}
 }
@@ -167,9 +184,12 @@
 			case removeServerCmd:
 				state.removeServer(tcmd.server)
 				close(tcmd.done)
-			case nameCmd:
+			case addNameCmd:
 				state.addName(tcmd.name)
 				close(tcmd.done)
+			case removeNameCmd:
+				state.removeName(tcmd.name)
+				close(tcmd.done)
 			case publishedCmd:
 				tcmd <- state.published()
 				close(tcmd)
@@ -190,11 +210,11 @@
 	ctx      context.T
 	ns       naming.Namespace
 	period   time.Duration
-	deadline time.Time       // deadline for the next sync call
-	names    []string        // names that have been added
-	servers  map[string]bool // servers that have been added, true
+	deadline time.Time                 // deadline for the next sync call
+	names    map[string]bool           // names that have been added
+	servers  map[string]bool           // servers that have been added, true
+	mounts   map[mountKey]*mountStatus // map each (name,server) to its status
 	//   if server is a mount table server
-	mounts map[mountKey]*mountStatus // map each (name,server) to its status
 }
 
 type mountKey struct {
@@ -215,6 +235,7 @@
 		ns:       ns,
 		period:   period,
 		deadline: time.Now().Add(period),
+		names:    make(map[string]bool),
 		servers:  make(map[string]bool),
 		mounts:   make(map[mountKey]*mountStatus),
 	}
@@ -227,12 +248,10 @@
 func (ps *pubState) addName(name string) {
 	// Each non-dup name that is added causes new mounts to be created for all
 	// existing servers.
-	for _, n := range ps.names {
-		if n == name {
-			return
-		}
+	if ps.names[name] {
+		return
 	}
-	ps.names = append(ps.names, name)
+	ps.names[name] = true
 	for server, servesMT := range ps.servers {
 		status := new(mountStatus)
 		ps.mounts[mountKey{name, server}] = status
@@ -240,12 +259,24 @@
 	}
 }
 
+func (ps *pubState) removeName(name string) {
+	if !ps.names[name] {
+		return
+	}
+	for server, _ := range ps.servers {
+		if status, exists := ps.mounts[mountKey{name, server}]; exists {
+			ps.unmount(name, server, status)
+		}
+	}
+	delete(ps.names, name)
+}
+
 func (ps *pubState) addServer(server string, servesMT bool) {
 	// Each non-dup server that is added causes new mounts to be created for all
 	// existing names.
-	if _, exists := ps.servers[server]; !exists {
+	if !ps.servers[server] {
 		ps.servers[server] = servesMT
-		for _, name := range ps.names {
+		for name, _ := range ps.names {
 			status := new(mountStatus)
 			ps.mounts[mountKey{name, server}] = status
 			ps.mount(name, server, status, servesMT)
@@ -258,7 +289,7 @@
 		return
 	}
 	delete(ps.servers, server)
-	for _, name := range ps.names {
+	for name, _ := range ps.names {
 		if status, exists := ps.mounts[mountKey{name, server}]; exists {
 			ps.unmount(name, server, status)
 		}
@@ -310,7 +341,7 @@
 
 func (ps *pubState) published() []string {
 	var ret []string
-	for _, name := range ps.names {
+	for name, _ := range ps.names {
 		e, err := ps.ns.ResolveToMountTableX(ps.ctx, name)
 		if err != nil {
 			vlog.Errorf("ipc pub: couldn't resolve %v to mount table: %v", name, err)
@@ -327,6 +358,7 @@
 	return ret
 }
 
+// TODO(toddw): sort the names/servers so that the output order is stable.
 func (ps *pubState) debugString() string {
 	l := make([]string, 2+len(ps.mounts))
 	l = append(l, fmt.Sprintf("Publisher period:%v deadline:%v", ps.period, ps.deadline))
diff --git a/runtimes/google/lib/publisher/publisher_test.go b/runtimes/google/lib/publisher/publisher_test.go
new file mode 100644
index 0000000..720f16f
--- /dev/null
+++ b/runtimes/google/lib/publisher/publisher_test.go
@@ -0,0 +1,58 @@
+package publisher_test
+
+import (
+	"reflect"
+	"sort"
+	"testing"
+	"time"
+
+	"veyron.io/veyron/veyron2/context"
+	"veyron.io/veyron/veyron2/naming"
+
+	iipc "veyron.io/veyron/veyron/runtimes/google/ipc"
+	"veyron.io/veyron/veyron/runtimes/google/lib/publisher"
+	tnaming "veyron.io/veyron/veyron/runtimes/google/testing/mocks/naming"
+	"veyron.io/veyron/veyron/runtimes/google/testing/mocks/runtime"
+	"veyron.io/veyron/veyron/runtimes/google/vtrace"
+)
+
+func testContext() context.T {
+	ctx := iipc.InternalNewContext(&runtime.PanicRuntime{})
+	ctx, _ = vtrace.WithNewSpan(ctx, "")
+	ctx, _ = ctx.WithDeadline(time.Now().Add(20 * time.Second))
+	return ctx
+}
+
+func resolve(t *testing.T, ns naming.Namespace, name string) []string {
+	servers, err := ns.Resolve(testContext(), name)
+	if err != nil {
+		t.Fatalf("failed to resolve %q", name)
+	}
+	return servers
+}
+
+func TestAddAndRemove(t *testing.T) {
+	ns := tnaming.NewSimpleNamespace()
+	pub := publisher.New(testContext(), ns, time.Second)
+	pub.AddName("foo")
+	pub.AddServer("foo-addr", false)
+	if got, want := resolve(t, ns, "foo"), []string{"foo-addr"}; !reflect.DeepEqual(got, want) {
+		t.Errorf("got %q, want %q", got, want)
+	}
+	pub.AddServer("bar-addr", false)
+	got, want := resolve(t, ns, "foo"), []string{"bar-addr", "foo-addr"}
+	sort.Strings(got)
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("got %q, want %q", got, want)
+	}
+	pub.AddName("baz")
+	got = resolve(t, ns, "baz")
+	sort.Strings(got)
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("got %q, want %q", got, want)
+	}
+	pub.RemoveName("foo")
+	if _, err := ns.Resolve(testContext(), "foo"); err == nil {
+		t.Errorf("expected an error")
+	}
+}
diff --git a/runtimes/google/naming/namespace/all_test.go b/runtimes/google/naming/namespace/all_test.go
index b803577..da85431 100644
--- a/runtimes/google/naming/namespace/all_test.go
+++ b/runtimes/google/naming/namespace/all_test.go
@@ -193,13 +193,10 @@
 	if err != nil {
 		boom(t, "Failed to Listen: %s", err)
 	}
-	if err := s.Serve(mountPoint, disp); err != nil {
+	if err := s.ServeDispatcher(mountPoint, disp); err != nil {
 		boom(t, "Failed to serve mount table at %s: %s", mountPoint, err)
 	}
 	name := naming.JoinAddressName(ep.String(), "")
-	if !mt {
-		name = name + "//"
-	}
 	return &serverEntry{mountPoint: mountPoint, server: s, endpoint: ep, name: name}
 }
 
@@ -291,21 +288,17 @@
 	// as the address portion of the terminal name for those mounttables.
 	testResolveToMountTable(t, r, ns, "", root.name)
 	for _, m := range []string{mt2MP, mt3MP, mt5MP} {
-		rootMT := naming.MakeTerminal(naming.Join(root.name, m))
+		rootMT := naming.Join(root.name, m)
 		// All of these mount tables are hosted by the root mount table
 		testResolveToMountTable(t, r, ns, m, rootMT)
-		testResolveToMountTable(t, r, ns, "//"+m, rootMT)
 
 		// The server registered for each mount point is a mount table
 		testResolve(t, r, ns, m, mts[m].name)
 
 		// ResolveToMountTable will walk through to the sub MountTables
 		mtbar := naming.Join(m, "bar")
-		subMT := naming.MakeTerminal(naming.Join(mts[m].name, "bar"))
+		subMT := naming.Join(mts[m].name, "bar")
 		testResolveToMountTable(t, r, ns, mtbar, subMT)
-
-		// ResolveToMountTable will not walk through if the name is terminal
-		testResolveToMountTable(t, r, ns, "//"+mtbar, naming.Join(rootMT, "bar"))
 	}
 
 	for _, j := range []string{j1MP, j2MP, j3MP} {
@@ -343,7 +336,7 @@
 		boom(t, "Failed to Mount %s: %s", mt2a, err)
 	}
 
-	mt2mt := naming.MakeTerminal(naming.Join(mts[mt2MP].name, "a"))
+	mt2mt := naming.Join(mts[mt2MP].name, "a")
 	// The mt2/a is served by the mt2 mount table
 	testResolveToMountTable(t, r, ns, mt2a, mt2mt)
 	// The server for mt2a is mt3server from the second mount above.
@@ -365,9 +358,9 @@
 
 	// We now have 3 mount tables prepared to serve mt2/a
 	testResolveToMountTable(t, r, ns, "mt2/a",
-		mts[mt2MP].name+"//a",
-		mts[mt4MP].name+"//a",
-		mts[mt5MP].name+"//a")
+		naming.JoinAddressName(mts[mt2MP].name, "a"),
+		naming.JoinAddressName(mts[mt4MP].name, "a"),
+		naming.JoinAddressName(mts[mt5MP].name, "a"))
 	testResolve(t, r, ns, "mt2", mts[mt2MP].name, mts[mt4MP].name, mts[mt5MP].name)
 }
 
@@ -388,10 +381,11 @@
 	}
 
 	testResolveToMountTable(t, r, ns, "mt4/foo",
-		mts[mt4MP].name+"//foo")
+		naming.JoinAddressName(mts[mt4MP].name, "foo"))
 	testResolveToMountTable(t, r, ns, "mt4/foo/bar",
-		mts["mt4/foo"].name+"//bar")
-	testResolveToMountTable(t, r, ns, "mt4/foo/baz", mts["mt4/foo"].name+"//baz")
+		naming.JoinAddressName(mts["mt4/foo"].name, "bar"))
+	testResolveToMountTable(t, r, ns, "mt4/foo/baz",
+		naming.JoinAddressName(mts["mt4/foo"].name, "baz"))
 }
 
 // TestServers tests invoking RPCs on simple servers
@@ -413,8 +407,8 @@
 		jokes[gj] = runServer(t, r, disp, globalName)
 		testResolve(t, r, ns, "mt4/"+j, jokes[gj].name)
 		knockKnock(t, r, "mt4/"+j)
-		testResolveToMountTable(t, r, ns, "mt4/"+j, naming.MakeTerminal(globalName))
-		testResolveToMountTable(t, r, ns, "mt4/"+j+"/garbage", naming.MakeTerminal(globalName+"/garbage"))
+		testResolveToMountTable(t, r, ns, "mt4/"+j, globalName)
+		testResolveToMountTable(t, r, ns, "mt4/"+j+"/garbage", globalName+"/garbage")
 	}
 }
 
diff --git a/runtimes/google/naming/namespace/cache.go b/runtimes/google/naming/namespace/cache.go
index be7b469..8d5293f 100644
--- a/runtimes/google/naming/namespace/cache.go
+++ b/runtimes/google/naming/namespace/cache.go
@@ -45,15 +45,6 @@
 	return false
 }
 
-// normalize removes any single trailing slash.  Added for idiots who seem to
-// like adding trailing slashes.
-func normalize(name string) string {
-	if strings.HasSuffix(name, "//") {
-		return name
-	}
-	return strings.TrimSuffix(name, "/")
-}
-
 // randomDrop randomly removes one cache entry.  Assumes we've already locked the cache.
 func (c *ttlCache) randomDrop() {
 	n := rand.Intn(len(c.entries))
@@ -90,6 +81,7 @@
 	// Remove suffix.  We only care about the name that gets us
 	// to the mounttable from the last mounttable.
 	prefix = normalize(prefix)
+	entry.Name = normalize(entry.Name)
 	prefix = naming.TrimSuffix(prefix, entry.Name)
 	// Copy the entry.
 	var ce naming.MountEntry
@@ -97,8 +89,6 @@
 		ce.Servers = append(ce.Servers, s)
 	}
 	ce.SetServesMountTable(entry.ServesMountTable())
-	// All keys must be terminal.
-	prefix = naming.MakeTerminal(prefix)
 	c.Lock()
 	// Enforce an upper limit on the cache size.
 	if len(c.entries) >= maxCacheEntries {
diff --git a/runtimes/google/naming/namespace/cache_test.go b/runtimes/google/naming/namespace/cache_test.go
index 0f4cffd..e12cd69 100644
--- a/runtimes/google/naming/namespace/cache_test.go
+++ b/runtimes/google/naming/namespace/cache_test.go
@@ -46,8 +46,8 @@
 		{"/h2//c/d", "d", "/h3", true},
 		{"/h3//d", "", "/h4:1234", true},
 		{"/notintcache", "", "", false},
-		{"/h1//a/b/f//g", "f//g", "/h2", true},
-		{"/h3//d//e", "//e", "/h4:1234", true},
+		{"/h1//a/b/f//g", "f/g", "/h2", true},
+		{"/h3//d//e", "e", "/h4:1234", true},
 	}
 	for _, p := range tests {
 		e, err := c.lookup(p.name)
diff --git a/runtimes/google/naming/namespace/namespace.go b/runtimes/google/naming/namespace/namespace.go
index 1b966d7..7458858 100644
--- a/runtimes/google/naming/namespace/namespace.go
+++ b/runtimes/google/naming/namespace/namespace.go
@@ -1,6 +1,7 @@
 package namespace
 
 import (
+	"strings"
 	"sync"
 	"time"
 
@@ -96,6 +97,7 @@
 // rootName 'roots' a name: if name is not a rooted name, it prepends the root
 // mounttable's OA.
 func (ns *namespace) rootName(name string) []string {
+	name = normalize(name)
 	if address, _ := naming.SplitAddressName(name); len(address) == 0 {
 		var ret []string
 		ns.RLock()
@@ -110,6 +112,7 @@
 
 // rootMountEntry 'roots' a name creating a mount entry for the name.
 func (ns *namespace) rootMountEntry(name string) (*naming.MountEntry, bool) {
+	name = normalize(name)
 	e := new(naming.MountEntry)
 	expiration := time.Now().Add(time.Hour) // plenty of time for a call
 	address, suffix := naming.SplitAddressName(name)
@@ -178,3 +181,21 @@
 	}
 	return nil
 }
+
+// normalize removes any single trailing slash and compresses
+// multiple consecutive slashes to one.
+// TODO(p): Transitionally it also removes a leading double
+// slash that used to mean something but doesn't any more.
+// I should remove that in a week or so when we've killed off
+// all code inserting this double slash.
+func normalize(name string) string {
+	// Eradicate leading double slash (for now).  Eventually we
+	// should get ris of this.
+	name = strings.TrimPrefix(name, "//")
+	// Eradicate duplicate slashes and trailing slashes.  We
+	// could use path.Clean but it has other side effects.
+	for strings.Contains(name, "//") {
+		name = strings.Replace(name, "//", "/", -1)
+	}
+	return strings.TrimSuffix(name, "/")
+}
diff --git a/runtimes/google/naming/namespace/resolve.go b/runtimes/google/naming/namespace/resolve.go
index 5943b6a..1d6e572 100644
--- a/runtimes/google/naming/namespace/resolve.go
+++ b/runtimes/google/naming/namespace/resolve.go
@@ -58,12 +58,7 @@
 }
 
 func terminal(e *naming.MountEntry) bool {
-	for _, s := range e.Servers {
-		if !naming.Terminal(naming.JoinAddressName(s.Server, e.Name)) {
-			return false
-		}
-	}
-	return true
+	return len(e.Name) == 0
 }
 
 // ResolveX implements veyron2/naming.Namespace.
@@ -130,7 +125,7 @@
 	}
 	last := e
 	for remaining := ns.maxResolveDepth; remaining > 0; remaining-- {
-		vlog.VI(2).Infof("ResolveToMountTable(%s) loop %v", name, e)
+		vlog.VI(2).Infof("ResolveToMountTableX(%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.
@@ -245,7 +240,6 @@
 		// Walk the cache as we would in a resolution.  Unlike a resolution, we have to follow
 		// all branches since we want to flush all entries at which we might end up whereas in a resolution,
 		// we stop with the first branch that works.
-		n := naming.MakeTerminal(n)
 		if e, err := ns.resolutionCache.lookup(n); err == nil {
 			// Recurse.
 			for _, s := range e.Servers {
diff --git a/runtimes/google/rt/ipc.go b/runtimes/google/rt/ipc.go
index 4923176..5c115f8 100644
--- a/runtimes/google/rt/ipc.go
+++ b/runtimes/google/rt/ipc.go
@@ -94,7 +94,7 @@
 	// Add the option that provides the principal to the server.
 	otherOpts = append(otherOpts, vc.LocalPrincipal{rt.principal})
 	if rt.reservedDisp != nil {
-		ropts := options.ReservedNameDispatcher{rt.reservedPrefix, rt.reservedDisp}
+		ropts := options.ReservedNameDispatcher{rt.reservedDisp}
 		otherOpts = append(otherOpts, ropts)
 		otherOpts = append(otherOpts, rt.reservedOpts...)
 	}
diff --git a/runtimes/google/rt/ipc_test.go b/runtimes/google/rt/ipc_test.go
index 4c6cc6c..a29098b 100644
--- a/runtimes/google/rt/ipc_test.go
+++ b/runtimes/google/rt/ipc_test.go
@@ -131,7 +131,7 @@
 	} else {
 		serverObjectName = naming.JoinAddressName(endpoint.String(), "")
 	}
-	if err := server.Serve("", ipc.LeafDispatcher(testService{}, vsecurity.NewACLAuthorizer(vsecurity.OpenACL()))); err != nil {
+	if err := server.Serve("", testService{}, vsecurity.NewACLAuthorizer(vsecurity.OpenACL())); err != nil {
 		t.Fatal(err)
 	}
 	// Let it rip!
diff --git a/runtimes/google/rt/mgmt.go b/runtimes/google/rt/mgmt.go
index 772fdfa..a6cac2a 100644
--- a/runtimes/google/rt/mgmt.go
+++ b/runtimes/google/rt/mgmt.go
@@ -69,7 +69,7 @@
 	if err != nil {
 		return err
 	}
-	if err := m.server.Serve("", ipc.LeafDispatcher(appcycle.NewServerAppCycle(m), nil)); err != nil {
+	if err := m.server.Serve("", appcycle.NewServerAppCycle(m), nil); err != nil {
 		return err
 	}
 	return m.callbackToParent(parentName, naming.JoinAddressName(ep.String(), ""))
diff --git a/runtimes/google/rt/mgmt_test.go b/runtimes/google/rt/mgmt_test.go
index 866585e..002cc2e 100644
--- a/runtimes/google/rt/mgmt_test.go
+++ b/runtimes/google/rt/mgmt_test.go
@@ -273,7 +273,7 @@
 	if ep, err = server.Listen(profiles.LocalListenSpec); err != nil {
 		t.Fatalf("Got error: %v", err)
 	}
-	if err := server.Serve("", ipc.LeafDispatcher(node.NewServerConfig(&configServer{ch}), vflag.NewAuthorizerOrDie())); err != nil {
+	if err := server.Serve("", node.NewServerConfig(&configServer{ch}), vflag.NewAuthorizerOrDie()); err != nil {
 		t.Fatalf("Got error: %v", err)
 	}
 	return server, naming.JoinAddressName(ep.String(), ""), ch
diff --git a/runtimes/google/rt/rt.go b/runtimes/google/rt/rt.go
index b8ff3d0..8e199b5 100644
--- a/runtimes/google/rt/rt.go
+++ b/runtimes/google/rt/rt.go
@@ -5,7 +5,6 @@
 	"fmt"
 	"os"
 	"path/filepath"
-	"strings"
 	"sync"
 
 	"veyron.io/veyron/veyron2"
@@ -31,20 +30,19 @@
 type vrt struct {
 	mu sync.Mutex
 
-	profile        veyron2.Profile
-	publisher      *config.Publisher
-	sm             []stream.Manager // GUARDED_BY(mu)
-	ns             naming.Namespace
-	signals        chan os.Signal
-	principal      security.Principal
-	client         ipc.Client
-	mgmt           *mgmtImpl
-	flags          flags.RuntimeFlags
-	reservedDisp   ipc.Dispatcher
-	reservedPrefix string
-	reservedOpts   []ipc.ServerOpt
-	nServers       int  // GUARDED_BY(mu)
-	cleaningUp     bool // GUARDED_BY(mu)
+	profile      veyron2.Profile
+	publisher    *config.Publisher
+	sm           []stream.Manager // GUARDED_BY(mu)
+	ns           naming.Namespace
+	signals      chan os.Signal
+	principal    security.Principal
+	client       ipc.Client
+	mgmt         *mgmtImpl
+	flags        flags.RuntimeFlags
+	reservedDisp ipc.Dispatcher
+	reservedOpts []ipc.ServerOpt
+	nServers     int  // GUARDED_BY(mu)
+	cleaningUp   bool // GUARDED_BY(mu)
 
 	lang    i18n.LangID // Language, from environment variables.
 	program string      // Program name, from os.Args[0].
@@ -142,12 +140,10 @@
 	return rt.profile
 }
 
-func (rt *vrt) ConfigureReservedName(prefix string, server ipc.Dispatcher, opts ...ipc.ServerOpt) {
+func (rt *vrt) ConfigureReservedName(server ipc.Dispatcher, opts ...ipc.ServerOpt) {
 	rt.mu.Lock()
 	defer rt.mu.Unlock()
 	rt.reservedDisp = server
-	prefix = strings.TrimLeft(prefix, "_")
-	rt.reservedPrefix = naming.ReservedNamePrefix + prefix
 	rt.reservedOpts = make([]ipc.ServerOpt, 0, len(opts))
 	copy(rt.reservedOpts, opts)
 }
diff --git a/runtimes/google/testing/mocks/runtime/panic_runtime.go b/runtimes/google/testing/mocks/runtime/panic_runtime.go
index cccc4d7..f5c7c2c 100644
--- a/runtimes/google/testing/mocks/runtime/panic_runtime.go
+++ b/runtimes/google/testing/mocks/runtime/panic_runtime.go
@@ -45,7 +45,7 @@
 func (*PanicRuntime) AdvanceGoal(delta int)         { panic(badRuntime) }
 func (*PanicRuntime) AdvanceProgress(delta int)     { panic(badRuntime) }
 func (*PanicRuntime) TrackTask(chan<- veyron2.Task) { panic(badRuntime) }
-func (*PanicRuntime) ConfigureReservedName(string, ipc.Dispatcher, ...ipc.ServerOpt) {
+func (*PanicRuntime) ConfigureReservedName(ipc.Dispatcher, ...ipc.ServerOpt) {
 	panic(badRuntime)
 }
 func (*PanicRuntime) Cleanup() { panic(badRuntime) }
diff --git a/runtimes/google/vtrace/vtrace_test.go b/runtimes/google/vtrace/vtrace_test.go
index 66c8bd7..f8af7f9 100644
--- a/runtimes/google/vtrace/vtrace_test.go
+++ b/runtimes/google/vtrace/vtrace_test.go
@@ -114,7 +114,7 @@
 		forceCollect: forceCollect,
 	}
 
-	if err := s.Serve(name, ipc.LeafDispatcher(c, fakeAuthorizer(0))); err != nil {
+	if err := s.Serve(name, c, fakeAuthorizer(0)); err != nil {
 		return nil, err
 	}
 
@@ -227,10 +227,10 @@
 
 	expectedSpans := []string{
 		": c0-begin, c0-end",
-		"Client Call: c1.Run",
-		"Server Call: .Run: c1-begin, c1-end",
-		"Client Call: c2.Run",
-		"Server Call: .Run: c2-begin, c2-end",
+		"<client>\"c1\".Run",
+		"\"\".Run: c1-begin, c1-end",
+		"<client>\"c2\".Run",
+		"\"\".Run: c2-begin, c2-end",
 	}
 	expectSequence(t, span.Trace().Record(), expectedSpans)
 }
@@ -247,10 +247,10 @@
 
 	expectedSpans := []string{
 		": c0-end",
-		"Client Call: c1.Run",
-		"Server Call: .Run: c1-end",
-		"Client Call: c2.Run",
-		"Server Call: .Run: c2-begin, c2-end",
+		"<client>\"c1\".Run",
+		"\"\".Run: c1-end",
+		"<client>\"c2\".Run",
+		"\"\".Run: c2-begin, c2-end",
 	}
 	expectSequence(t, span.Trace().Record(), expectedSpans)
 }
diff --git a/security/acl/acl.go b/security/acl/acl.go
new file mode 100644
index 0000000..3971530
--- /dev/null
+++ b/security/acl/acl.go
@@ -0,0 +1,44 @@
+package acl
+
+import (
+	"encoding/json"
+	"io"
+
+	"veyron.io/veyron/veyron2/security"
+)
+
+// Includes returns true iff the ACL grants access to a principal
+// that presents blessings.
+func (acl ACL) Includes(blessings ...string) bool {
+	blessings = pruneBlacklisted(acl.NotIn, blessings)
+	for _, pattern := range acl.In {
+		if pattern.MatchedBy(blessings...) {
+			return true
+		}
+	}
+	return false
+}
+
+// WriteTo writes the JSON-encoded representation of a TaggedACLMap to w.
+func (m TaggedACLMap) WriteTo(w io.Writer) error {
+	return json.NewEncoder(w).Encode(m)
+}
+
+// ReadTaggedACLMap reads the JSON-encoded representation of a TaggedACLMap from r.
+func ReadTaggedACLMap(r io.Reader) (m TaggedACLMap, err error) {
+	err = json.NewDecoder(r).Decode(&m)
+	return
+}
+
+func pruneBlacklisted(blacklist, blessings []string) []string {
+	if len(blacklist) == 0 {
+		return blessings
+	}
+	var filtered []string
+	for _, b := range blessings {
+		if !security.BlessingPattern(b).MatchedBy(blacklist...) {
+			filtered = append(filtered, b)
+		}
+	}
+	return filtered
+}
diff --git a/security/acl/acl.vdl b/security/acl/acl.vdl
new file mode 100644
index 0000000..51bc01c
--- /dev/null
+++ b/security/acl/acl.vdl
@@ -0,0 +1,38 @@
+// Package acl defines types and methods to represent Access Control Lists and enforce authorization policies based on them.
+package acl
+
+import "veyron.io/veyron/veyron2/security"
+
+// ACL represents an Access Control List - a set of blessings that should be
+// granted access.
+type ACL struct {
+  // In denotes the set of blessings (represented as BlessingPatterns) that
+  // should be granted access, unless blacklisted by an entry in NotIn.
+  //
+  // For example:
+  //   In: {"alice/family/..."}
+  // grants access to a principal that presents at least one of "alice",
+  // "alice/family", "alice/family/friend" etc. as a blessing.
+  In []security.BlessingPattern
+
+  // NotIn denotes the set of blessings (and their delegates) that
+  // have been explicitly blacklisted from the In set.
+  //
+  // For example:
+  //   In: {"alice/friend/..."}, NotIn: {"alice/friend/bob"}
+  // grants access to principals that present "alice", "alice/friend",
+  // "alice/friend/carol" etc. but NOT to a principal that presents
+  // "alice/friend/bob" or "alice/friend/bob/spouse" etc.
+  NotIn []string
+
+  // TODO(ashankar,ataly): At some point, introduce group identifiers here?
+}
+
+// TaggedACLMap maps string tags to access control lists specifying the
+// blessings required to invoke methods with that tag.
+//
+// These tags are meant to add a layer of interposition between set of users
+// (blessings, specifically) and the set of methods, much like "Roles" do in
+// Role Based Access Control (RBAC).
+// (http://en.wikipedia.org/wiki/Role-based_access_control)
+type TaggedACLMap map[string]ACL
diff --git a/security/acl/acl.vdl.go b/security/acl/acl.vdl.go
new file mode 100644
index 0000000..4a658de
--- /dev/null
+++ b/security/acl/acl.vdl.go
@@ -0,0 +1,40 @@
+// This file was auto-generated by the veyron vdl tool.
+// Source: acl.vdl
+
+// Package acl defines types and methods to represent Access Control Lists and enforce authorization policies based on them.
+package acl
+
+import (
+	"veyron.io/veyron/veyron2/security"
+)
+
+// ACL represents an Access Control List - a set of blessings that should be
+// granted access.
+type ACL struct {
+	// In denotes the set of blessings (represented as BlessingPatterns) that
+	// should be granted access, unless blacklisted by an entry in NotIn.
+	//
+	// For example:
+	//   In: {"alice/family/..."}
+	// grants access to a principal that presents at least one of "alice",
+	// "alice/family", "alice/family/friend" etc. as a blessing.
+	In []security.BlessingPattern
+	// NotIn denotes the set of blessings (and their delegates) that
+	// have been explicitly blacklisted from the In set.
+	//
+	// For example:
+	//   In: {"alice/friend/..."}, NotIn: {"alice/friend/bob"}
+	// grants access to principals that present "alice", "alice/friend",
+	// "alice/friend/carol" etc. but NOT to a principal that presents
+	// "alice/friend/bob" or "alice/friend/bob/spouse" etc.
+	NotIn []string
+}
+
+// TaggedACLMap maps string tags to access control lists specifying the
+// blessings required to invoke methods with that tag.
+//
+// These tags are meant to add a layer of interposition between set of users
+// (blessings, specifically) and the set of methods, much like "Roles" do in
+// Role Based Access Control (RBAC).
+// (http://en.wikipedia.org/wiki/Role-based_access_control)
+type TaggedACLMap map[string]ACL
diff --git a/security/acl/acl_test.go b/security/acl/acl_test.go
new file mode 100644
index 0000000..4187b18
--- /dev/null
+++ b/security/acl/acl_test.go
@@ -0,0 +1,86 @@
+package acl
+
+import (
+	"bytes"
+	"reflect"
+	"testing"
+
+	"veyron.io/veyron/veyron2/security"
+)
+
+func TestInclude(t *testing.T) {
+	acl := ACL{
+		In:    []security.BlessingPattern{"alice", "alice/friend/...", "bob/family/..."},
+		NotIn: []string{"alice/friend/carol", "bob/family/mallory"},
+	}
+	type V []string // shorthand
+	tests := []struct {
+		Blessings []string
+		Want      bool
+	}{
+		{nil, false}, // No blessings presented, cannot access
+		{V{}, false},
+		{V{"alice"}, true},
+		{V{"bob"}, true},
+		{V{"carol"}, false},
+		{V{"alice/colleague"}, false},
+		{V{"alice", "carol/friend"}, true}, // Presenting one blessing that grants access is sufficient
+		{V{"alice/friend/bob"}, true},
+		{V{"alice/friend/carol"}, false},        // alice/friend/carol is blacklisted
+		{V{"alice/friend/carol/family"}, false}, // alice/friend/carol is blacklisted, thus her delegates must be too.
+		{V{"alice/friend/bob", "alice/friend/carol"}, true},
+		{V{"bob/family/eve", "bob/family/mallory"}, true},
+		{V{"bob/family/mallory", "alice/friend/carol"}, false},
+	}
+	for _, test := range tests {
+		if got, want := acl.Includes(test.Blessings...), test.Want; got != want {
+			t.Errorf("Includes(%v): Got %v, want %v", test.Blessings, got, want)
+		}
+	}
+}
+
+func TestOpenACL(t *testing.T) {
+	acl := ACL{In: []security.BlessingPattern{security.AllPrincipals}}
+	if !acl.Includes() {
+		t.Errorf("OpenACL should allow principals that present no blessings")
+	}
+	if !acl.Includes("frank") {
+		t.Errorf("OpenACL should allow principals that present any blessings")
+	}
+}
+
+func TestTaggedACLMapSerialization(t *testing.T) {
+	obj := TaggedACLMap{
+		"R": ACL{
+			In:    []security.BlessingPattern{"foo/...", "bar/..."},
+			NotIn: []string{"bar/baz"},
+		},
+		"W": ACL{
+			In:    []security.BlessingPattern{"foo/...", "bar"},
+			NotIn: []string{"foo/bar", "foo/baz/boz"},
+		},
+	}
+	txt := `
+{
+	"R": {
+		"In":["foo/...","bar/..."],
+		"NotIn":["bar/baz"]
+	},
+	"W": {
+		"In":["foo/...","bar"],
+		"NotIn":["foo/bar","foo/baz/boz"]
+	}
+}
+`
+	if got, err := ReadTaggedACLMap(bytes.NewBufferString(txt)); err != nil || !reflect.DeepEqual(got, obj) {
+		t.Errorf("Got error %v, TaggedACLMap: %v, want %v", err, got, obj)
+	}
+	// And round-trip (don't compare with 'txt' because indentation/spacing might differ).
+	var buf bytes.Buffer
+	if err := obj.WriteTo(&buf); err != nil {
+		t.Fatal(err)
+	}
+	if got, err := ReadTaggedACLMap(&buf); err != nil || !reflect.DeepEqual(got, obj) {
+		t.Errorf("Got error %v, TaggedACLMap: %v, want %v", err, got, obj)
+	}
+}
diff --git a/security/acl/authorizer.go b/security/acl/authorizer.go
new file mode 100644
index 0000000..f4d60c9
--- /dev/null
+++ b/security/acl/authorizer.go
@@ -0,0 +1,150 @@
+package acl
+
+import (
+	"fmt"
+	"os"
+	"reflect"
+
+	"veyron.io/veyron/veyron2/security"
+)
+
+// TaggedACLAuthorizer implements an authorization policy where access is
+// granted if the remote end presents blessings included in the Access Control
+// Lists (ACLs) associated with the set of relevant tags.
+//
+// The set of relevant tags is the subset of tags associated with the
+// method (security.Context.MethodTags) that have the same type as tagType.
+// Currently, tagType.Kind must be reflect.String, i.e., only tags that are
+// named string types are supported.
+//
+// If multiple tags of tagType are associated with the method, then access is
+// granted if the peer presents blessings that match the ACLs of each one of
+// those tags. If no tags of tagType are associated with the method, then
+// access is denied.
+//
+// If the TaggedACLMap provided is nil, then a nil authorizer is returned.
+//
+// Sample usage:
+//
+// (1) Attach tags to methods in the VDL (eg. myservice.vdl)
+//   package myservice
+//
+//   type MyTag string
+//   const (
+//     ReadAccess  = MyTag("R")
+//     WriteAccess = MyTag("W")
+//   )
+//
+//   type MyService interface {
+//     Get() ([]string, error)       {ReadAccess}
+//     GetIndex(int) (string, error) {ReadAccess}
+//
+//     Set([]string) error           {WriteAccess}
+//     SetIndex(int, string) error   {WriteAccess}
+//
+//     GetAndSet([]string) ([]string, error) {ReadAccess, WriteAccess}
+//   }
+//
+// (2) Setup the ipc.Dispatcher to use the TaggedACLAuthorizer
+//   import (
+//     "reflect"
+//     "veyron.io/veyron/veyron/security/acl"
+//
+//     "veyron.io/veyron/veyron2/ipc"
+//     "veyron.io/veyron/veyron2/security"
+//   )
+//
+//   type dispatcher struct{}
+//   func (d dispatcher) Lookup(suffix, method) (ipc.Invoker, security.Authorizer, error) {
+//      acl := acl.TaggedACLMap{
+//        "R": acl.ACL{In: []security.BlessingPattern{"alice/friends/...", "alice/family/..."} },
+//        "W": acl.ACL{In: []security.BlessingPattern{"alice/family/...", "alice/colleagues/..." } },
+//      }
+//      typ := reflect.TypeOf(ReadAccess)  // equivalently, reflect.TypeOf(WriteAccess)
+//      return newInvoker(), acl.TaggedACLAuthorizer(acl, typ), nil
+//   }
+//
+// With the above dispatcher, the server will grant access to a peer with the blessing
+// "alice/friend/bob" access only to the "Get" and "GetIndex" methods. A peer presenting
+// the blessing "alice/colleague/carol" will get access only to the "Set" and "SetIndex"
+// methods. A peer presenting "alice/family/mom" will get access to all methods, even
+// GetAndSet - which requires that the blessing appear in the ACLs for both the
+// ReadAccess and WriteAccess tags.
+func TaggedACLAuthorizer(acls TaggedACLMap, tagType reflect.Type) (security.Authorizer, error) {
+	if tagType.Kind() != reflect.String {
+		return nil, fmt.Errorf("tag type(%v) must be backed by a string not %v", tagType, tagType.Kind())
+	}
+	return &authorizer{acls, tagType}, nil
+}
+
+// TaggedACLAuthorizerFromFile applies the same authorization policy as
+// TaggedACLAuthorizer, with the TaggedACLMap to be used sourced from a file named
+// filename.
+//
+// Changes to the file are monitored and affect subsequent calls to Authorize.
+// Currently, this is achieved by re-reading the file on every call to
+// Authorize.
+// TODO(ashankar,ataly): Use inotify or a similar mechanism to watch for
+// changes.
+func TaggedACLAuthorizerFromFile(filename string, tagType reflect.Type) (security.Authorizer, error) {
+	if tagType.Kind() != reflect.String {
+		return nil, fmt.Errorf("tag type(%v) must be backed by a string not %v", tagType, tagType.Kind())
+	}
+	return &fileAuthorizer{filename, tagType}, nil
+}
+
+type authorizer struct {
+	acls    TaggedACLMap
+	tagType reflect.Type
+}
+
+func (a *authorizer) Authorize(ctx security.Context) error {
+	// "Self-RPCs" are always authorized.
+	if l, r := ctx.LocalBlessings(), ctx.RemoteBlessings(); l != nil && r != nil && reflect.DeepEqual(l.PublicKey(), r.PublicKey()) {
+		return nil
+	}
+	var blessings []string
+	if ctx.RemoteBlessings() != nil {
+		blessings = ctx.RemoteBlessings().ForContext(ctx)
+	}
+	grant := false
+	for _, tag := range ctx.MethodTags() {
+		if v := reflect.ValueOf(tag); v.Type() == a.tagType {
+			if acl, exists := a.acls[v.String()]; !exists || !acl.Includes(blessings...) {
+				return errACLMatch(blessings)
+			}
+			grant = true
+		}
+	}
+	if grant {
+		return nil
+	}
+	return errACLMatch(blessings)
+}
+
+type fileAuthorizer struct {
+	filename string
+	tagType  reflect.Type
+}
+
+func (a *fileAuthorizer) Authorize(ctx security.Context) error {
+	acl, err := loadTaggedACLMapFromFile(a.filename)
+	if err != nil {
+		// TODO(ashankar): Information leak?
+		return fmt.Errorf("failed to read ACL from file: %v", err)
+	}
+	return (&authorizer{acl, a.tagType}).Authorize(ctx)
+}
+
+func loadTaggedACLMapFromFile(filename string) (TaggedACLMap, error) {
+	file, err := os.Open(filename)
+	if err != nil {
+		return nil, err
+	}
+	defer file.Close()
+	return ReadTaggedACLMap(file)
+}
+
+func errACLMatch(blessings []string) error {
+	return fmt.Errorf("%v does not match ACL", blessings)
+}
diff --git a/security/acl/authorizer_test.go b/security/acl/authorizer_test.go
new file mode 100644
index 0000000..59137b5
--- /dev/null
+++ b/security/acl/authorizer_test.go
@@ -0,0 +1,214 @@
+package acl
+
+import (
+	"io/ioutil"
+	"reflect"
+	"testing"
+
+	vsecurity "veyron.io/veyron/veyron/security"
+	"veyron.io/veyron/veyron/security/acl/test"
+	"veyron.io/veyron/veyron2/security"
+)
+
+// TestTaggedACLAuthorizer is both a test and a demonstration of the use of the
+// TaggedACLAuthorizer and interaction with interface specification in VDL.
+func TestTaggedACLAuthorizer(t *testing.T) {
+	type P []security.BlessingPattern
+	type S []string
+	// TaggedACLMap to test against.
+	acl := TaggedACLMap{
+		"R": {
+			In: P{"..."},
+		},
+		"W": {
+			In:    P{"ali/family/...", "bob/...", "che"},
+			NotIn: S{"bob/acquaintances"},
+		},
+		"X": {
+			In: P{"ali/family/boss", "superman"},
+		},
+	}
+	type testcase struct {
+		Method string
+		Client security.Blessings
+	}
+	var (
+		authorizer, _ = TaggedACLAuthorizer(acl, reflect.TypeOf(test.Read))
+		// Two principals: The "server" and the "client"
+		pserver, _ = vsecurity.NewPrincipal()
+		pclient, _ = vsecurity.NewPrincipal()
+		server, _  = pserver.BlessSelf("server")
+
+		// B generates the provided blessings for the client and ensures
+		// that the server will recognize them.
+		B = func(names ...string) security.Blessings {
+			var ret security.Blessings
+			for _, name := range names {
+				b, err := pclient.BlessSelf(name)
+				if err != nil {
+					t.Fatalf("%q: %v", name, err)
+				}
+				if err := pserver.AddToRoots(b); err != nil {
+					t.Fatalf("%q: %v", name, err)
+				}
+				if ret, err = security.UnionOfBlessings(ret, b); err != nil {
+					t.Fatal(err)
+				}
+			}
+			return ret
+		}
+
+		run = func(test testcase) error {
+			ctx := security.NewContext(&security.ContextParams{
+				LocalPrincipal:  pserver,
+				LocalBlessings:  server,
+				RemoteBlessings: test.Client,
+				Method:          test.Method,
+				MethodTags:      methodTags(test.Method),
+			})
+			return authorizer.Authorize(ctx)
+		}
+	)
+
+	// Test cases where access should be granted to methods with tags on
+	// them.
+	for _, test := range []testcase{
+		{"Get", nil},
+		{"Get", B("ali")},
+		{"Get", B("bob/friend", "che/enemy")},
+
+		{"Put", B("ali")},
+		{"Put", B("ali/family/mom")},
+		{"Put", B("bob/friends")},
+		{"Put", B("bob/acquantainces/carol", "che")}, // Access granted because of "che"
+
+		{"Resolve", B("ali")},
+		{"Resolve", B("ali/family/boss")},
+
+		{"AllTags", B("ali/family/boss")},
+	} {
+		if err := run(test); err != nil {
+			t.Errorf("Access denied to method %q to %v: %v", test.Method, test.Client, err)
+		}
+	}
+	// Test cases where access should be denied.
+	for _, test := range []testcase{
+		// Nobody is denied access to "Get"
+		{"Put", B("bob/acquaintances/dave", "che/friend", "dave")},
+		{"Resolve", B("ali/family/friend")},
+		// Since there are no tags on the NoTags method, it has an
+		// empty ACL.  No client will have access.
+		{"NoTags", B("ali", "ali/family/boss", "bob")},
+		// On a method with multiple tags on it, all must be satisfied.
+		{"AllTags", B("superman")},          // Only in the X ACL, not in R or W
+		{"AllTags", B("superman", "clark")}, // In X and in R, but not W
+	} {
+		if err := run(test); err == nil {
+			t.Errorf("Access to %q granted to %v", test.Method, test.Client)
+		}
+	}
+}
+
+func TestTaggedACLAuthorizerSelfRPCs(t *testing.T) {
+	var (
+		// Client and server are the same principal, though have
+		// different blessings.
+		p, _      = vsecurity.NewPrincipal()
+		client, _ = p.BlessSelf("client")
+		server, _ = p.BlessSelf("server")
+		// Authorizer with a TaggedACLMap that grants read access to
+		// anyone, write/execute access to noone.
+		typ           test.MyTag
+		authorizer, _ = TaggedACLAuthorizer(TaggedACLMap{"R": {In: []security.BlessingPattern{"nobody"}}}, reflect.TypeOf(typ))
+	)
+	for _, test := range []string{"Put", "Get", "Resolve", "NoTags", "AllTags"} {
+		ctx := security.NewContext(&security.ContextParams{
+			LocalPrincipal:  p,
+			LocalBlessings:  server,
+			RemoteBlessings: client,
+			Method:          test,
+			MethodTags:      methodTags(test),
+		})
+		if err := authorizer.Authorize(ctx); err != nil {
+			t.Errorf("Got error %v for method %q", err, test)
+		}
+	}
+}
+
+func TestTaggedACLAuthorizerWithNilACL(t *testing.T) {
+	var (
+		authorizer, _ = TaggedACLAuthorizer(nil, reflect.TypeOf(test.Read))
+		pserver, _    = vsecurity.NewPrincipal()
+		pclient, _    = vsecurity.NewPrincipal()
+		server, _     = pserver.BlessSelf("server")
+		client, _     = pclient.BlessSelf("client")
+	)
+	for _, test := range []string{"Put", "Get", "Resolve", "NoTags", "AllTags"} {
+		ctx := security.NewContext(&security.ContextParams{
+			LocalPrincipal:  pserver,
+			LocalBlessings:  server,
+			RemoteBlessings: client,
+			Method:          test,
+			MethodTags:      methodTags(test),
+		})
+		if err := authorizer.Authorize(ctx); err == nil {
+			t.Errorf("nil TaggedACLMap authorized method %q", test)
+		}
+	}
+}
+
+func TestTaggedACLAuthorizerFromFile(t *testing.T) {
+	file, err := ioutil.TempFile("", "TestTaggedACLAuthorizerFromFile")
+	if err != nil {
+		t.Fatal(err)
+	}
+	filename := file.Name()
+	file.Close()
+
+	var (
+		authorizer, _  = TaggedACLAuthorizerFromFile(filename, reflect.TypeOf(test.Read))
+		pserver, _     = vsecurity.NewPrincipal()
+		pclient, _     = vsecurity.NewPrincipal()
+		server, _      = pserver.BlessSelf("alice")
+		alicefriend, _ = pserver.Bless(pclient.PublicKey(), server, "friend/bob", security.UnconstrainedUse())
+		ctx            = security.NewContext(&security.ContextParams{
+			LocalPrincipal:  pserver,
+			LocalBlessings:  server,
+			RemoteBlessings: alicefriend,
+			Method:          "Get",
+			MethodTags:      methodTags("Get"),
+		})
+	)
+	// Make pserver recognize itself as an authority on "alice/..." blessings.
+	if err := pserver.AddToRoots(server); err != nil {
+		t.Fatal(err)
+	}
+	// "alice/friend/bob" should not have access to test.Read methods like Get.
+	if err := authorizer.Authorize(ctx); err == nil {
+		t.Fatalf("Expected authorization error as %v is not on the ACL for Read operations", ctx.RemoteBlessings())
+	}
+	// Rewrite the file giving access
+	if err := ioutil.WriteFile(filename, []byte(`{"R": { "In":["alice/friend/..."] }}`), 0600); err != nil {
+		t.Fatal(err)
+	}
+	// Now should have access
+	if err := authorizer.Authorize(ctx); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestTagTypeMustBeString(t *testing.T) {
+	type I int
+	if auth, err := TaggedACLAuthorizer(TaggedACLMap{}, reflect.TypeOf(I(0))); err == nil || auth != nil {
+		t.Errorf("Got (%v, %v), wanted error since tag type is not a string", auth, err)
+	}
+	if auth, err := TaggedACLAuthorizerFromFile("does_not_matter", reflect.TypeOf(I(0))); err == nil || auth != nil {
+		t.Errorf("Got (%v, %v), wanted error since tag type is not a string", auth, err)
+	}
+}
+
+func methodTags(method string) []interface{} {
+	server := &test.ServerStubMyObject{}
+	tags, _ := server.GetMethodTags(nil, method)
+	return tags
+}
diff --git a/security/acl/test/vdl.vdl b/security/acl/test/vdl.vdl
new file mode 100644
index 0000000..fd3a73f
--- /dev/null
+++ b/security/acl/test/vdl.vdl
@@ -0,0 +1,23 @@
+// Package test provides a VDL specification for a service used in the unittest of the acl package.
+package test
+
+// Any package can define tags (of arbitrary types) to be attached to methods.
+// This type can be used to index into a TaggedACLMap.
+type MyTag string
+
+const (
+	// For this example/unittest, there are three possible values of MyTag,
+        // each represented by a single-character string.
+	Read    = MyTag("R")
+	Write   = MyTag("W")
+	Execute = MyTag("X")
+)
+
+// MyObject demonstrates how tags are attached to methods.
+type MyObject interface {
+  Get() error     {Read}
+  Put() error     {Write}
+  Resolve() error {Execute}
+  NoTags() error  // No tags attached to this.
+  AllTags() error {Read, Write, Execute}
+}
diff --git a/security/acl/test/vdl.vdl.go b/security/acl/test/vdl.vdl.go
new file mode 100644
index 0000000..91e5790
--- /dev/null
+++ b/security/acl/test/vdl.vdl.go
@@ -0,0 +1,324 @@
+// This file was auto-generated by the veyron vdl tool.
+// Source: vdl.vdl
+
+// Package test provides a VDL specification for a service used in the unittest of the acl package.
+package test
+
+import (
+	// The non-user imports are prefixed with "_gen_" to prevent collisions.
+	_gen_veyron2 "veyron.io/veyron/veyron2"
+	_gen_context "veyron.io/veyron/veyron2/context"
+	_gen_ipc "veyron.io/veyron/veyron2/ipc"
+	_gen_naming "veyron.io/veyron/veyron2/naming"
+	_gen_vdlutil "veyron.io/veyron/veyron2/vdl/vdlutil"
+	_gen_wiretype "veyron.io/veyron/veyron2/wiretype"
+)
+
+// Any package can define tags (of arbitrary types) to be attached to methods.
+// This type can be used to index into a TaggedACLMap.
+type MyTag string
+
+// For this example/unittest, there are three possible values of MyTag,
+// each represented by a single-character string.
+const Read = MyTag("R")
+
+const Write = MyTag("W")
+
+const Execute = MyTag("X")
+
+// TODO(toddw): Remove this line once the new signature support is done.
+// It corrects a bug where _gen_wiretype is unused in VDL pacakges where only
+// bootstrap types are used on interfaces.
+const _ = _gen_wiretype.TypeIDInvalid
+
+// MyObject demonstrates how tags are attached to methods.
+// MyObject is the interface the client binds and uses.
+// MyObject_ExcludingUniversal is the interface without internal framework-added methods
+// to enable embedding without method collisions.  Not to be used directly by clients.
+type MyObject_ExcludingUniversal interface {
+	Get(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error)
+	Put(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error)
+	Resolve(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error)
+	NoTags(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error) // No tags attached to this.
+	AllTags(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error)
+}
+type MyObject interface {
+	_gen_ipc.UniversalServiceMethods
+	MyObject_ExcludingUniversal
+}
+
+// MyObjectService is the interface the server implements.
+type MyObjectService interface {
+	Get(context _gen_ipc.ServerContext) (err error)
+	Put(context _gen_ipc.ServerContext) (err error)
+	Resolve(context _gen_ipc.ServerContext) (err error)
+	NoTags(context _gen_ipc.ServerContext) (err error) // No tags attached to this.
+	AllTags(context _gen_ipc.ServerContext) (err error)
+}
+
+// BindMyObject returns the client stub implementing the MyObject
+// interface.
+//
+// If no _gen_ipc.Client is specified, the default _gen_ipc.Client in the
+// global Runtime is used.
+func BindMyObject(name string, opts ..._gen_ipc.BindOpt) (MyObject, error) {
+	var client _gen_ipc.Client
+	switch len(opts) {
+	case 0:
+		// Do nothing.
+	case 1:
+		if clientOpt, ok := opts[0].(_gen_ipc.Client); opts[0] == nil || ok {
+			client = clientOpt
+		} else {
+			return nil, _gen_vdlutil.ErrUnrecognizedOption
+		}
+	default:
+		return nil, _gen_vdlutil.ErrTooManyOptionsToBind
+	}
+	stub := &clientStubMyObject{defaultClient: client, name: name}
+
+	return stub, nil
+}
+
+// NewServerMyObject creates a new server stub.
+//
+// It takes a regular server implementing the MyObjectService
+// interface, and returns a new server stub.
+func NewServerMyObject(server MyObjectService) interface{} {
+	stub := &ServerStubMyObject{
+		service: server,
+	}
+	var gs _gen_ipc.GlobState
+	var self interface{} = stub
+	// VAllGlobber is implemented by the server object, which is wrapped in
+	// a VDL generated server stub.
+	if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VAllGlobber is implemented by the server object without using a VDL
+	// generated stub.
+	if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VChildrenGlobber is implemented in the server object.
+	if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+		gs.VChildrenGlobber = x
+	}
+	stub.gs = &gs
+	return stub
+}
+
+// clientStubMyObject implements MyObject.
+type clientStubMyObject struct {
+	defaultClient _gen_ipc.Client
+	name          string
+}
+
+func (__gen_c *clientStubMyObject) client(ctx _gen_context.T) _gen_ipc.Client {
+	if __gen_c.defaultClient != nil {
+		return __gen_c.defaultClient
+	}
+	return _gen_veyron2.RuntimeFromContext(ctx).Client()
+}
+
+func (__gen_c *clientStubMyObject) Get(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error) {
+	var call _gen_ipc.Call
+	if call, err = __gen_c.client(ctx).StartCall(ctx, __gen_c.name, "Get", nil, opts...); err != nil {
+		return
+	}
+	if ierr := call.Finish(&err); ierr != nil {
+		err = ierr
+	}
+	return
+}
+
+func (__gen_c *clientStubMyObject) Put(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error) {
+	var call _gen_ipc.Call
+	if call, err = __gen_c.client(ctx).StartCall(ctx, __gen_c.name, "Put", nil, opts...); err != nil {
+		return
+	}
+	if ierr := call.Finish(&err); ierr != nil {
+		err = ierr
+	}
+	return
+}
+
+func (__gen_c *clientStubMyObject) Resolve(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error) {
+	var call _gen_ipc.Call
+	if call, err = __gen_c.client(ctx).StartCall(ctx, __gen_c.name, "Resolve", nil, opts...); err != nil {
+		return
+	}
+	if ierr := call.Finish(&err); ierr != nil {
+		err = ierr
+	}
+	return
+}
+
+func (__gen_c *clientStubMyObject) NoTags(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error) {
+	var call _gen_ipc.Call
+	if call, err = __gen_c.client(ctx).StartCall(ctx, __gen_c.name, "NoTags", nil, opts...); err != nil {
+		return
+	}
+	if ierr := call.Finish(&err); ierr != nil {
+		err = ierr
+	}
+	return
+}
+
+func (__gen_c *clientStubMyObject) AllTags(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error) {
+	var call _gen_ipc.Call
+	if call, err = __gen_c.client(ctx).StartCall(ctx, __gen_c.name, "AllTags", nil, opts...); err != nil {
+		return
+	}
+	if ierr := call.Finish(&err); ierr != nil {
+		err = ierr
+	}
+	return
+}
+
+func (__gen_c *clientStubMyObject) UnresolveStep(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (reply []string, err error) {
+	var call _gen_ipc.Call
+	if call, err = __gen_c.client(ctx).StartCall(ctx, __gen_c.name, "UnresolveStep", nil, opts...); err != nil {
+		return
+	}
+	if ierr := call.Finish(&reply, &err); ierr != nil {
+		err = ierr
+	}
+	return
+}
+
+func (__gen_c *clientStubMyObject) Signature(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (reply _gen_ipc.ServiceSignature, err error) {
+	var call _gen_ipc.Call
+	if call, err = __gen_c.client(ctx).StartCall(ctx, __gen_c.name, "Signature", nil, opts...); err != nil {
+		return
+	}
+	if ierr := call.Finish(&reply, &err); ierr != nil {
+		err = ierr
+	}
+	return
+}
+
+func (__gen_c *clientStubMyObject) GetMethodTags(ctx _gen_context.T, method string, opts ..._gen_ipc.CallOpt) (reply []interface{}, err error) {
+	var call _gen_ipc.Call
+	if call, err = __gen_c.client(ctx).StartCall(ctx, __gen_c.name, "GetMethodTags", []interface{}{method}, opts...); err != nil {
+		return
+	}
+	if ierr := call.Finish(&reply, &err); ierr != nil {
+		err = ierr
+	}
+	return
+}
+
+// ServerStubMyObject wraps a server that implements
+// MyObjectService and provides an object that satisfies
+// the requirements of veyron2/ipc.ReflectInvoker.
+type ServerStubMyObject struct {
+	service MyObjectService
+	gs      *_gen_ipc.GlobState
+}
+
+func (__gen_s *ServerStubMyObject) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
+	// TODO(bprosnitz) GetMethodTags() will be replaces with Signature().
+	// Note: This exhibits some weird behavior like returning a nil error if the method isn't found.
+	// This will change when it is replaced with Signature().
+	switch method {
+	case "Get":
+		return []interface{}{MyTag("R")}, nil
+	case "Put":
+		return []interface{}{MyTag("W")}, nil
+	case "Resolve":
+		return []interface{}{MyTag("X")}, nil
+	case "NoTags":
+		return []interface{}{}, nil
+	case "AllTags":
+		return []interface{}{MyTag("R"), MyTag("W"), MyTag("X")}, nil
+	default:
+		return nil, nil
+	}
+}
+
+func (__gen_s *ServerStubMyObject) Signature(call _gen_ipc.ServerCall) (_gen_ipc.ServiceSignature, error) {
+	result := _gen_ipc.ServiceSignature{Methods: make(map[string]_gen_ipc.MethodSignature)}
+	result.Methods["AllTags"] = _gen_ipc.MethodSignature{
+		InArgs: []_gen_ipc.MethodArgument{},
+		OutArgs: []_gen_ipc.MethodArgument{
+			{Name: "", Type: 65},
+		},
+	}
+	result.Methods["Get"] = _gen_ipc.MethodSignature{
+		InArgs: []_gen_ipc.MethodArgument{},
+		OutArgs: []_gen_ipc.MethodArgument{
+			{Name: "", Type: 65},
+		},
+	}
+	result.Methods["NoTags"] = _gen_ipc.MethodSignature{
+		InArgs: []_gen_ipc.MethodArgument{},
+		OutArgs: []_gen_ipc.MethodArgument{
+			{Name: "", Type: 65},
+		},
+	}
+	result.Methods["Put"] = _gen_ipc.MethodSignature{
+		InArgs: []_gen_ipc.MethodArgument{},
+		OutArgs: []_gen_ipc.MethodArgument{
+			{Name: "", Type: 65},
+		},
+	}
+	result.Methods["Resolve"] = _gen_ipc.MethodSignature{
+		InArgs: []_gen_ipc.MethodArgument{},
+		OutArgs: []_gen_ipc.MethodArgument{
+			{Name: "", Type: 65},
+		},
+	}
+
+	result.TypeDefs = []_gen_vdlutil.Any{
+		_gen_wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
+
+	return result, nil
+}
+
+func (__gen_s *ServerStubMyObject) UnresolveStep(call _gen_ipc.ServerCall) (reply []string, err error) {
+	if unresolver, ok := __gen_s.service.(_gen_ipc.Unresolver); ok {
+		return unresolver.UnresolveStep(call)
+	}
+	if call.Server() == nil {
+		return
+	}
+	var published []string
+	if published, err = call.Server().Published(); err != nil || published == nil {
+		return
+	}
+	reply = make([]string, len(published))
+	for i, p := range published {
+		reply[i] = _gen_naming.Join(p, call.Name())
+	}
+	return
+}
+
+func (__gen_s *ServerStubMyObject) VGlob() *_gen_ipc.GlobState {
+	return __gen_s.gs
+}
+
+func (__gen_s *ServerStubMyObject) Get(call _gen_ipc.ServerCall) (err error) {
+	err = __gen_s.service.Get(call)
+	return
+}
+
+func (__gen_s *ServerStubMyObject) Put(call _gen_ipc.ServerCall) (err error) {
+	err = __gen_s.service.Put(call)
+	return
+}
+
+func (__gen_s *ServerStubMyObject) Resolve(call _gen_ipc.ServerCall) (err error) {
+	err = __gen_s.service.Resolve(call)
+	return
+}
+
+func (__gen_s *ServerStubMyObject) NoTags(call _gen_ipc.ServerCall) (err error) {
+	err = __gen_s.service.NoTags(call)
+	return
+}
+
+func (__gen_s *ServerStubMyObject) AllTags(call _gen_ipc.ServerCall) (err error) {
+	err = __gen_s.service.AllTags(call)
+	return
+}
diff --git a/security/agent/pingpong/main.go b/security/agent/pingpong/main.go
index 08a3aab..1fa34fb 100644
--- a/security/agent/pingpong/main.go
+++ b/security/agent/pingpong/main.go
@@ -58,7 +58,7 @@
 	auth := vsecurity.NewACLAuthorizer(security.ACL{In: map[security.BlessingPattern]security.LabelSet{
 		security.AllPrincipals: security.AllLabels,
 	}})
-	if err := s.Serve("pingpong", ipc.LeafDispatcher(serverPong, auth)); err != nil {
+	if err := s.Serve("pingpong", serverPong, auth); err != nil {
 		log.Fatal("error serving service: ", err)
 	}
 
diff --git a/security/agent/pingpong/wire.vdl.go b/security/agent/pingpong/wire.vdl.go
index 9bf1574..35862ff 100644
--- a/security/agent/pingpong/wire.vdl.go
+++ b/security/agent/pingpong/wire.vdl.go
@@ -64,9 +64,27 @@
 // It takes a regular server implementing the PingPongService
 // interface, and returns a new server stub.
 func NewServerPingPong(server PingPongService) interface{} {
-	return &ServerStubPingPong{
+	stub := &ServerStubPingPong{
 		service: server,
 	}
+	var gs _gen_ipc.GlobState
+	var self interface{} = stub
+	// VAllGlobber is implemented by the server object, which is wrapped in
+	// a VDL generated server stub.
+	if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VAllGlobber is implemented by the server object without using a VDL
+	// generated stub.
+	if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VChildrenGlobber is implemented in the server object.
+	if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+		gs.VChildrenGlobber = x
+	}
+	stub.gs = &gs
+	return stub
 }
 
 // clientStubPingPong implements PingPong.
@@ -131,6 +149,7 @@
 // the requirements of veyron2/ipc.ReflectInvoker.
 type ServerStubPingPong struct {
 	service PingPongService
+	gs      *_gen_ipc.GlobState
 }
 
 func (__gen_s *ServerStubPingPong) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -181,6 +200,10 @@
 	return
 }
 
+func (__gen_s *ServerStubPingPong) VGlob() *_gen_ipc.GlobState {
+	return __gen_s.gs
+}
+
 func (__gen_s *ServerStubPingPong) Ping(call _gen_ipc.ServerCall, message string) (reply string, err error) {
 	reply, err = __gen_s.service.Ping(call, message)
 	return
diff --git a/security/agent/server/server.go b/security/agent/server/server.go
index a9798ff..9cfb422 100644
--- a/security/agent/server/server.go
+++ b/security/agent/server/server.go
@@ -192,7 +192,7 @@
 				}
 				spec := ipc.ListenSpec{Protocol: clientAddr.Network(), Address: clientAddr.String()}
 				if _, err = s.Listen(spec); err == nil {
-					err = s.Serve("", ipc.LeafDispatcher(serverAgent, nil))
+					err = s.Serve("", serverAgent, nil)
 				}
 			}
 			if err != nil {
diff --git a/security/agent/server/wire.vdl.go b/security/agent/server/wire.vdl.go
index d9fcc39..2870d8e 100644
--- a/security/agent/server/wire.vdl.go
+++ b/security/agent/server/wire.vdl.go
@@ -91,9 +91,27 @@
 // It takes a regular server implementing the AgentService
 // interface, and returns a new server stub.
 func NewServerAgent(server AgentService) interface{} {
-	return &ServerStubAgent{
+	stub := &ServerStubAgent{
 		service: server,
 	}
+	var gs _gen_ipc.GlobState
+	var self interface{} = stub
+	// VAllGlobber is implemented by the server object, which is wrapped in
+	// a VDL generated server stub.
+	if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VAllGlobber is implemented by the server object without using a VDL
+	// generated stub.
+	if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VChildrenGlobber is implemented in the server object.
+	if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+		gs.VChildrenGlobber = x
+	}
+	stub.gs = &gs
+	return stub
 }
 
 // clientStubAgent implements Agent.
@@ -301,6 +319,7 @@
 // the requirements of veyron2/ipc.ReflectInvoker.
 type ServerStubAgent struct {
 	service AgentService
+	gs      *_gen_ipc.GlobState
 }
 
 func (__gen_s *ServerStubAgent) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -518,6 +537,10 @@
 	return
 }
 
+func (__gen_s *ServerStubAgent) VGlob() *_gen_ipc.GlobState {
+	return __gen_s.gs
+}
+
 func (__gen_s *ServerStubAgent) Bless(call _gen_ipc.ServerCall, key []byte, wit security.WireBlessings, extension string, caveat security.Caveat, additionalCaveats []security.Caveat) (reply security.WireBlessings, err error) {
 	reply, err = __gen_s.service.Bless(call, key, wit, extension, caveat, additionalCaveats)
 	return
diff --git a/security/blessingroots_test.go b/security/blessingroots_test.go
index 899651c..f129d9e 100644
--- a/security/blessingroots_test.go
+++ b/security/blessingroots_test.go
@@ -15,7 +15,7 @@
 	var tester rootsTester
 	var err error
 	for idx := range tester {
-		if tester[idx], _, err = newKey(); err != nil {
+		if tester[idx], _, err = NewPrincipalKey(); err != nil {
 			panic(err)
 		}
 	}
diff --git a/security/principal.go b/security/principal.go
index 4959486..8f4906c 100644
--- a/security/principal.go
+++ b/security/principal.go
@@ -2,8 +2,6 @@
 
 import (
 	"crypto/ecdsa"
-	"crypto/elliptic"
-	"crypto/rand"
 	"fmt"
 	"os"
 	"path"
@@ -16,7 +14,7 @@
 // NewPrincipal mints a new private key and generates a principal based on
 // this key, storing its BlessingRoots and BlessingStore in memory.
 func NewPrincipal() (security.Principal, error) {
-	pub, priv, err := newKey()
+	pub, priv, err := NewPrincipalKey()
 	if err != nil {
 		return nil, err
 	}
@@ -159,15 +157,6 @@
 	return key.(*ecdsa.PrivateKey), nil
 }
 
-// newKey generates an ECDSA (public, private) key pair.
-func newKey() (security.PublicKey, *ecdsa.PrivateKey, error) {
-	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
-	if err != nil {
-		return nil, nil, err
-	}
-	return security.NewECDSAPublicKey(&priv.PublicKey), priv, nil
-}
-
 func initKey(dir string, passphrase []byte) (*ecdsa.PrivateKey, error) {
 	keyFile := path.Join(dir, privateKeyFile)
 	f, err := os.OpenFile(keyFile, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600)
@@ -175,7 +164,7 @@
 		return nil, fmt.Errorf("failed to open %q for writing: %v", keyFile, err)
 	}
 	defer f.Close()
-	_, key, err := newKey()
+	_, key, err := NewPrincipalKey()
 	if err != nil {
 		return nil, fmt.Errorf("failed to generate private key: %v", err)
 	}
diff --git a/security/util.go b/security/util.go
index a7bd085..6e1f848 100644
--- a/security/util.go
+++ b/security/util.go
@@ -3,6 +3,7 @@
 import (
 	"bytes"
 	"crypto/ecdsa"
+	"crypto/elliptic"
 	"crypto/rand"
 	"crypto/x509"
 	"encoding/json"
@@ -29,6 +30,15 @@
 
 var PassphraseErr = errors.New("passphrase incorrect for decrypting private key")
 
+// NewPrincipalKey generates an ECDSA (public, private) key pair.
+func NewPrincipalKey() (security.PublicKey, *ecdsa.PrivateKey, error) {
+	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+	if err != nil {
+		return nil, nil, err
+	}
+	return security.NewECDSAPublicKey(&priv.PublicKey), priv, nil
+}
+
 // LoadPEMKey loads a key from 'r'. returns PassphraseErr for incorrect Passphrase.
 // If the key held in 'r' is unencrypted, 'passphrase' will be ignored.
 func LoadPEMKey(r io.Reader, passphrase []byte) (interface{}, error) {
diff --git a/services/identity/identity.vdl.go b/services/identity/identity.vdl.go
index 85027dc..60a4fc0 100644
--- a/services/identity/identity.vdl.go
+++ b/services/identity/identity.vdl.go
@@ -84,9 +84,27 @@
 // It takes a regular server implementing the OAuthBlesserService
 // interface, and returns a new server stub.
 func NewServerOAuthBlesser(server OAuthBlesserService) interface{} {
-	return &ServerStubOAuthBlesser{
+	stub := &ServerStubOAuthBlesser{
 		service: server,
 	}
+	var gs _gen_ipc.GlobState
+	var self interface{} = stub
+	// VAllGlobber is implemented by the server object, which is wrapped in
+	// a VDL generated server stub.
+	if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VAllGlobber is implemented by the server object without using a VDL
+	// generated stub.
+	if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VChildrenGlobber is implemented in the server object.
+	if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+		gs.VChildrenGlobber = x
+	}
+	stub.gs = &gs
+	return stub
 }
 
 // clientStubOAuthBlesser implements OAuthBlesser.
@@ -151,6 +169,7 @@
 // the requirements of veyron2/ipc.ReflectInvoker.
 type ServerStubOAuthBlesser struct {
 	service OAuthBlesserService
+	gs      *_gen_ipc.GlobState
 }
 
 func (__gen_s *ServerStubOAuthBlesser) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -228,6 +247,10 @@
 	return
 }
 
+func (__gen_s *ServerStubOAuthBlesser) VGlob() *_gen_ipc.GlobState {
+	return __gen_s.gs
+}
+
 func (__gen_s *ServerStubOAuthBlesser) BlessUsingAccessToken(call _gen_ipc.ServerCall, token string) (blessing security.WireBlessings, email string, err error) {
 	blessing, email, err = __gen_s.service.BlessUsingAccessToken(call, token)
 	return
@@ -284,9 +307,27 @@
 // It takes a regular server implementing the MacaroonBlesserService
 // interface, and returns a new server stub.
 func NewServerMacaroonBlesser(server MacaroonBlesserService) interface{} {
-	return &ServerStubMacaroonBlesser{
+	stub := &ServerStubMacaroonBlesser{
 		service: server,
 	}
+	var gs _gen_ipc.GlobState
+	var self interface{} = stub
+	// VAllGlobber is implemented by the server object, which is wrapped in
+	// a VDL generated server stub.
+	if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VAllGlobber is implemented by the server object without using a VDL
+	// generated stub.
+	if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VChildrenGlobber is implemented in the server object.
+	if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+		gs.VChildrenGlobber = x
+	}
+	stub.gs = &gs
+	return stub
 }
 
 // clientStubMacaroonBlesser implements MacaroonBlesser.
@@ -351,6 +392,7 @@
 // the requirements of veyron2/ipc.ReflectInvoker.
 type ServerStubMacaroonBlesser struct {
 	service MacaroonBlesserService
+	gs      *_gen_ipc.GlobState
 }
 
 func (__gen_s *ServerStubMacaroonBlesser) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -427,6 +469,10 @@
 	return
 }
 
+func (__gen_s *ServerStubMacaroonBlesser) VGlob() *_gen_ipc.GlobState {
+	return __gen_s.gs
+}
+
 func (__gen_s *ServerStubMacaroonBlesser) Bless(call _gen_ipc.ServerCall, macaroon string) (reply security.WireBlessings, err error) {
 	reply, err = __gen_s.service.Bless(call, macaroon)
 	return
diff --git a/services/identity/identityd/main.go b/services/identity/identityd/main.go
index 5d4773f..f267b89 100644
--- a/services/identity/identityd/main.go
+++ b/services/identity/identityd/main.go
@@ -193,7 +193,7 @@
 
 	dispatcher := newDispatcher(googleParams, macaroonKey)
 	objectname := naming.Join("identity", fmt.Sprintf("%v", r.Principal().BlessingStore().Default()))
-	if err := server.Serve(objectname, dispatcher); err != nil {
+	if err := server.ServeDispatcher(objectname, dispatcher); err != nil {
 		return nil, nil, fmt.Errorf("failed to start Veyron services: %v", err)
 	}
 	vlog.Infof("Google blessing and discharger services enabled at %v", naming.JoinAddressName(ep.String(), objectname))
diff --git a/services/identity/revocation/revoker_test.go b/services/identity/revocation/revoker_test.go
index ad4ad7e..6bb2148 100644
--- a/services/identity/revocation/revoker_test.go
+++ b/services/identity/revocation/revoker_test.go
@@ -6,7 +6,6 @@
 	"testing"
 
 	"veyron.io/veyron/veyron2"
-	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/security"
@@ -33,7 +32,7 @@
 		t.Fatalf("dischargerServer.Listen failed: %v", err)
 	}
 	dischargerServiceStub := services.NewServerDischarger(discharger.NewDischarger())
-	if err := dischargerServer.Serve("", ipc.LeafDispatcher(dischargerServiceStub, nil)); err != nil {
+	if err := dischargerServer.Serve("", dischargerServiceStub, nil); err != nil {
 		t.Fatalf("dischargerServer.Serve revoker: %s", err)
 	}
 	return r.Principal().PublicKey(),
diff --git a/services/mgmt/application/applicationd/main.go b/services/mgmt/application/applicationd/main.go
index e815fa4..fa11016 100644
--- a/services/mgmt/application/applicationd/main.go
+++ b/services/mgmt/application/applicationd/main.go
@@ -39,7 +39,7 @@
 	if err != nil {
 		vlog.Fatalf("Listen(%s) failed: %v", roaming.ListenSpec, err)
 	}
-	if err := server.Serve(*name, dispatcher); err != nil {
+	if err := server.ServeDispatcher(*name, dispatcher); err != nil {
 		vlog.Fatalf("Serve(%v) failed: %v", *name, err)
 	}
 	vlog.Infof("Application repository running at endpoint=%q", endpoint)
diff --git a/services/mgmt/application/impl/impl_test.go b/services/mgmt/application/impl/impl_test.go
index 672a336..c073c99 100644
--- a/services/mgmt/application/impl/impl_test.go
+++ b/services/mgmt/application/impl/impl_test.go
@@ -45,7 +45,7 @@
 	if err != nil {
 		t.Fatalf("Listen(%s) failed: %v", profiles.LocalListenSpec, err)
 	}
-	if err := server.Serve("", dispatcher); err != nil {
+	if err := server.ServeDispatcher("", dispatcher); err != nil {
 		t.Fatalf("Serve(%v) failed: %v", dispatcher, err)
 	}
 
diff --git a/services/mgmt/binary/binaryd/main.go b/services/mgmt/binary/binaryd/main.go
index 28bb8ad..d67f1a7 100644
--- a/services/mgmt/binary/binaryd/main.go
+++ b/services/mgmt/binary/binaryd/main.go
@@ -3,6 +3,7 @@
 import (
 	"flag"
 	"io/ioutil"
+	"net"
 	"net/http"
 	"os"
 	"path/filepath"
@@ -10,6 +11,7 @@
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/vlog"
 
+	"veyron.io/veyron/veyron/lib/netstate"
 	"veyron.io/veyron/veyron/lib/signals"
 	"veyron.io/veyron/veyron/profiles/roaming"
 	vflag "veyron.io/veyron/veyron/security/flag"
@@ -22,12 +24,35 @@
 )
 
 var (
-	name = flag.String("name", "", "name to mount the binary repository as")
-	root = flag.String("root", "", "root directory for the binary repository")
+	name     = flag.String("name", "", "name to mount the binary repository as")
+	root     = flag.String("root", "", "root directory for the binary repository")
+	httpAddr = flag.String("http", ":0", "TCP address on which the HTTP  server runs")
 )
 
+// toIPPort tries to swap in the 'best' accessible IP for the host part of the
+// address, if the provided address has an unspecified IP.
+func toIPPort(addr string) string {
+	host, port, err := net.SplitHostPort(addr)
+	if err != nil {
+		vlog.Errorf("SplitHostPort(%v) failed: %v", addr, err)
+		os.Exit(1)
+	}
+	ip := net.ParseIP(host)
+	if ip.IsUnspecified() {
+		host = "127.0.0.1"
+		ips, err := netstate.GetAccessibleIPs()
+		if err == nil {
+			if a, err := roaming.ListenSpec.AddressChooser("tcp", ips); err == nil && len(a) > 0 {
+				host = a[0].Address().String()
+			}
+		}
+	}
+	return net.JoinHostPort(host, port)
+}
+
 func main() {
-	flag.Parse()
+	runtime := rt.Init()
+	defer runtime.Cleanup()
 	if *root == "" {
 		var err error
 		if *root, err = ioutil.TempDir("", defaultRootPrefix); err != nil {
@@ -67,16 +92,19 @@
 		return
 	}
 
-	// TODO(caprita): Flagify port.
+	listener, err := net.Listen("tcp", *httpAddr)
+	if err != nil {
+		vlog.Errorf("Listen(%s) failed: %v", *httpAddr, err)
+		os.Exit(1)
+	}
+	vlog.Infof("Binary repository HTTP server at: %q", toIPPort(listener.Addr().String()))
 	go func() {
-		if err := http.ListenAndServe(":8080", http.FileServer(impl.NewHTTPRoot(state))); err != nil {
-			vlog.Errorf("ListenAndServe() failed: %v", err)
+		if err := http.Serve(listener, http.FileServer(impl.NewHTTPRoot(state))); err != nil {
+			vlog.Errorf("Serve() failed: %v", err)
 			os.Exit(1)
 		}
 	}()
 
-	runtime := rt.Init()
-	defer runtime.Cleanup()
 	server, err := runtime.NewServer()
 	if err != nil {
 		vlog.Errorf("NewServer() failed: %v", err)
@@ -89,8 +117,8 @@
 		vlog.Errorf("Listen(%s) failed: %v", roaming.ListenSpec, err)
 		return
 	}
-	if err := server.Serve(*name, impl.NewDispatcher(state, auth)); err != nil {
-		vlog.Errorf("Serve(%v) failed: %v", *name, err)
+	if err := server.ServeDispatcher(*name, impl.NewDispatcher(state, auth)); err != nil {
+		vlog.Errorf("ServeDispatcher(%v) failed: %v", *name, err)
 		return
 	}
 	vlog.Infof("Binary repository running at endpoint=%q", endpoint)
diff --git a/services/mgmt/binary/binaryd/test.sh b/services/mgmt/binary/binaryd/test.sh
index e3547e9..2fd1661 100755
--- a/services/mgmt/binary/binaryd/test.sh
+++ b/services/mgmt/binary/binaryd/test.sh
@@ -25,6 +25,7 @@
   local -r REPO="binaryd-test-repo"
   shell_test::start_server "${BINARYD_BIN}" --name="${REPO}" --veyron.tcp.address=127.0.0.1:0 \
     || shell_test::fail "line ${LINENO} failed to start binaryd"
+  local -r HTTP_ADDR=$(grep 'HTTP server at: "' "${START_SERVER_LOG_FILE}" | sed -e 's/^.*HTTP server at: "//' | sed -e 's/"$//')
 
   # Create a binary file.
   local -r BINARY_SUFFIX="test-binary"
@@ -42,7 +43,7 @@
   fi
 
   local -r BINARY_FILE3=$(shell::tmp_file)
-  curl -f -o "${BINARY_FILE3}" http://localhost:8080/"${BINARY_SUFFIX}" || shell_test::fail "line ${LINENO}: 'HTTP download' failed"
+  curl -f -o "${BINARY_FILE3}" "http://${HTTP_ADDR}/${BINARY_SUFFIX}" || shell_test::fail "line ${LINENO}: 'HTTP download' failed"
   if [[ $(cmp "${BINARY_FILE}" "${BINARY_FILE3}" &> /dev/null) ]]; then
     shell_test::fail "mismatching binary file downloaded via HTTP"
   fi
diff --git a/services/mgmt/binary/impl/http.go b/services/mgmt/binary/impl/http.go
index df6ec69..251ff00 100644
--- a/services/mgmt/binary/impl/http.go
+++ b/services/mgmt/binary/impl/http.go
@@ -8,7 +8,7 @@
 
 	"veyron.io/veyron/veyron2/vlog"
 
-	"veyron.io/veyron/veyron/services/mgmt/binary/impl/merge_file"
+	"veyron.io/veyron/veyron/services/mgmt/binary/impl/multipart"
 )
 
 // NewHTTPRoot returns an implementation of http.FileSystem that can be used
@@ -24,7 +24,7 @@
 // TODO(caprita): Tie this in with DownloadURL, to control which binaries
 // are downloadable via url.
 
-// Open implements http.FileSystem.  It uses the merge file implementation
+// Open implements http.FileSystem.  It uses the multipart file implementation
 // to wrap the content parts into one logical file.
 func (r httpRoot) Open(name string) (http.File, error) {
 	name = strings.TrimPrefix(name, "/")
@@ -45,5 +45,5 @@
 			return nil, errOperationFailed
 		}
 	}
-	return merge_file.NewMergeFile(name, partFiles)
+	return multipart.NewFile(name, partFiles)
 }
diff --git a/services/mgmt/binary/impl/impl_test.go b/services/mgmt/binary/impl/impl_test.go
index 8212e1e..a38ef40 100644
--- a/services/mgmt/binary/impl/impl_test.go
+++ b/services/mgmt/binary/impl/impl_test.go
@@ -129,7 +129,7 @@
 		t.Fatalf("Listen(%s) failed: %v", profiles.LocalListenSpec, err)
 	}
 	dontPublishName := ""
-	if err := server.Serve(dontPublishName, dispatcher); err != nil {
+	if err := server.ServeDispatcher(dontPublishName, dispatcher); err != nil {
 		t.Fatalf("Serve(%q) failed: %v", dontPublishName, err)
 	}
 	name := naming.JoinAddressName(endpoint.String(), "//test")
diff --git a/services/mgmt/binary/impl/merge_file/merge_file.go b/services/mgmt/binary/impl/multipart/multipart.go
similarity index 73%
rename from services/mgmt/binary/impl/merge_file/merge_file.go
rename to services/mgmt/binary/impl/multipart/multipart.go
index 06dd1a2..ab43178 100644
--- a/services/mgmt/binary/impl/merge_file/merge_file.go
+++ b/services/mgmt/binary/impl/multipart/multipart.go
@@ -1,9 +1,6 @@
-// merge_file provides an implementation for http.File that merges
-// several files into one logical file.
-package merge_file
-
-// TODO(caprita): rename this package to multipart, and the constructor to
-// NewFile. Usage: f, err := multipart.NewFile(...).
+// multipart provides an implementation for http.File that acts as one logical
+// file backed by several physical files (the 'parts').
+package multipart
 
 import (
 	"fmt"
@@ -15,11 +12,11 @@
 
 var internalErr = fmt.Errorf("internal error")
 
-// NewMergeFile creates the "merge" file out of the provided parts.
+// NewFile creates the multipart file out of the provided parts.
 // The sizes of the parts are captured at the outset and not updated
-// for the lifetime of the merge file (any subsequent modifications
+// for the lifetime of the multipart file (any subsequent modifications
 // in the parts will cause Read and Seek to work incorrectly).
-func NewMergeFile(name string, parts []*os.File) (http.File, error) {
+func NewFile(name string, parts []*os.File) (http.File, error) {
 	fileParts := make([]filePart, len(parts))
 	for i, p := range parts {
 		stat, err := p.Stat()
@@ -33,7 +30,7 @@
 		}
 		fileParts[i] = filePart{file: p, size: size}
 	}
-	return &mergeFile{name: name, parts: fileParts}, nil
+	return &multipartFile{name: name, parts: fileParts}, nil
 }
 
 type filePart struct {
@@ -41,14 +38,14 @@
 	size int64
 }
 
-type mergeFile struct {
+type multipartFile struct {
 	name       string
 	parts      []filePart
 	activePart int
 	partOffset int64
 }
 
-func (m *mergeFile) currPos() (res int64) {
+func (m *multipartFile) currPos() (res int64) {
 	for i := 0; i < m.activePart; i++ {
 		res += m.parts[i].size
 	}
@@ -56,7 +53,7 @@
 	return
 }
 
-func (m *mergeFile) totalSize() (res int64) {
+func (m *multipartFile) totalSize() (res int64) {
 	for _, p := range m.parts {
 		res += p.size
 	}
@@ -64,7 +61,7 @@
 }
 
 // Readdir is not implemented.
-func (*mergeFile) Readdir(int) ([]os.FileInfo, error) {
+func (*multipartFile) Readdir(int) ([]os.FileInfo, error) {
 	return nil, fmt.Errorf("Not implemented")
 }
 
@@ -75,12 +72,12 @@
 	modTime time.Time
 }
 
-// Name returns the name of the merge file.
+// Name returns the name of the multipart file.
 func (f *fileInfo) Name() string {
 	return f.name
 }
 
-// Size returns the size of the merge file (the sum of all parts).
+// Size returns the size of the multipart file (the sum of all parts).
 func (f *fileInfo) Size() int64 {
 	return f.size
 }
@@ -105,8 +102,8 @@
 	return nil
 }
 
-// Stat describes the merge file.
-func (m *mergeFile) Stat() (os.FileInfo, error) {
+// Stat describes the multipart file.
+func (m *multipartFile) Stat() (os.FileInfo, error) {
 	return &fileInfo{
 		name:    m.name,
 		size:    m.totalSize(),
@@ -116,7 +113,7 @@
 }
 
 // Close closes all the parts.
-func (m *mergeFile) Close() error {
+func (m *multipartFile) Close() error {
 	var lastErr error
 	for _, p := range m.parts {
 		if err := p.file.Close(); err != nil {
@@ -127,7 +124,7 @@
 }
 
 // Read reads from the parts in sequence.
-func (m *mergeFile) Read(buf []byte) (int, error) {
+func (m *multipartFile) Read(buf []byte) (int, error) {
 	if m.activePart >= len(m.parts) {
 		return 0, io.EOF
 	}
@@ -151,7 +148,7 @@
 }
 
 // Seek seeks into the part corresponding to the global offset.
-func (m *mergeFile) Seek(offset int64, whence int) (int64, error) {
+func (m *multipartFile) Seek(offset int64, whence int) (int64, error) {
 	var target int64
 	switch whence {
 	case 0:
diff --git a/services/mgmt/binary/impl/merge_file/merge_file_test.go b/services/mgmt/binary/impl/multipart/multipart_test.go
similarity index 91%
rename from services/mgmt/binary/impl/merge_file/merge_file_test.go
rename to services/mgmt/binary/impl/multipart/multipart_test.go
index 1d903a1..9866697 100644
--- a/services/mgmt/binary/impl/merge_file/merge_file_test.go
+++ b/services/mgmt/binary/impl/multipart/multipart_test.go
@@ -1,4 +1,4 @@
-package merge_file_test
+package multipart_test
 
 import (
 	"io"
@@ -10,7 +10,7 @@
 	"strings"
 	"testing"
 
-	"veyron.io/veyron/veyron/services/mgmt/binary/impl/merge_file"
+	"veyron.io/veyron/veyron/services/mgmt/binary/impl/multipart"
 )
 
 func read(t *testing.T, m http.File, thisMuch int) string {
@@ -32,11 +32,11 @@
 	}
 }
 
-// TestMergeFile verifies the http.File operations on the merge file.
-func TestMergeFile(t *testing.T) {
+// TestFile verifies the http.File operations on the multipart file.
+func TestFile(t *testing.T) {
 	contents := []string{"v", "is", "for", "vanadium"}
 	files := make([]*os.File, len(contents))
-	d, err := ioutil.TempDir("", "merge_files")
+	d, err := ioutil.TempDir("", "multiparts")
 	if err != nil {
 		t.Fatalf("TempDir() failed: %v", err)
 	}
@@ -53,9 +53,9 @@
 			t.Fatalf("Open(%v) failed: %v", fPath, err)
 		}
 	}
-	m, err := merge_file.NewMergeFile("bunnies", files)
+	m, err := multipart.NewFile("bunnies", files)
 	if err != nil {
-		t.Fatalf("newMergeFile failed: %v", err)
+		t.Fatalf("NewFile failed: %v", err)
 	}
 	defer func() {
 		if err := m.Close(); err != nil {
diff --git a/services/mgmt/build/buildd/main.go b/services/mgmt/build/buildd/main.go
index b46e98c..6d05b59 100644
--- a/services/mgmt/build/buildd/main.go
+++ b/services/mgmt/build/buildd/main.go
@@ -4,7 +4,6 @@
 	"flag"
 	"os"
 
-	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/services/mgmt/build"
 	"veyron.io/veyron/veyron2/vlog"
@@ -36,7 +35,7 @@
 		vlog.Errorf("Listen(%s) failed: %v", roaming.ListenSpec, err)
 		return
 	}
-	if err := server.Serve(*name, ipc.LeafDispatcher(build.NewServerBuilder(impl.NewInvoker(*gobin, *goroot)), vflag.NewAuthorizerOrDie())); err != nil {
+	if err := server.Serve(*name, build.NewServerBuilder(impl.NewInvoker(*gobin, *goroot)), vflag.NewAuthorizerOrDie()); err != nil {
 		vlog.Errorf("Serve(%v) failed: %v", *name, err)
 		return
 	}
diff --git a/services/mgmt/build/impl/impl_test.go b/services/mgmt/build/impl/impl_test.go
index dd4be30..37f0f5a 100644
--- a/services/mgmt/build/impl/impl_test.go
+++ b/services/mgmt/build/impl/impl_test.go
@@ -8,7 +8,6 @@
 	"strings"
 	"testing"
 
-	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/services/mgmt/build"
 
@@ -58,7 +57,7 @@
 		t.Fatalf("Listen(%s) failed: %v", profiles.LocalListenSpec, err)
 	}
 	unpublished := ""
-	if err := server.Serve(unpublished, ipc.LeafDispatcher(build.NewServerBuilder(NewInvoker(gobin, goroot)), nil)); err != nil {
+	if err := server.Serve(unpublished, build.NewServerBuilder(NewInvoker(gobin, goroot)), nil); err != nil {
 		t.Fatalf("Serve(%q) failed: %v", unpublished, err)
 	}
 	name := "/" + endpoint.String()
diff --git a/services/mgmt/debug/debug.vdl.go b/services/mgmt/debug/debug.vdl.go
index 96e09d0..34514b4 100644
--- a/services/mgmt/debug/debug.vdl.go
+++ b/services/mgmt/debug/debug.vdl.go
@@ -97,12 +97,30 @@
 // It takes a regular server implementing the DebugService
 // interface, and returns a new server stub.
 func NewServerDebug(server DebugService) interface{} {
-	return &ServerStubDebug{
+	stub := &ServerStubDebug{
 		ServerStubLogFile: *logreader.NewServerLogFile(server).(*logreader.ServerStubLogFile),
 		ServerStubStats:   *stats.NewServerStats(server).(*stats.ServerStubStats),
 		ServerStubPProf:   *pprof.NewServerPProf(server).(*pprof.ServerStubPProf),
 		service:           server,
 	}
+	var gs _gen_ipc.GlobState
+	var self interface{} = stub
+	// VAllGlobber is implemented by the server object, which is wrapped in
+	// a VDL generated server stub.
+	if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VAllGlobber is implemented by the server object without using a VDL
+	// generated stub.
+	if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VChildrenGlobber is implemented in the server object.
+	if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+		gs.VChildrenGlobber = x
+	}
+	stub.gs = &gs
+	return stub
 }
 
 // clientStubDebug implements Debug.
@@ -164,6 +182,7 @@
 	pprof.ServerStubPProf
 
 	service DebugService
+	gs      *_gen_ipc.GlobState
 }
 
 func (__gen_s *ServerStubDebug) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -368,3 +387,7 @@
 	}
 	return
 }
+
+func (__gen_s *ServerStubDebug) VGlob() *_gen_ipc.GlobState {
+	return __gen_s.gs
+}
diff --git a/services/mgmt/debug/server.go b/services/mgmt/debug/server.go
index 95b8c13..4cff33a 100644
--- a/services/mgmt/debug/server.go
+++ b/services/mgmt/debug/server.go
@@ -25,7 +25,7 @@
 	if err != nil {
 		return "", nil, fmt.Errorf("failed to listen on %s: %v", listenSpec, err)
 	}
-	if err := server.Serve("", disp); err != nil {
+	if err := server.ServeDispatcher("", disp); err != nil {
 		return "", nil, err
 	}
 	ep := endpoint.String()
diff --git a/services/mgmt/lib/binary/impl_test.go b/services/mgmt/lib/binary/impl_test.go
index 8ec796f..8da8032 100644
--- a/services/mgmt/lib/binary/impl_test.go
+++ b/services/mgmt/lib/binary/impl_test.go
@@ -51,7 +51,7 @@
 		t.Fatalf("Listen(%s) failed: %v", profiles.LocalListenSpec, err)
 	}
 	suffix := ""
-	if err := server.Serve(suffix, dispatcher); err != nil {
+	if err := server.ServeDispatcher(suffix, dispatcher); err != nil {
 		t.Fatalf("Serve(%v, %v) failed: %v", suffix, dispatcher, err)
 	}
 	von := naming.JoinAddressName(endpoint.String(), "//test")
diff --git a/services/mgmt/logreader/impl/common_test.go b/services/mgmt/logreader/impl/common_test.go
index c81320b..91194ad 100644
--- a/services/mgmt/logreader/impl/common_test.go
+++ b/services/mgmt/logreader/impl/common_test.go
@@ -20,7 +20,7 @@
 		t.Fatalf("Listen failed: %v", err)
 		return nil, "", err
 	}
-	if err := server.Serve("", disp); err != nil {
+	if err := server.ServeDispatcher("", disp); err != nil {
 		t.Fatalf("Serve failed: %v", err)
 		return nil, "", err
 	}
diff --git a/services/mgmt/node/config.vdl.go b/services/mgmt/node/config.vdl.go
index 5ef274f..7b9dfbe 100644
--- a/services/mgmt/node/config.vdl.go
+++ b/services/mgmt/node/config.vdl.go
@@ -67,9 +67,27 @@
 // It takes a regular server implementing the ConfigService
 // interface, and returns a new server stub.
 func NewServerConfig(server ConfigService) interface{} {
-	return &ServerStubConfig{
+	stub := &ServerStubConfig{
 		service: server,
 	}
+	var gs _gen_ipc.GlobState
+	var self interface{} = stub
+	// VAllGlobber is implemented by the server object, which is wrapped in
+	// a VDL generated server stub.
+	if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VAllGlobber is implemented by the server object without using a VDL
+	// generated stub.
+	if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VChildrenGlobber is implemented in the server object.
+	if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+		gs.VChildrenGlobber = x
+	}
+	stub.gs = &gs
+	return stub
 }
 
 // clientStubConfig implements Config.
@@ -134,6 +152,7 @@
 // the requirements of veyron2/ipc.ReflectInvoker.
 type ServerStubConfig struct {
 	service ConfigService
+	gs      *_gen_ipc.GlobState
 }
 
 func (__gen_s *ServerStubConfig) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -184,6 +203,10 @@
 	return
 }
 
+func (__gen_s *ServerStubConfig) VGlob() *_gen_ipc.GlobState {
+	return __gen_s.gs
+}
+
 func (__gen_s *ServerStubConfig) Set(call _gen_ipc.ServerCall, key string, value string) (err error) {
 	err = __gen_s.service.Set(call, key, value)
 	return
diff --git a/services/mgmt/node/impl/config_invoker.go b/services/mgmt/node/impl/config_invoker.go
index 7e191ac..97ccc35 100644
--- a/services/mgmt/node/impl/config_invoker.go
+++ b/services/mgmt/node/impl/config_invoker.go
@@ -78,7 +78,7 @@
 
 func (c *callbackState) listenFor(key string) callbackListener {
 	id := c.generateID()
-	callbackName := naming.MakeTerminal(naming.Join(c.name, configSuffix, id))
+	callbackName := naming.Join(c.name, configSuffix, id)
 	// Make the channel buffered to avoid blocking the Set method when
 	// nothing is receiving on the channel.  This happens e.g. when
 	// unregisterCallbacks executes before Set is called.
diff --git a/services/mgmt/node/impl/impl_test.go b/services/mgmt/node/impl/impl_test.go
index e412e63..a5670c2 100644
--- a/services/mgmt/node/impl/impl_test.go
+++ b/services/mgmt/node/impl/impl_test.go
@@ -143,7 +143,7 @@
 	defer rt.R().Cleanup()
 	server, endpoint := newServer()
 	defer server.Stop()
-	name := naming.MakeTerminal(naming.JoinAddressName(endpoint, ""))
+	name := naming.JoinAddressName(endpoint, "")
 	vlog.VI(1).Infof("Node manager name: %v", name)
 
 	// Satisfy the contract described in doc.go by passing the config state
@@ -167,7 +167,7 @@
 	if err != nil {
 		vlog.Fatalf("Failed to create node manager dispatcher: %v", err)
 	}
-	if err := server.Serve(publishName, dispatcher); err != nil {
+	if err := server.ServeDispatcher(publishName, dispatcher); err != nil {
 		vlog.Fatalf("Serve(%v) failed: %v", publishName, err)
 	}
 	impl.InvokeCallback(name)
@@ -239,7 +239,7 @@
 	defer rt.R().Cleanup()
 	server, _ := newServer()
 	defer server.Stop()
-	if err := server.Serve(publishName, ipc.LeafDispatcher(new(appService), nil)); err != nil {
+	if err := server.Serve(publishName, new(appService), nil); err != nil {
 		vlog.Fatalf("Serve(%v) failed: %v", publishName, err)
 	}
 	ping()
@@ -497,7 +497,7 @@
 func setupPingServer(t *testing.T) (<-chan string, func()) {
 	server, _ := newServer()
 	pingCh := make(chan string, 1)
-	if err := server.Serve("pingserver", ipc.LeafDispatcher(pingServerDisp(pingCh), nil)); err != nil {
+	if err := server.Serve("pingserver", pingServerDisp(pingCh), nil); err != nil {
 		t.Fatalf("Serve(%q, <dispatcher>) failed: %v", "pingserver", err)
 	}
 	return pingCh, func() {
@@ -1329,7 +1329,7 @@
 	server, _ := newServer()
 	defer server.Stop()
 	pingCh := make(chan string, 1)
-	if err := server.Serve("pingserver", ipc.LeafDispatcher(pingServerDisp(pingCh), nil)); err != nil {
+	if err := server.Serve("pingserver", pingServerDisp(pingCh), nil); err != nil {
 		t.Fatalf("Serve(%q, <dispatcher>) failed: %v", "pingserver", err)
 	}
 
diff --git a/services/mgmt/node/impl/mock_repo_test.go b/services/mgmt/node/impl/mock_repo_test.go
index dd90a6a..cc8241f 100644
--- a/services/mgmt/node/impl/mock_repo_test.go
+++ b/services/mgmt/node/impl/mock_repo_test.go
@@ -35,9 +35,8 @@
 func startApplicationRepository() (*application.Envelope, func()) {
 	server, _ := newServer()
 	invoker := new(arInvoker)
-	dispatcher := ipc.LeafDispatcher(repository.NewServerApplication(invoker), nil)
 	name := mockApplicationRepoName
-	if err := server.Serve(name, dispatcher); err != nil {
+	if err := server.Serve(name, repository.NewServerApplication(invoker), nil); err != nil {
 		vlog.Fatalf("Serve(%v) failed: %v", name, err)
 	}
 	return &invoker.envelope, func() {
@@ -68,9 +67,8 @@
 // returns a cleanup function.
 func startBinaryRepository() func() {
 	server, _ := newServer()
-	dispatcher := ipc.LeafDispatcher(repository.NewServerBinary(new(brInvoker)), nil)
 	name := mockBinaryRepoName
-	if err := server.Serve(name, dispatcher); err != nil {
+	if err := server.Serve(name, repository.NewServerBinary(new(brInvoker)), nil); err != nil {
 		vlog.Fatalf("Serve(%q) failed: %v", name, err)
 	}
 	return func() {
diff --git a/services/mgmt/node/impl/node_invoker.go b/services/mgmt/node/impl/node_invoker.go
index 7374abd..309d867 100644
--- a/services/mgmt/node/impl/node_invoker.go
+++ b/services/mgmt/node/impl/node_invoker.go
@@ -256,7 +256,7 @@
 		return errOperationFailed
 	}
 	// Check that invoking Update() succeeds.
-	childName = naming.MakeTerminal(naming.Join(childName, "nm"))
+	childName = naming.Join(childName, "nm")
 	nmClient, err := node.BindNode(childName)
 	if err != nil {
 		vlog.Errorf("BindNode(%v) failed: %v", childName, err)
diff --git a/services/mgmt/node/impl/proxy_invoker.go b/services/mgmt/node/impl/proxy_invoker.go
index b46733c..fb52ef7 100644
--- a/services/mgmt/node/impl/proxy_invoker.go
+++ b/services/mgmt/node/impl/proxy_invoker.go
@@ -121,6 +121,11 @@
 	return results, err
 }
 
+func (p *proxyInvoker) VGlob() *ipc.GlobState {
+	// TODO(rthellend): Add implementation
+	return nil
+}
+
 // numResults returns the number of result values for the given method.
 func (p *proxyInvoker) numResults(method string) (int, error) {
 	sig, err := p.sigStub.Signature(nil)
diff --git a/services/mgmt/node/impl/proxy_invoker_test.go b/services/mgmt/node/impl/proxy_invoker_test.go
index b27c671..b2861f6 100644
--- a/services/mgmt/node/impl/proxy_invoker_test.go
+++ b/services/mgmt/node/impl/proxy_invoker_test.go
@@ -16,7 +16,7 @@
 func TestProxyInvoker(t *testing.T) {
 	r := rt.R()
 
-	// server1 is a normal server with a nil dispatcher.
+	// server1 is a normal server
 	server1, err := r.NewServer()
 	if err != nil {
 		t.Fatalf("NewServer: %v", err)
@@ -27,7 +27,7 @@
 	if err != nil {
 		t.Fatalf("Listen: %v", err)
 	}
-	if err := server1.Serve("", nil); err != nil {
+	if err := server1.Serve("", &dummy{}, nil); err != nil {
 		t.Fatalf("server1.Serve: %v", err)
 	}
 
@@ -46,7 +46,7 @@
 		security.Label(security.AllLabels),
 		&stats.ServerStubStats{},
 	}
-	if err := server2.Serve("", disp); err != nil {
+	if err := server2.ServeDispatcher("", disp); err != nil {
 		t.Fatalf("server2.Serve: %v", err)
 	}
 
@@ -95,6 +95,10 @@
 	return results
 }
 
+type dummy struct{}
+
+func (*dummy) Method(_ ipc.ServerCall) error { return nil }
+
 type proxyDispatcher struct {
 	remote  string
 	label   security.Label
diff --git a/services/mgmt/node/noded/main.go b/services/mgmt/node/noded/main.go
index cda1286..f1b9a2d 100644
--- a/services/mgmt/node/noded/main.go
+++ b/services/mgmt/node/noded/main.go
@@ -50,7 +50,7 @@
 	if err != nil {
 		vlog.Fatalf("Listen(%s) failed: %v", roaming.ListenSpec, err)
 	}
-	name := naming.MakeTerminal(naming.JoinAddressName(endpoint.String(), ""))
+	name := naming.JoinAddressName(endpoint.String(), "")
 	vlog.VI(0).Infof("Node manager object name: %v", name)
 	configState, err := config.Load()
 	if err != nil {
@@ -65,7 +65,7 @@
 	if err != nil {
 		vlog.Fatalf("Failed to create dispatcher: %v", err)
 	}
-	if err := server.Serve(*publishAs, dispatcher); err != nil {
+	if err := server.ServeDispatcher(*publishAs, dispatcher); err != nil {
 		vlog.Fatalf("Serve(%v) failed: %v", *publishAs, err)
 	}
 	impl.InvokeCallback(name)
diff --git a/services/mgmt/pprof/client/proxy_test.go b/services/mgmt/pprof/client/proxy_test.go
index a563d9f..9b9c655 100644
--- a/services/mgmt/pprof/client/proxy_test.go
+++ b/services/mgmt/pprof/client/proxy_test.go
@@ -37,7 +37,7 @@
 	if err != nil {
 		t.Fatalf("failed to listen: %v", err)
 	}
-	if err := s.Serve("", &dispatcher{impl.NewInvoker()}); err != nil {
+	if err := s.ServeDispatcher("", &dispatcher{impl.NewInvoker()}); err != nil {
 		t.Fatalf("failed to serve: %v", err)
 	}
 	l, err := client.StartProxy(r, naming.JoinAddressName(endpoint.String(), ""))
diff --git a/services/mgmt/profile/impl/impl_test.go b/services/mgmt/profile/impl/impl_test.go
index ec4a864..d869dc1 100644
--- a/services/mgmt/profile/impl/impl_test.go
+++ b/services/mgmt/profile/impl/impl_test.go
@@ -59,7 +59,7 @@
 	if err != nil {
 		t.Fatalf("Listen(%s) failed: %v", profiles.LocalListenSpec, err)
 	}
-	if err := server.Serve("", dispatcher); err != nil {
+	if err := server.ServeDispatcher("", dispatcher); err != nil {
 		t.Fatalf("Serve failed: %v", err)
 	}
 	t.Logf("Profile repository at %v", endpoint)
diff --git a/services/mgmt/profile/profiled/main.go b/services/mgmt/profile/profiled/main.go
index 3aee540..d01b803 100644
--- a/services/mgmt/profile/profiled/main.go
+++ b/services/mgmt/profile/profiled/main.go
@@ -39,8 +39,8 @@
 	if err != nil {
 		vlog.Fatalf("Listen(%s) failed: %v", roaming.ListenSpec, err)
 	}
-	if err := server.Serve(*name, dispatcher); err != nil {
-		vlog.Fatalf("Serve(%v) failed: %v", *name, err)
+	if err := server.ServeDispatcher(*name, dispatcher); err != nil {
+		vlog.Fatalf("ServeDispatcher(%v) failed: %v", *name, err)
 	}
 	vlog.Infof("Profile repository running at endpoint=%q", endpoint)
 
diff --git a/services/mgmt/repository/repository.vdl.go b/services/mgmt/repository/repository.vdl.go
index 57ac530..93dbd1a 100644
--- a/services/mgmt/repository/repository.vdl.go
+++ b/services/mgmt/repository/repository.vdl.go
@@ -122,10 +122,28 @@
 // It takes a regular server implementing the ApplicationService
 // interface, and returns a new server stub.
 func NewServerApplication(server ApplicationService) interface{} {
-	return &ServerStubApplication{
+	stub := &ServerStubApplication{
 		ServerStubApplication: *repository.NewServerApplication(server).(*repository.ServerStubApplication),
 		service:               server,
 	}
+	var gs _gen_ipc.GlobState
+	var self interface{} = stub
+	// VAllGlobber is implemented by the server object, which is wrapped in
+	// a VDL generated server stub.
+	if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VAllGlobber is implemented by the server object without using a VDL
+	// generated stub.
+	if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VChildrenGlobber is implemented in the server object.
+	if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+		gs.VChildrenGlobber = x
+	}
+	stub.gs = &gs
+	return stub
 }
 
 // clientStubApplication implements Application.
@@ -205,6 +223,7 @@
 	repository.ServerStubApplication
 
 	service ApplicationService
+	gs      *_gen_ipc.GlobState
 }
 
 func (__gen_s *ServerStubApplication) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -331,6 +350,10 @@
 	return
 }
 
+func (__gen_s *ServerStubApplication) VGlob() *_gen_ipc.GlobState {
+	return __gen_s.gs
+}
+
 func (__gen_s *ServerStubApplication) Put(call _gen_ipc.ServerCall, Profiles []string, Envelope application.Envelope) (err error) {
 	err = __gen_s.service.Put(call, Profiles, Envelope)
 	return
@@ -416,10 +439,28 @@
 // It takes a regular server implementing the ProfileService
 // interface, and returns a new server stub.
 func NewServerProfile(server ProfileService) interface{} {
-	return &ServerStubProfile{
+	stub := &ServerStubProfile{
 		ServerStubProfile: *repository.NewServerProfile(server).(*repository.ServerStubProfile),
 		service:           server,
 	}
+	var gs _gen_ipc.GlobState
+	var self interface{} = stub
+	// VAllGlobber is implemented by the server object, which is wrapped in
+	// a VDL generated server stub.
+	if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VAllGlobber is implemented by the server object without using a VDL
+	// generated stub.
+	if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VChildrenGlobber is implemented in the server object.
+	if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+		gs.VChildrenGlobber = x
+	}
+	stub.gs = &gs
+	return stub
 }
 
 // clientStubProfile implements Profile.
@@ -510,6 +551,7 @@
 	repository.ServerStubProfile
 
 	service ProfileService
+	gs      *_gen_ipc.GlobState
 }
 
 func (__gen_s *ServerStubProfile) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -651,6 +693,10 @@
 	return
 }
 
+func (__gen_s *ServerStubProfile) VGlob() *_gen_ipc.GlobState {
+	return __gen_s.gs
+}
+
 func (__gen_s *ServerStubProfile) Specification(call _gen_ipc.ServerCall) (reply profile.Specification, err error) {
 	reply, err = __gen_s.service.Specification(call)
 	return
diff --git a/services/mgmt/root/root.vdl.go b/services/mgmt/root/root.vdl.go
index 273f77b..452cff5 100644
--- a/services/mgmt/root/root.vdl.go
+++ b/services/mgmt/root/root.vdl.go
@@ -72,9 +72,27 @@
 // It takes a regular server implementing the RootService
 // interface, and returns a new server stub.
 func NewServerRoot(server RootService) interface{} {
-	return &ServerStubRoot{
+	stub := &ServerStubRoot{
 		service: server,
 	}
+	var gs _gen_ipc.GlobState
+	var self interface{} = stub
+	// VAllGlobber is implemented by the server object, which is wrapped in
+	// a VDL generated server stub.
+	if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VAllGlobber is implemented by the server object without using a VDL
+	// generated stub.
+	if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VChildrenGlobber is implemented in the server object.
+	if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+		gs.VChildrenGlobber = x
+	}
+	stub.gs = &gs
+	return stub
 }
 
 // clientStubRoot implements Root.
@@ -139,6 +157,7 @@
 // the requirements of veyron2/ipc.ReflectInvoker.
 type ServerStubRoot struct {
 	service RootService
+	gs      *_gen_ipc.GlobState
 }
 
 func (__gen_s *ServerStubRoot) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -188,6 +207,10 @@
 	return
 }
 
+func (__gen_s *ServerStubRoot) VGlob() *_gen_ipc.GlobState {
+	return __gen_s.gs
+}
+
 func (__gen_s *ServerStubRoot) Reset(call _gen_ipc.ServerCall, Deadline uint64) (err error) {
 	err = __gen_s.service.Reset(call, Deadline)
 	return
diff --git a/services/mgmt/root/rootd/main.go b/services/mgmt/root/rootd/main.go
index 1b93942..ff23fdc 100644
--- a/services/mgmt/root/rootd/main.go
+++ b/services/mgmt/root/rootd/main.go
@@ -26,8 +26,8 @@
 	}
 	vlog.VI(0).Infof("Listening on %v", ep)
 	name := ""
-	if err := server.Serve(name, dispatcher); err != nil {
-		vlog.Errorf("Serve(%v) failed: %v", name, err)
+	if err := server.ServeDispatcher(name, dispatcher); err != nil {
+		vlog.Errorf("ServeDispatcher(%v) failed: %v", name, err)
 		return
 	}
 
diff --git a/services/mgmt/stats/impl/stats_invoker_test.go b/services/mgmt/stats/impl/stats_invoker_test.go
index d15c915..e830fad 100644
--- a/services/mgmt/stats/impl/stats_invoker_test.go
+++ b/services/mgmt/stats/impl/stats_invoker_test.go
@@ -38,7 +38,7 @@
 		t.Fatalf("Listen failed: %v", err)
 		return "", nil
 	}
-	if err := server.Serve("", disp); err != nil {
+	if err := server.ServeDispatcher("", disp); err != nil {
 		t.Fatalf("Serve failed: %v", err)
 		return "", nil
 	}
diff --git a/services/mounttable/lib/collection_test.vdl b/services/mounttable/lib/collection_test_interface.vdl
similarity index 100%
rename from services/mounttable/lib/collection_test.vdl
rename to services/mounttable/lib/collection_test_interface.vdl
diff --git a/services/mounttable/lib/collection_test.vdl.go b/services/mounttable/lib/collection_test_interface.vdl.go
similarity index 90%
rename from services/mounttable/lib/collection_test.vdl.go
rename to services/mounttable/lib/collection_test_interface.vdl.go
index e31a27d..377eeb2 100644
--- a/services/mounttable/lib/collection_test.vdl.go
+++ b/services/mounttable/lib/collection_test_interface.vdl.go
@@ -1,5 +1,5 @@
 // This file was auto-generated by the veyron vdl tool.
-// Source: collection_test.vdl
+// Source: collection_test_interface.vdl
 
 package mounttable
 
@@ -78,9 +78,27 @@
 // It takes a regular server implementing the CollectionService
 // interface, and returns a new server stub.
 func NewServerCollection(server CollectionService) interface{} {
-	return &ServerStubCollection{
+	stub := &ServerStubCollection{
 		service: server,
 	}
+	var gs _gen_ipc.GlobState
+	var self interface{} = stub
+	// VAllGlobber is implemented by the server object, which is wrapped in
+	// a VDL generated server stub.
+	if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VAllGlobber is implemented by the server object without using a VDL
+	// generated stub.
+	if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VChildrenGlobber is implemented in the server object.
+	if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+		gs.VChildrenGlobber = x
+	}
+	stub.gs = &gs
+	return stub
 }
 
 // clientStubCollection implements Collection.
@@ -156,6 +174,7 @@
 // the requirements of veyron2/ipc.ReflectInvoker.
 type ServerStubCollection struct {
 	service CollectionService
+	gs      *_gen_ipc.GlobState
 }
 
 func (__gen_s *ServerStubCollection) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -215,6 +234,10 @@
 	return
 }
 
+func (__gen_s *ServerStubCollection) VGlob() *_gen_ipc.GlobState {
+	return __gen_s.gs
+}
+
 func (__gen_s *ServerStubCollection) Export(call _gen_ipc.ServerCall, Val string, Overwrite bool) (err error) {
 	err = __gen_s.service.Export(call, Val, Overwrite)
 	return
diff --git a/services/mounttable/lib/mounttable_test.go b/services/mounttable/lib/mounttable_test.go
index f4a3bed..5a011f1 100644
--- a/services/mounttable/lib/mounttable_test.go
+++ b/services/mounttable/lib/mounttable_test.go
@@ -176,7 +176,7 @@
 	if err != nil {
 		boom(t, "Failed to Listen mount table: %s", err)
 	}
-	if err := server.Serve("", mt); err != nil {
+	if err := server.ServeDispatcher("", mt); err != nil {
 		boom(t, "Failed to register mock collection: %s", err)
 	}
 	estr := e.String()
@@ -197,7 +197,7 @@
 	// Add a collection service.  This is just a service we can mount
 	// and test against.
 	cPrefix := "collection"
-	if err := server.Serve(cPrefix, newCollectionServer()); err != nil {
+	if err := server.ServeDispatcher(cPrefix, newCollectionServer()); err != nil {
 		boom(t, "Failed to register mock collection: %s", err)
 	}
 	estr := e.String()
diff --git a/services/mounttable/lib/neighborhood_test.go b/services/mounttable/lib/neighborhood_test.go
index 07146da..f4d47c6 100644
--- a/services/mounttable/lib/neighborhood_test.go
+++ b/services/mounttable/lib/neighborhood_test.go
@@ -55,7 +55,7 @@
 		boom(t, "Failed to create neighborhood server: %s\n", err)
 	}
 	defer nhd.Stop()
-	if err := server.Serve("", nhd); err != nil {
+	if err := server.ServeDispatcher("", nhd); err != nil {
 		boom(t, "Failed to register neighborhood server: %s", err)
 	}
 
diff --git a/services/mounttable/mounttabled/mounttable.go b/services/mounttable/mounttabled/mounttable.go
index 7a4be80..0ef7b3b 100644
--- a/services/mounttable/mounttabled/mounttable.go
+++ b/services/mounttable/mounttabled/mounttable.go
@@ -43,8 +43,8 @@
 		os.Exit(1)
 	}
 	name := *mountName
-	if err := mtServer.Serve(name, mt); err != nil {
-		vlog.Errorf("Serve(%v) failed: %v", name, err)
+	if err := mtServer.ServeDispatcher(name, mt); err != nil {
+		vlog.Errorf("ServeDispatcher(%v) failed: %v", name, err)
 		os.Exit(1)
 	}
 
@@ -77,8 +77,8 @@
 			vlog.Errorf("NewNeighborhoodServer failed: %v", err)
 			os.Exit(1)
 		}
-		if err := nhServer.Serve(naming.JoinAddressName(myObjectName, "//nh"), nh); err != nil {
-			vlog.Errorf("nhServer.Serve failed to register neighborhood: %v", err)
+		if err := nhServer.ServeDispatcher(naming.JoinAddressName(myObjectName, "//nh"), nh); err != nil {
+			vlog.Errorf("nhServer.ServeDispatcher failed to register neighborhood: %v", err)
 			os.Exit(1)
 		}
 	}
diff --git a/services/security/discharger.vdl.go b/services/security/discharger.vdl.go
index 6793150..b36f608 100644
--- a/services/security/discharger.vdl.go
+++ b/services/security/discharger.vdl.go
@@ -83,9 +83,27 @@
 // It takes a regular server implementing the DischargerService
 // interface, and returns a new server stub.
 func NewServerDischarger(server DischargerService) interface{} {
-	return &ServerStubDischarger{
+	stub := &ServerStubDischarger{
 		service: server,
 	}
+	var gs _gen_ipc.GlobState
+	var self interface{} = stub
+	// VAllGlobber is implemented by the server object, which is wrapped in
+	// a VDL generated server stub.
+	if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VAllGlobber is implemented by the server object without using a VDL
+	// generated stub.
+	if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VChildrenGlobber is implemented in the server object.
+	if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+		gs.VChildrenGlobber = x
+	}
+	stub.gs = &gs
+	return stub
 }
 
 // clientStubDischarger implements Discharger.
@@ -150,6 +168,7 @@
 // the requirements of veyron2/ipc.ReflectInvoker.
 type ServerStubDischarger struct {
 	service DischargerService
+	gs      *_gen_ipc.GlobState
 }
 
 func (__gen_s *ServerStubDischarger) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -208,6 +227,10 @@
 	return
 }
 
+func (__gen_s *ServerStubDischarger) VGlob() *_gen_ipc.GlobState {
+	return __gen_s.gs
+}
+
 func (__gen_s *ServerStubDischarger) Discharge(call _gen_ipc.ServerCall, Caveat _gen_vdlutil.Any, Impetus security.DischargeImpetus) (reply _gen_vdlutil.Any, err error) {
 	reply, err = __gen_s.service.Discharge(call, Caveat, Impetus)
 	return
diff --git a/tools/application/impl_test.go b/tools/application/impl_test.go
index c55a5e9..bd323c9 100644
--- a/tools/application/impl_test.go
+++ b/tools/application/impl_test.go
@@ -85,7 +85,7 @@
 		t.Errorf("Listen failed: %v", err)
 		return nil, nil, err
 	}
-	if err := server.Serve("", dispatcher); err != nil {
+	if err := server.ServeDispatcher("", dispatcher); err != nil {
 		t.Errorf("Serve failed: %v", err)
 		return nil, nil, err
 	}
diff --git a/tools/associate/impl_test.go b/tools/associate/impl_test.go
index fff2ee5..54850d0 100644
--- a/tools/associate/impl_test.go
+++ b/tools/associate/impl_test.go
@@ -109,8 +109,8 @@
 		stopServer(t, server)
 		return nil, nil, err
 	}
-	if err := server.Serve("", dispatcher); err != nil {
-		t.Errorf("Serve failed: %v", err)
+	if err := server.ServeDispatcher("", dispatcher); err != nil {
+		t.Errorf("ServeDispatcher failed: %v", err)
 		stopServer(t, server)
 		return nil, nil, err
 	}
diff --git a/tools/binary/impl_test.go b/tools/binary/impl_test.go
index a924a93..d2379ec 100644
--- a/tools/binary/impl_test.go
+++ b/tools/binary/impl_test.go
@@ -94,8 +94,8 @@
 		t.Errorf("Listen failed: %v", err)
 		return nil, nil, err
 	}
-	if err := server.Serve("", dispatcher); err != nil {
-		t.Errorf("Serve failed: %v", err)
+	if err := server.ServeDispatcher("", dispatcher); err != nil {
+		t.Errorf("ServeDispatcher failed: %v", err)
 		return nil, nil, err
 	}
 	return server, endpoint, nil
diff --git a/tools/build/impl_test.go b/tools/build/impl_test.go
index 4ce3e9e..54bab19 100644
--- a/tools/build/impl_test.go
+++ b/tools/build/impl_test.go
@@ -49,7 +49,7 @@
 		t.Fatalf("Listen(%s) failed: %v", profiles.LocalListenSpec, err)
 	}
 	unpublished := ""
-	if err := server.Serve(unpublished, ipc.LeafDispatcher(build.NewServerBuilder(&mock{}), nil)); err != nil {
+	if err := server.Serve(unpublished, build.NewServerBuilder(&mock{}), nil); err != nil {
 		t.Fatalf("Serve(%v) failed: %v", unpublished, err)
 	}
 	return server, endpoint
diff --git a/tools/mounttable/impl.go b/tools/mounttable/impl.go
index 1c88cc7..b37d5f6 100644
--- a/tools/mounttable/impl.go
+++ b/tools/mounttable/impl.go
@@ -177,11 +177,14 @@
 	}
 	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
 	defer cancel()
-	c, err := bindMT(ctx, args[0])
+	call, err := rt.R().Client().StartCall(ctx, args[0], "ResolveStepX", []interface{}{}, options.NoResolve(true))
 	if err != nil {
-		return fmt.Errorf("bind error: %v", err)
+		return err
 	}
-	entry, err := c.ResolveStepX(ctx)
+	var entry types.MountEntry
+	if ierr := call.Finish(&entry, &err); ierr != nil {
+		return ierr
+	}
 	if err != nil {
 		return err
 	}
diff --git a/tools/mounttable/impl_test.go b/tools/mounttable/impl_test.go
index 9dfe601..fdfc5d1 100644
--- a/tools/mounttable/impl_test.go
+++ b/tools/mounttable/impl_test.go
@@ -73,8 +73,8 @@
 		t.Errorf("Listen failed: %v", err)
 		return nil, nil, err
 	}
-	if err := server.Serve("", dispatcher); err != nil {
-		t.Errorf("Serve failed: %v", err)
+	if err := server.ServeDispatcher("", dispatcher); err != nil {
+		t.Errorf("ServeDispatcher failed: %v", err)
 		return nil, nil, err
 	}
 	return server, endpoint, nil
@@ -126,7 +126,8 @@
 	stdout.Reset()
 
 	// Test the 'resolvestep' command.
-	if err := cmd.Execute([]string{"resolvestep", naming.JoinAddressName(endpoint.String(), "//name")}); err != nil {
+	vlog.Infof("resovestep %s", naming.JoinAddressName(endpoint.String(), "name"))
+	if err := cmd.Execute([]string{"resolvestep", naming.JoinAddressName(endpoint.String(), "name")}); err != nil {
 		t.Fatalf("%v", err)
 	}
 	if expected, got := `Servers: [{server1 123}] Suffix: "name" MT: false`, strings.TrimSpace(stdout.String()); got != expected {
diff --git a/tools/profile/impl_test.go b/tools/profile/impl_test.go
index 0bfd27e..dd8a329 100644
--- a/tools/profile/impl_test.go
+++ b/tools/profile/impl_test.go
@@ -85,7 +85,6 @@
 }
 
 func startServer(t *testing.T, r veyron2.Runtime) (ipc.Server, naming.Endpoint, error) {
-	dispatcher := NewDispatcher()
 	server, err := r.NewServer()
 	if err != nil {
 		t.Errorf("NewServer failed: %v", err)
@@ -96,8 +95,8 @@
 		t.Errorf("Listen failed: %v", err)
 		return nil, nil, err
 	}
-	if err := server.Serve("", dispatcher); err != nil {
-		t.Errorf("Serve failed: %v", err)
+	if err := server.ServeDispatcher("", NewDispatcher()); err != nil {
+		t.Errorf("ServeDispatcher failed: %v", err)
 		return nil, nil, err
 	}
 	return server, endpoint, nil
diff --git a/tools/vrpc/impl_test.go b/tools/vrpc/impl_test.go
index 83f0e58..bbff9a4 100644
--- a/tools/vrpc/impl_test.go
+++ b/tools/vrpc/impl_test.go
@@ -126,7 +126,7 @@
 }
 
 func startServer(t *testing.T, r veyron2.Runtime) (ipc.Server, naming.Endpoint, error) {
-	dispatcher := ipc.LeafDispatcher(test_base.NewServerTypeTester(&server{}), nil)
+	obj := test_base.NewServerTypeTester(&server{})
 	server, err := r.NewServer()
 	if err != nil {
 		t.Errorf("NewServer failed: %v", err)
@@ -138,7 +138,7 @@
 		t.Errorf("Listen failed: %v", err)
 		return nil, nil, err
 	}
-	if err := server.Serve("", dispatcher); err != nil {
+	if err := server.Serve("", obj, nil); err != nil {
 		t.Errorf("Serve failed: %v", err)
 		return nil, nil, err
 	}
diff --git a/tools/vrpc/test_base/test_base.vdl.go b/tools/vrpc/test_base/test_base.vdl.go
index 92bf836..ef4e9cf 100644
--- a/tools/vrpc/test_base/test_base.vdl.go
+++ b/tools/vrpc/test_base/test_base.vdl.go
@@ -236,9 +236,27 @@
 // It takes a regular server implementing the TypeTesterService
 // interface, and returns a new server stub.
 func NewServerTypeTester(server TypeTesterService) interface{} {
-	return &ServerStubTypeTester{
+	stub := &ServerStubTypeTester{
 		service: server,
 	}
+	var gs _gen_ipc.GlobState
+	var self interface{} = stub
+	// VAllGlobber is implemented by the server object, which is wrapped in
+	// a VDL generated server stub.
+	if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VAllGlobber is implemented by the server object without using a VDL
+	// generated stub.
+	if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+		gs.VAllGlobber = x
+	}
+	// VChildrenGlobber is implemented in the server object.
+	if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+		gs.VChildrenGlobber = x
+	}
+	stub.gs = &gs
+	return stub
 }
 
 // clientStubTypeTester implements TypeTester.
@@ -510,6 +528,7 @@
 // the requirements of veyron2/ipc.ReflectInvoker.
 type ServerStubTypeTester struct {
 	service TypeTesterService
+	gs      *_gen_ipc.GlobState
 }
 
 func (__gen_s *ServerStubTypeTester) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -764,6 +783,10 @@
 	return
 }
 
+func (__gen_s *ServerStubTypeTester) VGlob() *_gen_ipc.GlobState {
+	return __gen_s.gs
+}
+
 func (__gen_s *ServerStubTypeTester) EchoBool(call _gen_ipc.ServerCall, I1 bool) (reply bool, err error) {
 	reply, err = __gen_s.service.EchoBool(call, I1)
 	return