Merge ""veyron/services/identity: TBR: Enable revocation now that third party caveat issue is resolved."
diff --git a/lib/exec/exec_test.go b/lib/exec/exec_test.go
index f34b280..a013d55 100644
--- a/lib/exec/exec_test.go
+++ b/lib/exec/exec_test.go
@@ -410,6 +410,29 @@
 	clean(t, ph)
 }
 
+func TestWaitAndCleanRace(t *testing.T) {
+	name := "TestWaitAndCleanRace"
+	cmd := helperCommand("testReadySlow")
+	tk := timekeeper.NewManualTime()
+	ph := vexec.NewParentHandle(cmd, vexec.TimeKeeperOpt{tk})
+	err := ph.Start()
+	if err != nil {
+		t.Fatalf("%s: start: %v", name, err)
+	}
+	go func() {
+		// Wait for the ph.Wait below to block, then advance the time
+		// s.t. the Wait times out.
+		<-tk.Requests()
+		tk.AdvanceTime(2 * time.Second)
+	}()
+	if got, want := ph.Wait(time.Second), vexec.ErrTimeout; got == nil || got.Error() != want.Error() {
+		t.Fatalf("Wait returned %v, wanted %v instead", got, want)
+	}
+	if got, want := ph.Clean(), "signal: killed"; got == nil || got.Error() != want {
+		t.Fatalf("Wait returned %v, wanted %v instead", got, want)
+	}
+}
+
 func verifyNoExecVariable() {
 	version := os.Getenv(vexec.VersionVariable)
 	if len(version) != 0 {
diff --git a/lib/exec/parent.go b/lib/exec/parent.go
index 8520b4a..9d98c15 100644
--- a/lib/exec/parent.go
+++ b/lib/exec/parent.go
@@ -8,6 +8,7 @@
 	"os"
 	"os/exec"
 	"strings"
+	"sync"
 	"syscall"
 	"time"
 
@@ -30,6 +31,9 @@
 	statusRead  *os.File
 	statusWrite *os.File
 	tk          timekeeper.TimeKeeper
+	waitDone    bool
+	waitErr     error
+	waitLock    sync.Mutex
 }
 
 // ParentHandleOpt is an option for NewParentHandle.
@@ -202,13 +206,28 @@
 	panic("unreachable")
 }
 
+// wait performs the Wait on the underlying command under lock, and only once
+// (subsequent wait calls block until the Wait is finished).  It's ok to call
+// wait multiple times, and in parallel.  The error from the initial Wait is
+// cached and returned for all subsequent calls.
+func (p *ParentHandle) wait() error {
+	p.waitLock.Lock()
+	defer p.waitLock.Unlock()
+	if p.waitDone {
+		return p.waitErr
+	}
+	p.waitErr = p.c.Wait()
+	p.waitDone = true
+	return p.waitErr
+}
+
 // Wait will wait for the child process to terminate of its own accord.
 // It returns nil if the process exited cleanly with an exit status of 0,
 // any other exit code or error will result in an appropriate error return
 func (p *ParentHandle) Wait(timeout time.Duration) error {
 	c := make(chan error, 1)
 	go func() {
-		c <- p.c.Wait()
+		c <- p.wait()
 		close(c)
 	}()
 	// If timeout is zero time.After will panic; we handle zero specially
@@ -257,7 +276,7 @@
 	if err := p.Kill(); err != nil {
 		return err
 	}
-	return p.c.Wait()
+	return p.wait()
 }
 
 func encodeString(w io.Writer, data string) error {
diff --git a/lib/expect/expect.go b/lib/expect/expect.go
index b9b8311..afed004 100644
--- a/lib/expect/expect.go
+++ b/lib/expect/expect.go
@@ -242,7 +242,7 @@
 		return [][]string{}
 	}
 	l, m, err := s.expectRE(pattern, n)
-	s.log(err, "ExpectVar: %s", l)
+	s.log(err, "ExpectRE: %s", l)
 	if err != nil {
 		s.error(err)
 		return [][]string{}
diff --git a/lib/filelocker/locker_test.go b/lib/filelocker/locker_test.go
index f3ce658..fc23e17 100644
--- a/lib/filelocker/locker_test.go
+++ b/lib/filelocker/locker_test.go
@@ -63,7 +63,10 @@
 	filepath := newFile()
 	defer os.Remove(filepath)
 
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 	h, err := sh.Start("testLockChild", nil, filepath)
 	if err != nil {
@@ -133,7 +136,10 @@
 	filepath := newFile()
 	defer os.Remove(filepath)
 
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 	h, err := sh.Start("testLockChild", nil, filepath)
 	if err != nil {
diff --git a/lib/modules/core/core_test.go b/lib/modules/core/core_test.go
index 5f72ee9..86bbb0e 100644
--- a/lib/modules/core/core_test.go
+++ b/lib/modules/core/core_test.go
@@ -23,8 +23,8 @@
 )
 
 func TestCommands(t *testing.T) {
-	sh := modules.NewShell()
-	defer sh.Cleanup(nil, os.Stderr)
+	sh, fn := newShell(t)
+	defer fn()
 	for _, c := range []string{core.RootMTCommand, core.MTCommand} {
 		if len(sh.Help(c)) == 0 {
 			t.Fatalf("missing command %q", c)
@@ -37,8 +37,11 @@
 	rt.Init()
 }
 
-func newShell() (*modules.Shell, func()) {
-	sh := modules.NewShell()
+func newShell(t *testing.T) (*modules.Shell, func()) {
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	return sh, func() {
 		if testing.Verbose() {
 			vlog.Infof("------ cleanup ------")
@@ -55,7 +58,7 @@
 }
 
 func TestRoot(t *testing.T) {
-	sh, fn := newShell()
+	sh, fn := newShell(t)
 	defer fn()
 	root, err := sh.Start(core.RootMTCommand, nil, testArgs()...)
 	if err != nil {
@@ -128,7 +131,7 @@
 }
 
 func TestMountTableAndGlob(t *testing.T) {
-	sh, fn := newShell()
+	sh, fn := newShell(t)
 	defer fn()
 
 	mountPoints := []string{"a", "b", "c", "d", "e"}
@@ -201,7 +204,7 @@
 }
 
 func TestEcho(t *testing.T) {
-	sh, fn := newShell()
+	sh, fn := newShell(t)
 	defer fn()
 
 	srv, err := sh.Start(core.EchoServerCommand, nil, testArgs("test", "")...)
@@ -223,7 +226,7 @@
 }
 
 func TestResolve(t *testing.T) {
-	sh, fn := newShell()
+	sh, fn := newShell(t)
 	defer fn()
 
 	mountPoints := []string{"a", "b"}
diff --git a/lib/modules/core/mounttable.go b/lib/modules/core/mounttable.go
index 51373a6..bee0e5d 100644
--- a/lib/modules/core/mounttable.go
+++ b/lib/modules/core/mounttable.go
@@ -120,7 +120,7 @@
 	return nil
 }
 
-type resolver func(ctx context.T, name string) (names []string, err error)
+type resolver func(ctx context.T, name string, opts ...naming.ResolveOpt) (names []string, err error)
 
 func resolve(fn resolver, stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
 	if err := checkArgs(args[1:], 1, "<name>"); err != nil {
@@ -148,9 +148,5 @@
 }
 
 func setNamespaceRoots(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
-	ns := rt.R().Namespace()
-	if err := checkArgs(args, -1, "<name>..."); err != nil {
-		return err
-	}
-	return ns.SetRoots(args[1:]...)
+	return rt.R().Namespace().SetRoots(args[1:]...)
 }
diff --git a/lib/modules/core/proxy.go b/lib/modules/core/proxy.go
index 3f83ece..4cba574 100644
--- a/lib/modules/core/proxy.go
+++ b/lib/modules/core/proxy.go
@@ -3,6 +3,7 @@
 import (
 	"fmt"
 	"io"
+	"strings"
 	"time"
 
 	"veyron.io/veyron/veyron2/naming"
@@ -48,6 +49,12 @@
 	defer pub.WaitForStop()
 	defer pub.Stop()
 	pub.AddServer(pname, false)
+	// If the protocol is tcp we need to also publish the websocket endpoint.
+	// TODO(bjornick): Remove this hack before we launch.
+	if strings.HasPrefix(proxy.Endpoint().Addr().Network(), "tcp") {
+		wsEP := strings.Replace(pname, "@"+proxy.Endpoint().Addr().Network()+"@", "@ws@", 1)
+		pub.AddServer(wsEP, false)
+	}
 	for _, name := range args {
 		pub.AddName(name)
 	}
diff --git a/lib/modules/exec.go b/lib/modules/exec.go
index d656d0a..74acf2f 100644
--- a/lib/modules/exec.go
+++ b/lib/modules/exec.go
@@ -24,6 +24,7 @@
 	stderr     *os.File
 	stdout     io.ReadCloser
 	stdin      io.WriteCloser
+	procErrCh  chan error
 }
 
 func testFlags() []string {
@@ -44,13 +45,15 @@
 		// use supplied command value for subprocesses
 		fl = append(fl, "--test.timeout="+timeout.Value.String())
 	} else {
-		// translate default value into 1m for subproccesses
-		fl = append(fl, "--test.timeout=1m")
+		// translate default value into 3m for subproccesses.  The
+		// default of 10m is too long to wait in order to find out that
+		// our subprocess is wedged.
+		fl = append(fl, "--test.timeout=3m")
 	}
 	return fl
 }
 
-// IsTestHelperProces returns true if it is called in via
+// IsTestHelperProcess returns true if it is called in via
 // -run=TestHelperProcess which normally only ever happens for subprocesses
 // run from tests.
 func IsTestHelperProcess() bool {
@@ -62,7 +65,7 @@
 }
 
 func newExecHandle(name string) command {
-	return &execHandle{name: name, entryPoint: shellEntryPoint + "=" + name}
+	return &execHandle{name: name, entryPoint: shellEntryPoint + "=" + name, procErrCh: make(chan error, 1)}
 }
 
 func (eh *execHandle) Stdout() io.Reader {
@@ -112,15 +115,19 @@
 	newargs, newenv := eh.envelope(sh, env, args[1:]...)
 	cmd := exec.Command(os.Args[0], newargs[1:]...)
 	cmd.Env = newenv
-	stderr, err := newLogfile(strings.TrimLeft(eh.name, "-\n\t "))
+	stderr, err := newLogfile("stderr", eh.name)
 	if err != nil {
 		return nil, err
 	}
 	cmd.Stderr = stderr
-	stdout, err := cmd.StdoutPipe()
-	if err != nil {
-		return nil, err
-	}
+	// We use a custom queue-based Writer implementation for stdout to
+	// decouple the consumers of eh.stdout from the file where the child
+	// sends its output.  This avoids data races between closing the file
+	// and reading from it (since cmd.Wait will wait for the all readers to
+	// be done before closing it).  It also enables Shutdown to drain stdout
+	// while respecting the timeout.
+	stdout := newRW()
+	cmd.Stdout = stdout
 	stdin, err := cmd.StdinPipe()
 	if err != nil {
 		return nil, err
@@ -139,6 +146,15 @@
 	}
 	vlog.VI(1).Infof("Started: %q, pid %d", eh.name, cmd.Process.Pid)
 	err = handle.WaitForReady(sh.startTimeout)
+	go func() {
+		eh.procErrCh <- eh.handle.Wait(0)
+		// It's now safe to close eh.stdout, since Wait only returns
+		// once all writes from the pipe to the stdout Writer have
+		// completed.  Closing eh.stdout lets consumers of stdout wrap
+		// up (they'll receive EOF).
+		eh.stdout.Close()
+	}()
+
 	return eh, err
 }
 
@@ -150,39 +166,36 @@
 	eh.mu.Lock()
 	defer eh.mu.Unlock()
 	vlog.VI(1).Infof("Shutdown: %q", eh.name)
+	defer vlog.VI(1).Infof("Shutdown: %q [DONE]", eh.name)
 	eh.stdin.Close()
-	logFile := eh.stderr.Name()
 	defer eh.sh.Forget(eh)
 
-	defer func() {
-		os.Remove(logFile)
-	}()
-
-	// TODO(cnicolaou): make this configurable
-	timeout := 10 * time.Second
-	if stdout == nil && stderr == nil {
-		return eh.handle.Wait(timeout)
-	}
-
+	waitStdout := make(chan struct{})
 	if stdout != nil {
-		// Read from stdin before waiting for the child process to ensure
-		// that we get to read all of its output.
-		readTo(eh.stdout, stdout)
+		// Drain stdout.
+		go func() {
+			io.Copy(stdout, eh.stdout)
+			close(waitStdout)
+		}()
+	} else {
+		close(waitStdout)
 	}
 
-	procErr := eh.handle.Wait(timeout)
-
-	// Stderr is buffered to a file, so we can safely read it after we
-	// wait for the process.
-	eh.stderr.Close()
-	if stderr != nil {
-		stderrFile, err := os.Open(logFile)
-		if err != nil {
-			vlog.VI(1).Infof("failed to open %q: %s\n", logFile, err)
-			return procErr
-		}
-		readTo(stderrFile, stderr)
-		stderrFile.Close()
+	var procErr error
+	select {
+	case procErr = <-eh.procErrCh:
+		// The child has exited already.
+	case <-time.After(eh.sh.waitTimeout):
+		// Time out waiting for child to exit.
+		procErr = vexec.ErrTimeout
+		// Force close stdout to unblock any readers of stdout
+		// (including the drain loop started above).
+		eh.stdout.Close()
 	}
+	<-waitStdout
+
+	// Transcribe stderr.
+	outputFromFile(eh.stderr, stderr)
+
 	return procErr
 }
diff --git a/lib/modules/func.go b/lib/modules/func.go
index 54ce341..8fd0523 100644
--- a/lib/modules/func.go
+++ b/lib/modules/func.go
@@ -65,7 +65,7 @@
 			return nil, err
 		}
 	}
-	stderr, err := newLogfile(args[0])
+	stderr, err := newLogfile("stderr", args[0])
 	if err != nil {
 		return nil, err
 	}
@@ -111,7 +111,9 @@
 	fh.mu.Unlock()
 
 	// Read stdout until EOF to ensure that we read all of it.
-	readTo(stdout, stdout_w)
+	if stdout_w != nil {
+		io.Copy(stdout_w, stdout)
+	}
 	fh.wg.Wait()
 
 	fh.mu.Lock()
@@ -120,12 +122,13 @@
 
 	// Safe to close stderr now.
 	stderr.Close()
-	stderr, err := os.Open(stderr.Name())
-	if err == nil {
-		readTo(stderr, stderr_w)
-		stderr.Close()
-	} else {
-		fmt.Fprintf(os.Stderr, "failed to open %q: %s\n", stderr.Name(), err)
+	if stderr_w != nil {
+		if stderr, err := os.Open(stderr.Name()); err == nil {
+			io.Copy(stderr_w, stderr)
+			stderr.Close()
+		} else {
+			fmt.Fprintf(os.Stderr, "failed to open %q: %s\n", stderr.Name(), err)
+		}
 	}
 
 	fh.mu.Lock()
diff --git a/lib/modules/modules_internal_test.go b/lib/modules/modules_internal_test.go
index d0112e6..b8229e3 100644
--- a/lib/modules/modules_internal_test.go
+++ b/lib/modules/modules_internal_test.go
@@ -13,7 +13,7 @@
 		return fmt.Errorf("no args")
 	}
 	for _, a := range args {
-		fmt.Println(a)
+		fmt.Fprintln(stdout, a)
 	}
 	return nil
 }
@@ -26,7 +26,10 @@
 }
 
 func TestState(t *testing.T) {
-	sh := NewShell()
+	sh, err := NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	RegisterFunction("echoff", "[args]*", Echo)
 	assertNumHandles(t, sh, 0)
 
diff --git a/lib/modules/modules_test.go b/lib/modules/modules_test.go
index 0852a00..cee9708 100644
--- a/lib/modules/modules_test.go
+++ b/lib/modules/modules_test.go
@@ -3,31 +3,46 @@
 import (
 	"bufio"
 	"bytes"
+	"errors"
 	"fmt"
 	"io"
 	"os"
 	"reflect"
 	"sort"
 	"strings"
+	"syscall"
 	"testing"
 	"time"
 
 	"veyron.io/veyron/veyron/lib/exec"
+	"veyron.io/veyron/veyron/lib/flags/consts"
 	"veyron.io/veyron/veyron/lib/modules"
 	"veyron.io/veyron/veyron/lib/testutil"
+	tsecurity "veyron.io/veyron/veyron/lib/testutil/security"
+	_ "veyron.io/veyron/veyron/profiles"
+	vsecurity "veyron.io/veyron/veyron/security"
+
+	"veyron.io/veyron/veyron2/security"
 )
 
+const credentialsEnvPrefix = "\"" + consts.VeyronCredentials + "="
+
 func init() {
 	testutil.Init()
 	modules.RegisterChild("envtest", "envtest: <variables to print>...", PrintFromEnv)
 	modules.RegisterChild("printenv", "printenv", PrintEnv)
 	modules.RegisterChild("echos", "[args]*", Echo)
 	modules.RegisterChild("errortestChild", "", ErrorMain)
+	modules.RegisterChild("ignores_stdin", "", ignoresStdin)
 
 	modules.RegisterFunction("envtestf", "envtest: <variables to print>...", PrintFromEnv)
 	modules.RegisterFunction("echof", "[args]*", Echo)
 	modules.RegisterFunction("errortestFunc", "", ErrorMain)
+}
 
+func ignoresStdin(io.Reader, io.Writer, io.Writer, map[string]string, ...string) error {
+	<-time.After(time.Minute)
+	return nil
 }
 
 func Echo(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
@@ -118,7 +133,10 @@
 }
 
 func TestChild(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(nil, nil)
 	key, val := "simpleVar", "foo & bar"
 	sh.SetVar(key, val)
@@ -126,19 +144,25 @@
 }
 
 func TestChildNoRegistration(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 	key, val := "simpleVar", "foo & bar"
 	sh.SetVar(key, val)
 	testCommand(t, sh, "envtest", key, val)
-	_, err := sh.Start("non-existent-command", nil, "random", "args")
+	_, err = sh.Start("non-existent-command", nil, "random", "args")
 	if err == nil {
 		t.Fatalf("expected error")
 	}
 }
 
 func TestFunction(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(nil, nil)
 	key, val := "simpleVar", "foo & bar & baz"
 	sh.SetVar(key, val)
@@ -146,7 +170,10 @@
 }
 
 func TestErrorChild(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(nil, nil)
 	h, err := sh.Start("errortestChild", nil)
 	if err != nil {
@@ -183,15 +210,86 @@
 }
 
 func TestShutdownSubprocess(t *testing.T) {
-	testShutdown(t, modules.NewShell(), "echos", false)
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
+	testShutdown(t, sh, "echos", false)
+}
+
+// TestShutdownSubprocessIgnoresStdin verifies that Shutdown doesn't wait
+// forever if a child does not die upon closing stdin; but instead times out and
+// returns an appropriate error.
+func TestShutdownSubprocessIgnoresStdin(t *testing.T) {
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
+	sh.SetWaitTimeout(time.Second)
+	h, err := sh.Start("ignores_stdin", nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
+	var stdoutBuf, stderrBuf bytes.Buffer
+	if err := sh.Cleanup(&stdoutBuf, &stderrBuf); err == nil || err.Error() != exec.ErrTimeout.Error() {
+		t.Errorf("unexpected error in Cleanup: got %v, want %v", err, exec.ErrTimeout)
+	}
+	if err := syscall.Kill(h.Pid(), syscall.SIGINT); err != nil {
+		t.Errorf("Kill failed: %v", err)
+	}
+}
+
+// TestStdoutRace exemplifies a potential race between reading from child's
+// stdout and closing stdout in Wait (called by Shutdown).
+//
+// NOTE: triggering the actual --race failure is hard, even if the
+// implementation inappropriately sets stdout to the file that is to be closed
+// in Wait.
+func TestStdoutRace(t *testing.T) {
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
+	sh.SetWaitTimeout(time.Second)
+	h, err := sh.Start("ignores_stdin", nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
+	ch := make(chan error, 1)
+	go func() {
+		buf := make([]byte, 5)
+		// This will block since the child is not writing anything on
+		// stdout.
+		_, err := h.Stdout().Read(buf)
+		ch <- err
+	}()
+	// Give the goroutine above a chance to run, so that we're blocked on
+	// stdout.Read.
+	<-time.After(time.Second)
+	// Cleanup should close stdout, and unblock the goroutine.
+	sh.Cleanup(nil, nil)
+	if got, want := <-ch, io.EOF; got != want {
+		t.Errorf("Expected %v, got %v instead", want, got)
+	}
+
+	if err := syscall.Kill(h.Pid(), syscall.SIGINT); err != nil {
+		t.Errorf("Kill failed: %v", err)
+	}
 }
 
 func TestShutdownFunction(t *testing.T) {
-	testShutdown(t, modules.NewShell(), "echof", true)
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
+	testShutdown(t, sh, "echof", true)
 }
 
 func TestErrorFunc(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(nil, nil)
 	h, err := sh.Start("errortestFunc", nil)
 	if err != nil {
@@ -212,7 +310,10 @@
 }
 
 func TestEnvelope(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(nil, nil)
 	sh.SetVar("a", "1")
 	sh.SetVar("b", "2")
@@ -244,29 +345,154 @@
 		}
 	}
 
+	foundVeyronCredentials := false
 	for _, want := range shEnv {
+		if strings.HasPrefix(want, credentialsEnvPrefix) {
+			foundVeyronCredentials = true
+			continue
+		}
 		if !find(want, childEnv) {
 			t.Errorf("failed to find %s in %#v", want, childEnv)
 		}
 	}
+	if !foundVeyronCredentials {
+		t.Errorf("%v environment variable not set in command envelope", consts.VeyronCredentials)
+	}
+
+	foundVeyronCredentials = false
 	for _, want := range childEnv {
 		if want == "\""+exec.VersionVariable+"=\"" {
 			continue
 		}
+		if strings.HasPrefix(want, credentialsEnvPrefix) {
+			foundVeyronCredentials = true
+			continue
+		}
 		if !find(want, shEnv) {
 			t.Errorf("failed to find %s in %#v", want, shEnv)
 		}
 	}
+	if !foundVeyronCredentials {
+		t.Errorf("%v environment variable not set for command", consts.VeyronCredentials)
+	}
+}
+
+func TestEnvCredentials(t *testing.T) {
+	startChildAndGetCredentials := func(sh *modules.Shell, env []string) string {
+		h, err := sh.Start("printenv", env)
+		if err != nil {
+			t.Fatalf("unexpected error: %s", err)
+		}
+		defer h.Shutdown(os.Stderr, os.Stderr)
+		scanner := bufio.NewScanner(h.Stdout())
+		for scanner.Scan() {
+			o := scanner.Text()
+			if strings.HasPrefix(o, credentialsEnvPrefix) {
+				return strings.TrimSuffix(strings.TrimPrefix(o, credentialsEnvPrefix), "\"")
+			}
+		}
+		return ""
+	}
+	validateCredentials := func(dir string, wantBlessing string) error {
+		if len(dir) == 0 {
+			return errors.New("credentials directory not found")
+		}
+		p, err := vsecurity.LoadPersistentPrincipal(dir, nil)
+		if err != nil {
+			return err
+		}
+		def := p.BlessingStore().Default()
+		if blessingsSharedWithAll := p.BlessingStore().ForPeer("random_peer"); !reflect.DeepEqual(blessingsSharedWithAll, def) {
+			return fmt.Errorf("Blessing shared with all peers: %v is different from default Blessings: %v", blessingsSharedWithAll, def)
+		}
+		if got := def.ForContext(security.NewContext(&security.ContextParams{LocalPrincipal: p})); len(got) != 1 || got[0] != wantBlessing {
+			return fmt.Errorf("got blessings: %v, want exactly one blessing: %v", got, wantBlessing)
+		}
+		return nil
+	}
+
+	// Test child credentials when runtime is not initialized and VeyronCredentials
+	// is not set.
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
+	defer sh.Cleanup(nil, nil)
+	if err := validateCredentials(startChildAndGetCredentials(sh, nil), "test-shell/child"); err != nil {
+		t.Fatal(err)
+	}
+
+	// Test that no two children have the same credentials directory.
+	if cred1, cred2 := startChildAndGetCredentials(sh, nil), startChildAndGetCredentials(sh, nil); cred1 == cred2 {
+		t.Fatalf("The same credentials directory %v was set for two children", cred1)
+	}
+
+	// Test child credentials when VeyronCredentials are set.
+	root := tsecurity.NewPrincipal("root")
+	old := os.Getenv(consts.VeyronCredentials)
+	defer os.Setenv(consts.VeyronCredentials, old)
+	dir := tsecurity.NewVeyronCredentials(root, "os")
+	defer os.RemoveAll(dir)
+	if err := os.Setenv(consts.VeyronCredentials, dir); err != nil {
+		t.Fatal(err)
+	}
+	sh, err = modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
+	if err := validateCredentials(startChildAndGetCredentials(sh, nil), "root/os/child"); err != nil {
+		t.Fatal(err)
+	}
+	sh.Cleanup(nil, nil)
+
+	// Test that os VeyronCredentials are not deleted by the Cleanup.
+	if finfo, err := os.Stat(dir); err != nil || !finfo.IsDir() {
+		t.Fatalf("%q is not a directory", dir)
+	}
+
+	// Test that VeyronCredentials specified on the shell override the OS ones.
+	dir = tsecurity.NewVeyronCredentials(root, "shell")
+	defer os.RemoveAll(dir)
+	sh, err = modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
+	sh.SetVar(consts.VeyronCredentials, dir)
+	if err := validateCredentials(startChildAndGetCredentials(sh, nil), "root/shell/child"); err != nil {
+		t.Fatal(err)
+	}
+	sh.ClearVar(consts.VeyronCredentials)
+	if credentials := startChildAndGetCredentials(sh, nil); len(credentials) != 0 {
+		t.Fatalf("found credentials %v set for child even when shell credentials were cleared", credentials)
+	}
+	anotherDir := tsecurity.NewVeyronCredentials(root, "anotherShell")
+	defer os.RemoveAll(anotherDir)
+	sh.SetVar(consts.VeyronCredentials, anotherDir)
+	if err := validateCredentials(startChildAndGetCredentials(sh, nil), "root/anotherShell/child"); err != nil {
+		t.Fatal(err)
+	}
+
+	// Test that VeyronCredentials specified as a parameter overrides the OS and
+	// shell ones.
+	dir = tsecurity.NewVeyronCredentials(root, "param")
+	defer os.RemoveAll(dir)
+	env := []string{consts.VeyronCredentials + "=" + dir}
+	if err := validateCredentials(startChildAndGetCredentials(sh, env), "root/param"); err != nil {
+		t.Fatal(err)
+	}
+
 }
 
 func TestEnvMerge(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(nil, nil)
 	sh.SetVar("a", "1")
 	os.Setenv("a", "wrong, should be 1")
 	sh.SetVar("b", "2 also wrong")
 	os.Setenv("b", "wrong, should be 2")
-
 	h, err := sh.Start("printenv", []string{"b=2"})
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
diff --git a/lib/modules/only_for_test.go b/lib/modules/only_for_test.go
new file mode 100644
index 0000000..8f3143a
--- /dev/null
+++ b/lib/modules/only_for_test.go
@@ -0,0 +1,8 @@
+package modules
+
+import "io"
+
+// NewRW exposes newRW for unit tests.
+func NewRW() io.ReadWriteCloser {
+	return newRW()
+}
diff --git a/lib/modules/queue_rw.go b/lib/modules/queue_rw.go
new file mode 100644
index 0000000..b4c83e9
--- /dev/null
+++ b/lib/modules/queue_rw.go
@@ -0,0 +1,58 @@
+package modules
+
+import (
+	"io"
+	"sync"
+
+	// TODO(caprita): Move upcqueue into veyron/lib.
+	"veyron.io/veyron/veyron/runtimes/google/lib/upcqueue"
+)
+
+// queueRW implements a ReadWriteCloser backed by an unbounded in-memory
+// producer-consumer queue.
+type queueRW struct {
+	sync.Mutex
+	q        *upcqueue.T
+	buf      []byte
+	buffered int
+	cancel   chan struct{}
+}
+
+func newRW() io.ReadWriteCloser {
+	return &queueRW{q: upcqueue.New(), cancel: make(chan struct{})}
+}
+
+func (q *queueRW) Close() error {
+	// We use an empty message to signal EOF to the reader.
+	_, err := q.Write([]byte{})
+	return err
+}
+
+func (q *queueRW) Read(p []byte) (n int, err error) {
+	q.Lock()
+	defer q.Unlock()
+	for q.buffered == 0 {
+		elem, err := q.q.Get(q.cancel)
+		if err != nil {
+			return 0, io.EOF
+		}
+		s := elem.(string)
+		b := []byte(s)
+		if len(b) == 0 {
+			close(q.cancel)
+			return 0, io.EOF
+		}
+		q.buf, q.buffered = b, len(b)
+	}
+	copied := copy(p, q.buf[:q.buffered])
+	q.buf = q.buf[copied:]
+	q.buffered -= copied
+	return copied, nil
+}
+
+func (q *queueRW) Write(p []byte) (n int, err error) {
+	if err := q.q.Put(string(p)); err != nil {
+		return 0, err
+	}
+	return len(p), nil
+}
diff --git a/lib/modules/queue_rw_test.go b/lib/modules/queue_rw_test.go
new file mode 100644
index 0000000..735c301
--- /dev/null
+++ b/lib/modules/queue_rw_test.go
@@ -0,0 +1,60 @@
+package modules_test
+
+import (
+	"bytes"
+	"io"
+	"testing"
+
+	"veyron.io/veyron/veyron/lib/modules"
+	"veyron.io/veyron/veyron/lib/testutil"
+)
+
+func init() {
+	if !modules.IsModulesProcess() {
+		testutil.Init()
+	}
+}
+func TestQueueRW(t *testing.T) {
+	q := modules.NewRW()
+	size := testutil.Rand.Intn(1000)
+	data := testutil.RandomBytes(size)
+	begin := 0
+	for {
+		end := begin + testutil.Rand.Intn(100) + 1
+		if end > len(data) {
+			end = len(data)
+		}
+		n, err := q.Write(data[begin:end])
+		if err != nil {
+			t.Fatalf("Write failed: %v", err)
+		}
+		begin = begin + n
+		if begin == len(data) {
+			break
+		}
+	}
+	// This marks EOF.
+	if _, err := q.Write([]byte{}); err != nil {
+		t.Fatalf("err %v", err)
+	}
+	readData := make([]byte, 0, size)
+	for {
+		buf := make([]byte, testutil.Rand.Intn(100)+1)
+		n, err := q.Read(buf)
+		if n > 0 {
+			readData = append(readData, buf[:n]...)
+		}
+		if err != nil {
+			if err == io.EOF {
+				break
+			}
+			t.Fatalf("Read failed: %v", err)
+		}
+	}
+	if size != len(readData) {
+		t.Fatalf("Mismatching data size: %d != %d", size, len(readData))
+	}
+	if !bytes.Equal(data, readData) {
+		t.Fatalf("Diffing data:\n%v\n%v", data, readData)
+	}
+}
diff --git a/lib/modules/shell.go b/lib/modules/shell.go
index 9e4c3b9..8d4324b 100644
--- a/lib/modules/shell.go
+++ b/lib/modules/shell.go
@@ -29,74 +29,181 @@
 // In particular stdin, stdout and stderr are provided as parameters, as is
 // a map representation of the shell's environment.
 //
-// If a Shell is created within a unit test then it will automatically
-// generate a security ID, write it to a file and set the appropriate
-// environment variable to refer to it.
+// Every Shell created by NewShell is initialized with its VeyronCredentials
+// environment variable set. The variable is set to the os's VeyronCredentials
+// if that is set, otherwise to a freshly created credentials directory. The
+// shell's VeyronCredentials can be set and cleared using the SetVar and
+// ClearVar methods respectively.
+//
+// By default, the VeyronCredentials for each command Start-ed by the shell are
+// set to a freshly created credentials directory that is blessed by the shell's
+// credentials (i.e., if shell's credentials have not been cleared). Thus, each
+// child of the shell gets its own credentials directory with a blessing from the
+// shell of the form
+//   <shell's default blessing>/child
+// These default credentials provided by the shell to each command can be
+// overridden by specifying VeyronCredentials in the environment provided as a
+// parameter to the Start method.
 package modules
 
 import (
-	"flag"
 	"fmt"
 	"io"
 	"io/ioutil"
+	"math/rand"
 	"os"
 	"sync"
 	"time"
 
+	"veyron.io/veyron/veyron2/security"
+
 	"veyron.io/veyron/veyron/lib/exec"
 	"veyron.io/veyron/veyron/lib/flags/consts"
+	vsecurity "veyron.io/veyron/veyron/security"
+)
+
+const (
+	shellBlessingExtension = "test-shell"
+	childBlessingExtension = "child"
 )
 
 // Shell represents the context within which commands are run.
 type Shell struct {
-	mu           sync.Mutex
-	env          map[string]string
-	handles      map[Handle]struct{}
-	credDir      string
-	startTimeout time.Duration
-	config       exec.Config
+	mu      sync.Mutex
+	env     map[string]string
+	handles map[Handle]struct{}
+	// tmpCredDirs are the temporary directories created by this
+	// shell. These must be removed when the shell is cleaned up.
+	tempCredDirs              []string
+	startTimeout, waitTimeout time.Duration
+	config                    exec.Config
+	principal                 security.Principal
+	blessing                  security.Blessings
 }
 
-// NewShell creates a new instance of Shell. If this new instance is is a test
-// and no credentials have been configured in the environment via
-// consts.VeyronCredentials then CreateAndUseNewCredentials will be used to
-// configure a new ID for the shell and its children.
-func NewShell() *Shell {
+// NewShell creates a new instance of Shell. It will also add a blessing
+// to the supplied principal and ensure that any child processes are
+// created with principals that are in turn blessed with it. A typical
+// use case is to pass in the runtime's principal and hence allow the
+// process hosting the shell to interact with its children and vice
+// versa. If a nil principal is passed in then NewShell will create a new
+// principal that shares a blessing with all of its children, in this mode,
+// any child processes can interact with each other but not with the parent.
+func NewShell(p security.Principal) (*Shell, error) {
 	sh := &Shell{
 		env:          make(map[string]string),
 		handles:      make(map[Handle]struct{}),
 		startTimeout: time.Minute,
+		waitTimeout:  10 * time.Second,
 		config:       exec.NewConfig(),
+		principal:    p,
 	}
-	if flag.Lookup("test.run") != nil && os.Getenv(consts.VeyronCredentials) == "" {
-		if err := sh.CreateAndUseNewCredentials(); err != nil {
-			// TODO(cnicolaou): return an error rather than panic.
-			panic(err)
+	if p == nil {
+		if err := sh.initShellCredentials(); err != nil {
+			return nil, err
 		}
+		return sh, nil
 	}
-	return sh
+	gen := rand.New(rand.NewSource(time.Now().UnixNano()))
+	// Use a unique blessing tree per shell.
+	blessingName := fmt.Sprintf("%s-%d", shellBlessingExtension, gen.Int63())
+	blessing, err := p.BlessSelf(blessingName)
+	if err != nil {
+		return nil, err
+	}
+	sh.blessing = blessing
+	if _, err := p.BlessingStore().Set(blessing, security.BlessingPattern(blessingName+"/"+childBlessingExtension+"/...")); err != nil {
+		return nil, err
+	}
+	if err := p.AddToRoots(blessing); err != nil {
+		return nil, err
+	}
+	// Our blessing store now contains a blessing with our unique prefix
+	// and the principal has that blessing's root added to its trusted
+	// list so that it will accept blessings derived from it.
+	return sh, nil
 }
 
-// CreateAndUseNewCredentials setups a new credentials directory and then
-// configures the shell and all of its children to use to it.
-//
-// TODO(cnicolaou): this should use the principal already setup
-// with the runtime if the runtime has been initialized, if not,
-// it should create a new principal. As of now, this approach only works
-// for child processes that talk to each other, but not to the parent
-// process that started them since it's running with a different set of
-// credentials setup elsewhere. When this change is made it should
-// be possible to remove creating credentials in many unit tests.
-func (sh *Shell) CreateAndUseNewCredentials() error {
-	dir, err := ioutil.TempDir("", "veyron_credentials")
+func (sh *Shell) initShellCredentials() error {
+	sh.mu.Lock()
+	defer sh.mu.Unlock()
+	if dir := os.Getenv(consts.VeyronCredentials); len(dir) != 0 {
+		sh.env[consts.VeyronCredentials] = dir
+		return nil
+	}
+
+	dir, err := ioutil.TempDir("", "shell_credentials")
 	if err != nil {
 		return err
 	}
-	sh.credDir = dir
-	sh.SetVar(consts.VeyronCredentials, sh.credDir)
+	sh.env[consts.VeyronCredentials] = dir
+	sh.tempCredDirs = append(sh.tempCredDirs, dir)
 	return nil
 }
 
+func (sh *Shell) getChildCredentials(shellCredDir string) (string, error) {
+	root := sh.principal
+	rootBlessing := sh.blessing
+	if root == nil {
+		r, err := principalFromDir(shellCredDir)
+		if err != nil {
+			return "", err
+		}
+		root = r
+		rootBlessing = root.BlessingStore().Default()
+	}
+
+	dir, err := ioutil.TempDir("", "shell_child_credentials")
+	if err != nil {
+		return "", err
+	}
+	// Create a principal and default blessing for the child that is
+	// derived from the blessing created for this shell. This can
+	// be used by the parent to invoke RPCs on any children and for the
+	// children to invoke RPCs on each other.
+	p, err := vsecurity.CreatePersistentPrincipal(dir, nil)
+	if err != nil {
+		return "", err
+	}
+	blessingForChild, err := root.Bless(p.PublicKey(), rootBlessing, childBlessingExtension, security.UnconstrainedUse())
+	if err != nil {
+		return "", err
+	}
+	if err := p.BlessingStore().SetDefault(blessingForChild); err != nil {
+		return "", err
+	}
+	if _, err := p.BlessingStore().Set(blessingForChild, security.AllPrincipals); err != nil {
+		return "", err
+	}
+	if err := p.AddToRoots(blessingForChild); err != nil {
+		return "", err
+	}
+
+	if sh.blessing != nil {
+		// Create a second blessing for the child, that will be accepted
+		// by the parent, should the child choose to invoke RPCs on the parent.
+		blessingFromChild, err := root.Bless(p.PublicKey(), root.BlessingStore().Default(), childBlessingExtension, security.UnconstrainedUse())
+		if err != nil {
+			return "", err
+		}
+		// We store this blessing as the one to use with a pattern that matches
+		// the root's name.
+		// TODO(cnicolaou,caprita): at some point there will be a nicer API
+		// for getting the name of a blessing.
+		ctx := security.NewContext(&security.ContextParams{LocalPrincipal: root})
+		rootName := root.BlessingStore().Default().ForContext(ctx)[0]
+		if _, err := p.BlessingStore().Set(blessingFromChild, security.BlessingPattern(rootName)); err != nil {
+			return "", err
+		}
+
+		if err := p.AddToRoots(blessingFromChild); err != nil {
+			return "", err
+		}
+	}
+	sh.tempCredDirs = append(sh.tempCredDirs, dir)
+	return dir, nil
+}
+
 type Main func(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error
 
 // String returns a string representation of the Shell, which is a
@@ -110,10 +217,20 @@
 	return registry.help(command)
 }
 
-// Start starts the specified command, it returns a Handle which can be used
-// for interacting with that command. The OS and shell environment variables
-// are merged with the ones supplied as a parameter; the parameter specified
-// ones override the Shell and the Shell ones override the OS ones.
+// Start starts the specified command, it returns a Handle which can be
+// used for interacting with that command.
+//
+// The environment variables for the command are set by merging variables
+// from the OS environment, those in this Shell and those provided as a
+// parameter to it. In general, it prefers values from its parameter over
+// those from the Shell, over those from the OS. However, the VeyronCredentials
+// environment variable is handled specially.
+//
+// If the VeyronCredentials environment variable is set in 'env' then that
+// is the value that gets used. If the shell's VeyronCredentials are set then
+// VeyronCredentials for the command are set to a freshly created directory
+// specifying a principal blessed by the shell's credentials. In all other
+// cases VeyronCredentials for the command remains unset.
 //
 // The Shell tracks all of the Handles that it creates so that it can shut
 // them down when asked to. The returned Handle may be non-nil even when an
@@ -123,7 +240,10 @@
 // Commands must have already been registered using RegisterFunction
 // or RegisterChild.
 func (sh *Shell) Start(name string, env []string, args ...string) (Handle, error) {
-	cenv := sh.MergedEnv(env)
+	cenv, err := sh.setupCommandEnv(env)
+	if err != nil {
+		return nil, err
+	}
 	cmd := registry.getCommand(name)
 	if cmd == nil {
 		return nil, fmt.Errorf("%s: not registered", name)
@@ -146,15 +266,28 @@
 	sh.startTimeout = d
 }
 
+// SetWaitTimeout sets the timeout for waiting on subcommands to complete.
+func (sh *Shell) SetWaitTimeout(d time.Duration) {
+	sh.waitTimeout = d
+}
+
 // CommandEnvelope returns the command line and environment that would be
 // used for running the subprocess or function if it were started with the
 // specifed arguments.
+//
+// This method is not idempotent as the directory pointed to by the
+// VeyronCredentials environment variable may be freshly created with
+// each invocation.
 func (sh *Shell) CommandEnvelope(name string, env []string, args ...string) ([]string, []string) {
 	cmd := registry.getCommand(name)
 	if cmd == nil {
 		return []string{}, []string{}
 	}
-	return cmd.factory().envelope(sh, sh.MergedEnv(env), args...)
+	menv, err := sh.setupCommandEnv(env)
+	if err != nil {
+		return []string{}, []string{}
+	}
+	return cmd.factory().envelope(sh, menv, args...)
 }
 
 // Forget tells the Shell to stop tracking the supplied Handle. This is
@@ -190,6 +323,11 @@
 }
 
 // SetVar sets the value to be associated with key.
+//
+// Note that setting the VeyronCredentials environement
+// variable changes the shell's principal which is used
+// for blessing the principals supplied to the shell's
+// children.
 func (sh *Shell) SetVar(key, value string) {
 	sh.mu.Lock()
 	defer sh.mu.Unlock()
@@ -198,6 +336,11 @@
 }
 
 // ClearVar removes the speficied variable from the Shell's environment
+//
+// Note that clearing the VeyronCredentials environment variable
+// would amount to clearing the shell's principal, and therefore, any
+// children of this shell would have their VeyronCredentials environment
+// variable set only if it is explicitly set in their parameters.
 func (sh *Shell) ClearVar(key string) {
 	sh.mu.Lock()
 	defer sh.mu.Unlock()
@@ -255,28 +398,49 @@
 			err = cerr
 		}
 	}
-	if len(sh.credDir) > 0 {
-		os.RemoveAll(sh.credDir)
+
+	// TODO(ataly, ashankar, caprita): The following code may lead to
+	// removing the credential directories for child processes that are
+	// still alive (this can happen e.g. if the Wait on the child timed
+	// out). While we can hope that some error will reach the caller of
+	// Cleanup (because we harvest the error codes from Shutdown), it may
+	// lead to failures that are harder to debug because the original issue
+	// will get masked by the credentials going away. One possibility is
+	// to only remove the credentials dir when Shutdown returns no timeout
+	// error.
+	for _, dir := range sh.tempCredDirs {
+		os.RemoveAll(dir)
 	}
 	return err
 }
 
-// MergedEnv returns a slice that contains the merged set of environment
-// variables from the OS environment, those in this Shell and those provided
-// as a parameter to it. It prefers values from its parameter over those
-// from the Shell, over those from the OS.
-func (sh *Shell) MergedEnv(env []string) []string {
+func (sh *Shell) setupCommandEnv(env []string) ([]string, error) {
 	osmap := envSliceToMap(os.Environ())
 	evmap := envSliceToMap(env)
+
 	sh.mu.Lock()
-	m1 := mergeMaps(osmap, sh.env)
 	defer sh.mu.Unlock()
+	m1 := mergeMaps(osmap, sh.env)
+	// Clear any VeyronCredentials directory in m1 as we never
+	// want the child to directly use the directory specified
+	// by the shell's VeyronCredentials.
+	delete(m1, consts.VeyronCredentials)
+
+	// Set the VeyronCredentials environment variable for the child
+	// if it is not already set and the shell's VeyronCredentials are set.
+	if len(evmap[consts.VeyronCredentials]) == 0 && len(sh.env[consts.VeyronCredentials]) != 0 {
+		var err error
+		if evmap[consts.VeyronCredentials], err = sh.getChildCredentials(sh.env[consts.VeyronCredentials]); err != nil {
+			return nil, err
+		}
+	}
+
 	m2 := mergeMaps(m1, evmap)
 	r := []string{}
 	for k, v := range m2 {
 		r = append(r, k+"="+v)
 	}
-	return r
+	return r, nil
 }
 
 // Handle represents a running command.
diff --git a/lib/modules/util.go b/lib/modules/util.go
index c35c74e..b38e767 100644
--- a/lib/modules/util.go
+++ b/lib/modules/util.go
@@ -1,30 +1,42 @@
 package modules
 
 import (
-	"bufio"
 	"fmt"
+	"hash/adler32"
 	"io"
 	"io/ioutil"
 	"os"
 	"strings"
+
+	vsecurity "veyron.io/veyron/veyron/security"
+
+	"veyron.io/veyron/veyron2/security"
+	"veyron.io/veyron/veyron2/vlog"
 )
 
-func newLogfile(prefix string) (*os.File, error) {
-	f, err := ioutil.TempFile("", "__modules__"+prefix)
+func newLogfile(prefix, name string) (*os.File, error) {
+	nameHash := adler32.Checksum([]byte(name))
+	f, err := ioutil.TempFile("", fmt.Sprintf("__modules__%s-%x", prefix, nameHash))
 	if err != nil {
 		return nil, err
 	}
 	return f, nil
 }
 
-func readTo(r io.Reader, w io.Writer) {
-	if w == nil {
+func outputFromFile(f *os.File, out io.Writer) {
+	f.Close()
+	fName := f.Name()
+	defer os.Remove(fName)
+	if out == nil {
 		return
 	}
-	scanner := bufio.NewScanner(r)
-	for scanner.Scan() {
-		fmt.Fprintf(w, "%s\n", scanner.Text())
+	var err error
+	if f, err = os.Open(fName); err != nil {
+		vlog.VI(1).Infof("failed to open %q: %s\n", fName, err)
+		return
 	}
+	io.Copy(out, f)
+	f.Close()
 }
 
 // envSliceToMap returns a map representation of a string slive
@@ -63,3 +75,21 @@
 	}
 	return merged
 }
+
+func principalFromDir(dir string) (security.Principal, error) {
+	p, err := vsecurity.LoadPersistentPrincipal(dir, nil)
+	if err == nil {
+		return p, nil
+	}
+	if !os.IsNotExist(err) {
+		return nil, err
+	}
+	p, err = vsecurity.CreatePersistentPrincipal(dir, nil)
+	if err != nil {
+		return nil, err
+	}
+	if err := vsecurity.InitDefaultBlessings(p, shellBlessingExtension); err != nil {
+		return nil, err
+	}
+	return p, nil
+}
diff --git a/lib/signals/signals.go b/lib/signals/signals.go
index e24e1c3..35d2965 100644
--- a/lib/signals/signals.go
+++ b/lib/signals/signals.go
@@ -5,7 +5,7 @@
 	"os/signal"
 	"syscall"
 
-	"veyron.io/veyron/veyron2/rt"
+	"veyron.io/veyron/veyron2"
 )
 
 type stopSignal string
@@ -31,7 +31,7 @@
 // none are specified, the default signals.  The first signal received will be
 // made available on the returned channel; upon receiving a second signal, the
 // process will exit.
-func ShutdownOnSignals(signals ...os.Signal) <-chan os.Signal {
+func ShutdownOnSignals(runtime veyron2.Runtime, signals ...os.Signal) <-chan os.Signal {
 	if len(signals) == 0 {
 		signals = defaultSignals()
 	}
@@ -45,9 +45,9 @@
 		case STOP:
 			if !sawStop {
 				sawStop = true
-				if r := rt.R(); r != nil {
+				if runtime != nil {
 					stopWaiter := make(chan string, 1)
-					r.AppCycle().WaitForStop(stopWaiter)
+					runtime.AppCycle().WaitForStop(stopWaiter)
 					go func() {
 						for {
 							ch <- stopSignal(<-stopWaiter)
diff --git a/lib/signals/signals_test.go b/lib/signals/signals_test.go
index d57c65c..4220712 100644
--- a/lib/signals/signals_test.go
+++ b/lib/signals/signals_test.go
@@ -41,7 +41,7 @@
 	modules.RegisterChild("handleDefaultsIgnoreChan", "", handleDefaultsIgnoreChan)
 }
 
-func stopLoop(stdin io.Reader, ch chan<- struct{}) {
+func stopLoop(runtime veyron2.Runtime, stdin io.Reader, ch chan<- struct{}) {
 	scanner := bufio.NewScanner(stdin)
 	for scanner.Scan() {
 		switch scanner.Text() {
@@ -49,19 +49,23 @@
 			close(ch)
 			return
 		case "stop":
-			rt.R().AppCycle().Stop()
+			runtime.AppCycle().Stop()
 		}
 	}
 }
 
 func program(stdin io.Reader, stdout io.Writer, signals ...os.Signal) {
-	r := rt.Init()
+	runtime, err := rt.New()
+	if err != nil {
+		panic(err)
+	}
+
 	closeStopLoop := make(chan struct{})
-	go stopLoop(stdin, closeStopLoop)
-	wait := ShutdownOnSignals(signals...)
+	go stopLoop(runtime, stdin, closeStopLoop)
+	wait := ShutdownOnSignals(runtime, signals...)
 	fmt.Fprintf(stdout, "ready\n")
 	fmt.Fprintf(stdout, "received signal %s\n", <-wait)
-	r.Cleanup()
+	runtime.Cleanup()
 	<-closeStopLoop
 }
 
@@ -81,10 +85,14 @@
 }
 
 func handleDefaultsIgnoreChan(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
-	defer rt.Init().Cleanup()
+	runtime, err := rt.New()
+	if err != nil {
+		panic(err)
+	}
+	defer runtime.Cleanup()
 	closeStopLoop := make(chan struct{})
-	go stopLoop(stdin, closeStopLoop)
-	ShutdownOnSignals()
+	go stopLoop(runtime, stdin, closeStopLoop)
+	ShutdownOnSignals(runtime)
 	fmt.Fprintf(stdout, "ready\n")
 	<-closeStopLoop
 	return nil
@@ -112,7 +120,10 @@
 }
 
 func newShell(t *testing.T, command string) (*modules.Shell, modules.Handle, *expect.Session) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	handle, err := sh.Start(command, nil)
 	if err != nil {
 		sh.Cleanup(os.Stderr, os.Stderr)
@@ -284,7 +295,7 @@
 // the input list of signals.
 func TestParseSignalsList(t *testing.T) {
 	list := []os.Signal{STOP, syscall.SIGTERM}
-	ShutdownOnSignals(list...)
+	ShutdownOnSignals(nil, list...)
 	if !isSignalInSet(syscall.SIGTERM, list) {
 		t.Errorf("signal %s not in signal set, as expected: %v", syscall.SIGTERM, list)
 	}
@@ -306,8 +317,8 @@
 
 }
 
-func createConfigServer(t *testing.T) (ipc.Server, string, <-chan string) {
-	server, err := rt.R().NewServer()
+func createConfigServer(t *testing.T, runtime veyron2.Runtime) (ipc.Server, string, <-chan string) {
+	server, err := runtime.NewServer()
 	if err != nil {
 		t.Fatalf("Got error: %v", err)
 	}
@@ -325,17 +336,23 @@
 
 // TestCleanRemoteShutdown verifies that remote shutdown works correctly.
 func TestCleanRemoteShutdown(t *testing.T) {
-	r := rt.Init()
-	defer r.Cleanup()
+	runtime, err := rt.New()
+	if err != nil {
+		panic(err)
+	}
+	defer runtime.Cleanup()
 
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 
 	// Set the child process up with a blessing from the parent so that
 	// the default authorization works for RPCs between the two.
-	childcreds := security.NewVeyronCredentials(r.Principal(), "child")
+	childcreds := security.NewVeyronCredentials(runtime.Principal(), "child")
 	defer os.RemoveAll(childcreds)
-	configServer, configServiceName, ch := createConfigServer(t)
+	configServer, configServiceName, ch := createConfigServer(t, runtime)
 	defer configServer.Stop()
 	sh.SetVar(consts.VeyronCredentials, childcreds)
 	sh.SetConfigKey(mgmt.ParentNameConfigKey, configServiceName)
@@ -349,7 +366,7 @@
 	appCycleName := <-ch
 	s.Expect("ready")
 	appCycle := appcycle.AppCycleClient(appCycleName)
-	stream, err := appCycle.Stop(r.NewContext())
+	stream, err := appCycle.Stop(runtime.NewContext())
 	if err != nil {
 		t.Fatalf("Got error: %v", err)
 	}
diff --git a/lib/stats/counter/counter.go b/lib/stats/counter/counter.go
index 4aa9db3..0dc4ec9 100644
--- a/lib/stats/counter/counter.go
+++ b/lib/stats/counter/counter.go
@@ -20,7 +20,7 @@
 
 var (
 	// Used for testing.
-	Now func() time.Time = time.Now
+	TimeNow func() time.Time = time.Now
 )
 
 const (
@@ -39,7 +39,7 @@
 
 // New returns a new Counter.
 func New() *Counter {
-	now := Now()
+	now := TimeNow()
 	c := &Counter{}
 	c.ts[hour] = newTimeSeries(now, time.Hour, time.Minute)
 	c.ts[tenminutes] = newTimeSeries(now, 10*time.Minute, 10*time.Second)
@@ -48,7 +48,7 @@
 }
 
 func (c *Counter) advance() time.Time {
-	now := Now()
+	now := TimeNow()
 	for _, ts := range c.ts {
 		ts.advanceTime(now)
 	}
@@ -141,7 +141,7 @@
 func (c *Counter) Reset() {
 	c.mu.Lock()
 	defer c.mu.Unlock()
-	now := Now()
+	now := TimeNow()
 	for _, ts := range c.ts {
 		ts.reset(now)
 	}
diff --git a/lib/stats/counter/counter_test.go b/lib/stats/counter/counter_test.go
index 03a3951..fc943b3 100644
--- a/lib/stats/counter/counter_test.go
+++ b/lib/stats/counter/counter_test.go
@@ -10,7 +10,7 @@
 
 func TestCounter(t *testing.T) {
 	now := time.Unix(1, 0)
-	counter.Now = func() time.Time { return now }
+	counter.TimeNow = func() time.Time { return now }
 	c := counter.New()
 
 	// Time 1, value=1
@@ -107,7 +107,7 @@
 
 func TestCounterRate(t *testing.T) {
 	now := time.Unix(1, 0)
-	counter.Now = func() time.Time { return now }
+	counter.TimeNow = func() time.Time { return now }
 	c := counter.New()
 
 	// No data, rate is 0.
diff --git a/lib/stats/counter/timeseries.go b/lib/stats/counter/timeseries.go
index 06b5981..3573d57 100644
--- a/lib/stats/counter/timeseries.go
+++ b/lib/stats/counter/timeseries.go
@@ -29,10 +29,10 @@
 	}
 }
 
-// advanceTime moves the timeseries forward to time t and fills in any slots
-// that get skipped in the process. Values older than the timeseries period are
-// lost.
-func (ts *timeseries) advanceTime(t time.Time) {
+// advanceTimeWithFill moves the timeseries forward to time t and fills in any
+// slots that get skipped in the process with the given value. Values older than
+// the timeseries period are lost.
+func (ts *timeseries) advanceTimeWithFill(t time.Time, value int64) {
 	advanceTo := t.Truncate(ts.resolution)
 	if !advanceTo.After(ts.time) {
 		// This is shortcut for the most common case of a busy counter
@@ -45,7 +45,6 @@
 	if steps > ts.size {
 		steps = ts.size
 	}
-	value := ts.slots[ts.head]
 	for steps > 0 {
 		ts.head = (ts.head + 1) % ts.size
 		ts.slots[ts.head] = value
@@ -54,6 +53,13 @@
 	ts.time = advanceTo
 }
 
+// advanceTime moves the timeseries forward to time t and fills in any slots
+// that get skipped in the process with the head value. Values older than the
+// timeseries period are lost.
+func (ts *timeseries) advanceTime(t time.Time) {
+	ts.advanceTimeWithFill(t, ts.slots[ts.head])
+}
+
 // set sets the current value of the timeseries.
 func (ts *timeseries) set(value int64) {
 	ts.slots[ts.head] = value
@@ -113,9 +119,10 @@
 	if ts.stepCount < int64(ts.size) {
 		to = ts.head + 1
 	}
+	tail := (ts.head + 1) % ts.size
 	min := int64(math.MaxInt64)
 	for b := 0; b < to; b++ {
-		if ts.slots[b] < min {
+		if b != tail && ts.slots[b] < min {
 			min = ts.slots[b]
 		}
 	}
@@ -128,9 +135,10 @@
 	if ts.stepCount < int64(ts.size) {
 		to = ts.head + 1
 	}
+	tail := (ts.head + 1) % ts.size
 	max := int64(math.MinInt64)
 	for b := 0; b < to; b++ {
-		if ts.slots[b] > max {
+		if b != tail && ts.slots[b] > max {
 			max = ts.slots[b]
 		}
 	}
diff --git a/lib/stats/counter/timeseries_test.go b/lib/stats/counter/timeseries_test.go
index a05191e..9a3700d 100644
--- a/lib/stats/counter/timeseries_test.go
+++ b/lib/stats/counter/timeseries_test.go
@@ -69,6 +69,28 @@
 	if expected, got := int64(345), ts.tailValue(); got != expected {
 		t.Errorf("unexpected value. Got %v, want %v", got, expected)
 	}
+	if expected, got := int64(111), ts.min(); got != expected {
+		t.Errorf("unexpected value. Got %v, want %v", got, expected)
+	}
+	if expected, got := int64(345), ts.max(); got != expected {
+		t.Errorf("unexpected value. Got %v, want %v", got, expected)
+	}
+
+	// Time 8
+	now = now.Add(time.Second)
+	ts.advanceTime(now)
+	if expected, got := int64(111), ts.headValue(); got != expected {
+		t.Errorf("unexpected value. Got %v, want %v", got, expected)
+	}
+	if expected, got := int64(345), ts.tailValue(); got != expected {
+		t.Errorf("unexpected value. Got %v, want %v", got, expected)
+	}
+	if expected, got := int64(111), ts.min(); got != expected {
+		t.Errorf("unexpected value. Got %v, want %v", got, expected)
+	}
+	if expected, got := int64(111), ts.max(); got != expected {
+		t.Errorf("unexpected value. Got %v, want %v", got, expected)
+	}
 
 	// Time 27
 	now = now.Add(20 * time.Second)
diff --git a/lib/stats/counter/tracker.go b/lib/stats/counter/tracker.go
new file mode 100644
index 0000000..30cc114
--- /dev/null
+++ b/lib/stats/counter/tracker.go
@@ -0,0 +1,159 @@
+package counter
+
+import (
+	"math"
+	"sync"
+	"time"
+)
+
+// Tracker is a min/max value tracker that keeps track of its min/max values
+// over a given period of time, and with a given resolution. The initial min
+// and max values are math.MaxInt64 and math.MinInt64 respectively.
+type Tracker struct {
+	mu           sync.RWMutex
+	min, max     int64 // All time min/max.
+	minTS, maxTS [3]*timeseries
+	lastUpdate   time.Time
+}
+
+// NewTracker returns a new Tracker.
+func NewTracker() *Tracker {
+	now := TimeNow()
+	t := &Tracker{}
+	t.minTS[hour] = newTimeSeries(now, time.Hour, time.Minute)
+	t.minTS[tenminutes] = newTimeSeries(now, 10*time.Minute, 10*time.Second)
+	t.minTS[minute] = newTimeSeries(now, time.Minute, time.Second)
+	t.maxTS[hour] = newTimeSeries(now, time.Hour, time.Minute)
+	t.maxTS[tenminutes] = newTimeSeries(now, 10*time.Minute, 10*time.Second)
+	t.maxTS[minute] = newTimeSeries(now, time.Minute, time.Second)
+	t.init()
+	return t
+}
+
+func (t *Tracker) init() {
+	t.min = math.MaxInt64
+	t.max = math.MinInt64
+	for _, ts := range t.minTS {
+		ts.set(math.MaxInt64)
+	}
+	for _, ts := range t.maxTS {
+		ts.set(math.MinInt64)
+	}
+}
+
+func (t *Tracker) advance() time.Time {
+	now := TimeNow()
+	for _, ts := range t.minTS {
+		ts.advanceTimeWithFill(now, math.MaxInt64)
+	}
+	for _, ts := range t.maxTS {
+		ts.advanceTimeWithFill(now, math.MinInt64)
+	}
+	return now
+}
+
+// LastUpdate returns the last update time of the range.
+func (t *Tracker) LastUpdate() time.Time {
+	t.mu.RLock()
+	defer t.mu.RUnlock()
+	return t.lastUpdate
+}
+
+// Push adds a new value if it is a new minimum or maximum.
+func (t *Tracker) Push(value int64) {
+	t.mu.Lock()
+	defer t.mu.Unlock()
+	t.lastUpdate = t.advance()
+	if t.min > value {
+		t.min = value
+	}
+	if t.max < value {
+		t.max = value
+	}
+	for _, ts := range t.minTS {
+		if ts.headValue() > value {
+			ts.set(value)
+		}
+	}
+	for _, ts := range t.maxTS {
+		if ts.headValue() < value {
+			ts.set(value)
+		}
+	}
+}
+
+// Min returns the minimum value of the tracker
+func (t *Tracker) Min() int64 {
+	t.mu.RLock()
+	defer t.mu.RUnlock()
+	return t.min
+}
+
+// Max returns the maximum value of the tracker.
+func (t *Tracker) Max() int64 {
+	t.mu.RLock()
+	defer t.mu.RUnlock()
+	return t.max
+}
+
+// Min1h returns the minimum value for the last hour.
+func (t *Tracker) Min1h() int64 {
+	t.mu.Lock()
+	defer t.mu.Unlock()
+	t.advance()
+	return t.minTS[hour].min()
+}
+
+// Max1h returns the maximum value for the last hour.
+func (t *Tracker) Max1h() int64 {
+	t.mu.Lock()
+	defer t.mu.Unlock()
+	t.advance()
+	return t.maxTS[hour].max()
+}
+
+// Min10m returns the minimum value for the last 10 minutes.
+func (t *Tracker) Min10m() int64 {
+	t.mu.Lock()
+	defer t.mu.Unlock()
+	t.advance()
+	return t.minTS[tenminutes].min()
+}
+
+// Max10m returns the maximum value for the last 10 minutes.
+func (t *Tracker) Max10m() int64 {
+	t.mu.Lock()
+	defer t.mu.Unlock()
+	t.advance()
+	return t.maxTS[tenminutes].max()
+}
+
+// Min1m returns the minimum value for the last 1 minute.
+func (t *Tracker) Min1m() int64 {
+	t.mu.Lock()
+	defer t.mu.Unlock()
+	t.advance()
+	return t.minTS[minute].min()
+}
+
+// Max1m returns the maximum value for the last 1 minute.
+func (t *Tracker) Max1m() int64 {
+	t.mu.Lock()
+	defer t.mu.Unlock()
+	t.advance()
+	return t.maxTS[minute].max()
+}
+
+// Reset resets the range to an empty state.
+func (t *Tracker) Reset() {
+	t.mu.Lock()
+	defer t.mu.Unlock()
+	now := TimeNow()
+	for _, ts := range t.minTS {
+		ts.reset(now)
+	}
+	for _, ts := range t.maxTS {
+		ts.reset(now)
+	}
+	t.init()
+}
diff --git a/lib/stats/counter/tracker_test.go b/lib/stats/counter/tracker_test.go
new file mode 100644
index 0000000..c2e152c
--- /dev/null
+++ b/lib/stats/counter/tracker_test.go
@@ -0,0 +1,210 @@
+package counter_test
+
+import (
+	"fmt"
+	"math"
+	"math/rand"
+	"sync"
+	"testing"
+	"time"
+
+	"veyron.io/veyron/veyron/lib/stats/counter"
+)
+
+var trackerTests = []struct {
+	after      time.Duration
+	push       int64   // 0 = none, -1 = reset
+	mins, maxs []int64 // min, 10min, hour, all time
+}{
+	{ // T0
+		after: 0,
+		push:  0,
+		mins:  []int64{math.MaxInt64, math.MaxInt64, math.MaxInt64, math.MaxInt64},
+		maxs:  []int64{math.MinInt64, math.MinInt64, math.MinInt64, math.MinInt64},
+	},
+	{ // T1
+		after: 1 * time.Second,
+		push:  5,
+		mins:  []int64{5, 5, 5, 5},
+		maxs:  []int64{5, 5, 5, 5},
+	},
+	{ // T2
+		after: 1 * time.Second,
+		push:  10,
+		mins:  []int64{5, 5, 5, 5},
+		maxs:  []int64{10, 10, 10, 10},
+	},
+	{ // T3
+		after: 1 * time.Second,
+		push:  1,
+		mins:  []int64{1, 1, 1, 1},
+		maxs:  []int64{10, 10, 10, 10},
+	},
+	{ // T4
+		after: 1 * time.Minute,
+		push:  0,
+		mins:  []int64{math.MaxInt64, 1, 1, 1},
+		maxs:  []int64{math.MinInt64, 10, 10, 10},
+	},
+	{ // T5
+		after: 10 * time.Minute,
+		push:  0,
+		mins:  []int64{math.MaxInt64, math.MaxInt64, 1, 1},
+		maxs:  []int64{math.MinInt64, math.MinInt64, 10, 10},
+	},
+	{ // T6
+		after: 1 * time.Hour,
+		push:  0,
+		mins:  []int64{math.MaxInt64, math.MaxInt64, math.MaxInt64, 1},
+		maxs:  []int64{math.MinInt64, math.MinInt64, math.MinInt64, 10},
+	},
+	{ // T7
+		after: 1 * time.Second,
+		push:  5,
+		mins:  []int64{5, 5, 5, 1},
+		maxs:  []int64{5, 5, 5, 10},
+	},
+	{ // T8
+		after: 1 * time.Minute,
+		push:  20,
+		mins:  []int64{20, 5, 5, 1},
+		maxs:  []int64{20, 20, 20, 20},
+	},
+	{ // T9
+		after: 10 * time.Minute,
+		push:  15,
+		mins:  []int64{15, 15, 5, 1},
+		maxs:  []int64{15, 15, 20, 20},
+	},
+	{ // T10
+		after: 1 * time.Hour,
+		push:  10,
+		mins:  []int64{10, 10, 10, 1},
+		maxs:  []int64{10, 10, 10, 20},
+	},
+	{ // T11
+		after: 1 * time.Second,
+		push:  -1,
+		mins:  []int64{math.MaxInt64, math.MaxInt64, math.MaxInt64, math.MaxInt64},
+		maxs:  []int64{math.MinInt64, math.MinInt64, math.MinInt64, math.MinInt64},
+	},
+	{ // T12
+		after: 1 * time.Second,
+		push:  5,
+		mins:  []int64{5, 5, 5, 5},
+		maxs:  []int64{5, 5, 5, 5},
+	},
+}
+
+func TestTracker(t *testing.T) {
+	now := time.Unix(1, 0)
+	counter.TimeNow = func() time.Time { return now }
+
+	tracker := counter.NewTracker()
+	for i, tt := range trackerTests {
+		now = now.Add(tt.after)
+		name := fmt.Sprintf("[T%d] %s:", i, now.Format("15:04:05"))
+		if tt.push > 0 {
+			tracker.Push(tt.push)
+			t.Logf("%s pushed %d\n", name, tt.push)
+		} else if tt.push < 0 {
+			tracker.Reset()
+			t.Log(name, "reset")
+		} else {
+			t.Log(name, "none")
+		}
+
+		if expected, got := tt.mins[0], tracker.Min1m(); got != expected {
+			t.Errorf("%s Min1m returned %d, want %v", name, got, expected)
+		}
+		if expected, got := tt.maxs[0], tracker.Max1m(); got != expected {
+			t.Errorf("%s Max1m returned %d, want %v", name, got, expected)
+		}
+		if expected, got := tt.mins[1], tracker.Min10m(); got != expected {
+			t.Errorf("%s Min10m returned %d, want %v", name, got, expected)
+		}
+		if expected, got := tt.maxs[1], tracker.Max10m(); got != expected {
+			t.Errorf("%s Max10m returned %d, want %v", name, got, expected)
+		}
+		if expected, got := tt.mins[2], tracker.Min1h(); got != expected {
+			t.Errorf("%s Min1h returned %d, want %v", name, got, expected)
+		}
+		if expected, got := tt.maxs[2], tracker.Max1h(); got != expected {
+			t.Errorf("%s Max1h returned %d, want %v", name, got, expected)
+		}
+		if expected, got := tt.mins[3], tracker.Min(); got != expected {
+			t.Errorf("%s Min returned %d, want %v", name, got, expected)
+		}
+		if expected, got := tt.maxs[3], tracker.Max(); got != expected {
+			t.Errorf("%s Max returned %d, want %v", name, got, expected)
+		}
+	}
+}
+
+func min(a, b int64) int64 {
+	if a > b {
+		return b
+	}
+	return a
+}
+
+func max(a, b int64) int64 {
+	if a < b {
+		return b
+	}
+	return a
+}
+
+func TestTrackerConcurrent(t *testing.T) {
+	rand.Seed(time.Now().UnixNano())
+
+	const numGoRoutines = 100
+	const numPushPerGoRoutine = 100000
+	tracker := counter.NewTracker()
+
+	var mins, maxs [numGoRoutines]int64
+	var wg sync.WaitGroup
+	wg.Add(numGoRoutines)
+	for i := 0; i < numGoRoutines; i++ {
+		go func(i int) {
+			var localMin, localMax int64 = math.MaxInt64, math.MinInt64
+			for j := 0; j < numPushPerGoRoutine; j++ {
+				v := rand.Int63()
+				tracker.Push(v)
+				localMin, localMax = min(localMin, v), max(localMax, v)
+			}
+
+			mins[i], maxs[i] = localMin, localMax
+			wg.Done()
+		}(i)
+	}
+	wg.Wait()
+
+	var expectedMin, expectedMax int64 = math.MaxInt64, math.MinInt64
+	for _, v := range mins {
+		expectedMin = min(expectedMin, v)
+	}
+	for _, v := range maxs {
+		expectedMax = max(expectedMax, v)
+	}
+
+	if got := tracker.Min(); got != expectedMin {
+		t.Errorf("Min returned %d, want %v", got, expectedMin)
+	}
+	if got := tracker.Max(); got != expectedMax {
+		t.Errorf("Max returned %d, want %v", got, expectedMax)
+	}
+}
+
+func BenchmarkTrackerPush(b *testing.B) {
+	const numVals = 10000
+	vals := rand.Perm(numVals)
+	tracker := counter.NewTracker()
+
+	b.SetParallelism(100)
+	b.RunParallel(func(pb *testing.PB) {
+		for i := 0; pb.Next(); i++ {
+			tracker.Push(int64(vals[i%numVals]))
+		}
+	})
+}
diff --git a/lib/stats/histogram/histogram.go b/lib/stats/histogram/histogram.go
index 44c3b07..2c0ccef 100644
--- a/lib/stats/histogram/histogram.go
+++ b/lib/stats/histogram/histogram.go
@@ -17,8 +17,9 @@
 type Histogram struct {
 	opts    Options
 	buckets []bucketInternal
-	sum     *counter.Counter
 	count   *counter.Counter
+	sum     *counter.Counter
+	tracker *counter.Tracker
 }
 
 // Options contains the parameters that define the histogram's buckets.
@@ -54,8 +55,9 @@
 	h := Histogram{
 		opts:    opts,
 		buckets: make([]bucketInternal, opts.NumBuckets),
-		sum:     counter.New(),
 		count:   counter.New(),
+		sum:     counter.New(),
+		tracker: counter.NewTracker(),
 	}
 	low := opts.MinValue
 	delta := opts.SmallestBucketSize
@@ -82,6 +84,7 @@
 	h.buckets[bucket].count.Incr(1)
 	h.count.Incr(1)
 	h.sum.Incr(value)
+	h.tracker.Push(value)
 	return nil
 }
 
@@ -103,6 +106,8 @@
 	v := stats.HistogramValue{
 		Count:   h.count.Value(),
 		Sum:     h.sum.Value(),
+		Min:     h.tracker.Min(),
+		Max:     h.tracker.Max(),
 		Buckets: b,
 	}
 	return v
@@ -121,6 +126,8 @@
 	v := stats.HistogramValue{
 		Count:   h.count.Delta1h(),
 		Sum:     h.sum.Delta1h(),
+		Min:     h.tracker.Min1h(),
+		Max:     h.tracker.Max1h(),
 		Buckets: b,
 	}
 	return v
@@ -139,6 +146,8 @@
 	v := stats.HistogramValue{
 		Count:   h.count.Delta10m(),
 		Sum:     h.sum.Delta10m(),
+		Min:     h.tracker.Min10m(),
+		Max:     h.tracker.Max10m(),
 		Buckets: b,
 	}
 	return v
@@ -157,6 +166,8 @@
 	v := stats.HistogramValue{
 		Count:   h.count.Delta1m(),
 		Sum:     h.sum.Delta1m(),
+		Min:     h.tracker.Min1m(),
+		Max:     h.tracker.Max1m(),
 		Buckets: b,
 	}
 	return v
diff --git a/lib/stats/histogram/histogram_test.go b/lib/stats/histogram/histogram_test.go
index e184142..538e619 100644
--- a/lib/stats/histogram/histogram_test.go
+++ b/lib/stats/histogram/histogram_test.go
@@ -8,11 +8,11 @@
 
 func TestHistogram(t *testing.T) {
 	// This creates a histogram with the following buckets:
-	//  [1, 2[
-	//  [2, 4[
-	//  [4, 8[
-	//  [8, 16[
-	//  [16, Inf
+	//  [1, 2)
+	//  [2, 4)
+	//  [4, 8)
+	//  [8, 16)
+	//  [16, Inf)
 	opts := histogram.Options{
 		NumBuckets:         5,
 		GrowthFactor:       1.0,
@@ -22,21 +22,35 @@
 	h := histogram.New(opts)
 	// Trying to add a value that's less than MinValue, should return an error.
 	if err := h.Add(0); err == nil {
-		t.Errorf("unexpected return value for Add(0.0). Want != nil, Got nil")
+		t.Errorf("unexpected return value for Add(0.0). Want != nil, got nil")
 	}
 	// Adding good values. Expect no errors.
 	for i := 1; i <= 50; i++ {
 		if err := h.Add(int64(i)); err != nil {
-			t.Errorf("unexpected return value for Add(%d). Want nil, Got %v", i, err)
+			t.Errorf("unexpected return value for Add(%d). Want nil, got %v", i, err)
 		}
 	}
 	expectedCount := []int64{1, 2, 4, 8, 35}
 	buckets := h.Value().Buckets
 	for i := 0; i < opts.NumBuckets; i++ {
 		if buckets[i].Count != expectedCount[i] {
-			t.Errorf("unexpected count for bucket[%d]. Want %d, Got %v", i, expectedCount[i], buckets[i].Count)
+			t.Errorf("unexpected count for bucket[%d]. Want %d, got %v", i, expectedCount[i], buckets[i].Count)
 		}
 	}
+
+	v := h.Value()
+	if expected, got := int64(50), v.Count; got != expected {
+		t.Errorf("unexpected count in histogram value. Want %d, got %v", expected, got)
+	}
+	if expected, got := int64(50*(1+50)/2), v.Sum; got != expected {
+		t.Errorf("unexpected sum in histogram value. Want %d, got %v", expected, got)
+	}
+	if expected, got := int64(1), v.Min; got != expected {
+		t.Errorf("unexpected min in histogram value. Want %d, got %v", expected, got)
+	}
+	if expected, got := int64(50), v.Max; got != expected {
+		t.Errorf("unexpected max in histogram value. Want %d, got %v", expected, got)
+	}
 }
 
 func BenchmarkHistogram(b *testing.B) {
diff --git a/lib/stats/stats_test.go b/lib/stats/stats_test.go
index 0773280..e7b28a4 100644
--- a/lib/stats/stats_test.go
+++ b/lib/stats/stats_test.go
@@ -25,7 +25,7 @@
 
 func TestStats(t *testing.T) {
 	now := time.Unix(1, 0)
-	counter.Now = func() time.Time { return now }
+	counter.TimeNow = func() time.Time { return now }
 
 	a := libstats.NewInteger("ipc/test/aaa")
 	b := libstats.NewFloat("ipc/test/bbb")
@@ -224,6 +224,8 @@
 			Value: istats.HistogramValue{
 				Count: 2,
 				Sum:   3,
+				Min:   1,
+				Max:   2,
 				Buckets: []istats.HistogramBucket{
 					istats.HistogramBucket{LowBound: 0, Count: 0},
 					istats.HistogramBucket{LowBound: 1, Count: 1},
@@ -253,6 +255,8 @@
 			Value: istats.HistogramValue{
 				Count: 2,
 				Sum:   5,
+				Min:   2,
+				Max:   3,
 				Buckets: []istats.HistogramBucket{
 					istats.HistogramBucket{LowBound: 0, Count: 0},
 					istats.HistogramBucket{LowBound: 1, Count: 0},
diff --git a/lib/testutil/glob.go b/lib/testutil/glob.go
index 0bc1482..fa36e79 100644
--- a/lib/testutil/glob.go
+++ b/lib/testutil/glob.go
@@ -4,15 +4,17 @@
 	"io"
 	"sort"
 
+	"veyron.io/veyron/veyron2"
+	"veyron.io/veyron/veyron2/context"
 	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/naming"
-	"veyron.io/veyron/veyron2/rt"
 )
 
 // GlobName calls __Glob on the given object with the given pattern and returns
 // a sorted list of matching object names, or an error.
-func GlobName(name, pattern string) ([]string, error) {
-	call, err := rt.R().Client().StartCall(rt.R().NewContext(), name, ipc.GlobMethod, []interface{}{pattern})
+func GlobName(ctx context.T, name, pattern string) ([]string, error) {
+	client := ctx.Runtime().(veyron2.Runtime).Client()
+	call, err := client.StartCall(ctx, name, ipc.GlobMethod, []interface{}{pattern})
 	if err != nil {
 		return nil, err
 	}
diff --git a/lib/testutil/init.go b/lib/testutil/init.go
index c8aaf5d..794ec5a 100644
--- a/lib/testutil/init.go
+++ b/lib/testutil/init.go
@@ -14,6 +14,7 @@
 	"strconv"
 	"sync"
 	"time"
+
 	"veyron.io/veyron/veyron2/vlog"
 )
 
@@ -47,6 +48,7 @@
 }
 
 var Rand *Random
+var once sync.Once
 
 // Init sets up state for running tests: Adjusting GOMAXPROCS,
 // configuring the vlog logging library, setting up the random number generator
@@ -56,28 +58,32 @@
 // flags. Thus, it is NOT a good idea to call this from the init() function
 // of any module except "main" or _test.go files.
 func Init() {
-	if os.Getenv("GOMAXPROCS") == "" {
-		// Set the number of logical processors to the number of CPUs,
-		// if GOMAXPROCS is not set in the environment.
-		runtime.GOMAXPROCS(runtime.NumCPU())
-	}
-	// At this point all of the flags that we're going to use for
-	// tests must be defined.
-	// This will be the case if this is called from the init()
-	// function of a _test.go file.
-	flag.Parse()
-	vlog.ConfigureLibraryLoggerFromFlags()
-	// Initialize pseudo-random number generator.
-	seed := time.Now().UnixNano()
-	seedString := os.Getenv(SeedEnv)
-	if seedString != "" {
-		var err error
-		base, bitSize := 0, 64
-		seed, err = strconv.ParseInt(seedString, base, bitSize)
-		if err != nil {
-			vlog.Fatalf("ParseInt(%v, %v, %v) failed: %v", seedString, base, bitSize, err)
+	init := func() {
+		if os.Getenv("GOMAXPROCS") == "" {
+			// Set the number of logical processors to the number of CPUs,
+			// if GOMAXPROCS is not set in the environment.
+			runtime.GOMAXPROCS(runtime.NumCPU())
 		}
+		// At this point all of the flags that we're going to use for
+		// tests must be defined.
+		// This will be the case if this is called from the init()
+		// function of a _test.go file.
+		flag.Parse()
+		vlog.ConfigureLibraryLoggerFromFlags()
+
+		// Initialize pseudo-random number generator.
+		seed := time.Now().UnixNano()
+		seedString := os.Getenv(SeedEnv)
+		if seedString != "" {
+			var err error
+			base, bitSize := 0, 64
+			seed, err = strconv.ParseInt(seedString, base, bitSize)
+			if err != nil {
+				vlog.Fatalf("ParseInt(%v, %v, %v) failed: %v", seedString, base, bitSize, err)
+			}
+		}
+		vlog.Infof("Seeding pseudo-random number generator with %v", seed)
+		Rand = &Random{rand: rand.New(rand.NewSource(seed))}
 	}
-	vlog.Infof("Seeding pseudo-random number generator with %v", seed)
-	Rand = &Random{rand: rand.New(rand.NewSource(seed))}
+	once.Do(init)
 }
diff --git a/lib/testutil/security/util.go b/lib/testutil/security/util.go
index f92cd99..a696269 100644
--- a/lib/testutil/security/util.go
+++ b/lib/testutil/security/util.go
@@ -9,6 +9,7 @@
 	vsecurity "veyron.io/veyron/veyron/security"
 
 	"veyron.io/veyron/veyron2/security"
+	"veyron.io/veyron/veyron2/services/security/access"
 )
 
 // NewVeyronCredentials generates a directory with a new principal
@@ -88,13 +89,13 @@
 // temporary file, and returns the path to the file. This function is meant
 // to be used for testing purposes only, it panics if there is an error. The
 // caller must ensure that the created file is removed once it is no longer needed.
-func SaveACLToFile(acl security.ACL) string {
+func SaveACLToFile(acl access.TaggedACLMap) string {
 	f, err := ioutil.TempFile("", "saved_acl")
 	if err != nil {
 		panic(err)
 	}
 	defer f.Close()
-	if err := vsecurity.SaveACL(f, acl); err != nil {
+	if err := acl.WriteTo(f); err != nil {
 		defer os.Remove(f.Name())
 		panic(err)
 	}
diff --git a/lib/testutil/security/util_test.go b/lib/testutil/security/util_test.go
index 08eb1e1..36718c3 100644
--- a/lib/testutil/security/util_test.go
+++ b/lib/testutil/security/util_test.go
@@ -7,6 +7,7 @@
 
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/security"
+	"veyron.io/veyron/veyron2/services/security/access"
 
 	_ "veyron.io/veyron/veyron/profiles"
 	vsecurity "veyron.io/veyron/veyron/security"
@@ -37,14 +38,11 @@
 		t.Fatalf("rt.New failed: %v", err)
 	}
 	defer r.Cleanup()
-	acl := security.ACL{}
-	acl.In = map[security.BlessingPattern]security.LabelSet{
-		"veyron/...":   security.LabelSet(security.ReadLabel),
-		"veyron/alice": security.LabelSet(security.ReadLabel | security.WriteLabel),
-		"veyron/bob":   security.LabelSet(security.AdminLabel),
-	}
-	acl.NotIn = map[string]security.LabelSet{
-		"veyron/che": security.LabelSet(security.ReadLabel),
+	acl := access.TaggedACLMap{
+		"Admin": access.ACL{
+			In:    []security.BlessingPattern{"comics/..."},
+			NotIn: []string{"comics/villain"},
+		},
 	}
 
 	filePath := SaveACLToFile(acl)
@@ -55,12 +53,12 @@
 		t.Fatalf("os.Open(%v) failed: %v", filePath, err)
 	}
 	defer f.Close()
-	loadedACL, err := vsecurity.LoadACL(f)
+	loadedACL, err := access.ReadTaggedACLMap(f)
 	if err != nil {
 		t.Fatalf("LoadACL failed: %v", err)
 	}
 	if !reflect.DeepEqual(loadedACL, acl) {
-		t.Fatalf("Got ACL %v, but want %v", loadedACL, acl)
+		t.Fatalf("Got %#v, want %#v", loadedACL, acl)
 	}
 }
 
diff --git a/lib/websocket/conn_nacl.go b/lib/websocket/conn_nacl.go
index 22d368d..e20ced8 100644
--- a/lib/websocket/conn_nacl.go
+++ b/lib/websocket/conn_nacl.go
@@ -50,7 +50,7 @@
 	if len(c.currBuffer) == 0 {
 		c.currBuffer, err = c.ws.ReceiveMessage()
 		if err != nil {
-			return 0, nil
+			return 0, err
 		}
 	}
 
diff --git a/runtimes/google/ipc/benchmarks/bmclient/main.go b/runtimes/google/ipc/benchmarks/bmclient/main.go
index aee94e8..874afb2 100644
--- a/runtimes/google/ipc/benchmarks/bmclient/main.go
+++ b/runtimes/google/ipc/benchmarks/bmclient/main.go
@@ -19,6 +19,8 @@
 
 func main() {
 	r := rt.Init()
+	defer r.Cleanup()
+
 	ctx := r.NewContext()
 	if *chunkCount == 0 {
 		benchmarks.CallEcho(ctx, *server, *count, *payloadSize, os.Stdout)
diff --git a/runtimes/google/ipc/benchmarks/bmserver/main.go b/runtimes/google/ipc/benchmarks/bmserver/main.go
index f07afef..7d09e63 100644
--- a/runtimes/google/ipc/benchmarks/bmserver/main.go
+++ b/runtimes/google/ipc/benchmarks/bmserver/main.go
@@ -12,8 +12,10 @@
 
 func main() {
 	r := rt.Init()
+	defer r.Cleanup()
+
 	addr, stop := benchmarks.StartServer(r, roaming.ListenSpec)
 	vlog.Infof("Listening on %s", addr)
 	defer stop()
-	<-signals.ShutdownOnSignals()
+	<-signals.ShutdownOnSignals(r)
 }
diff --git a/runtimes/google/ipc/client.go b/runtimes/google/ipc/client.go
index 2121314..91fc5bc 100644
--- a/runtimes/google/ipc/client.go
+++ b/runtimes/google/ipc/client.go
@@ -13,26 +13,73 @@
 	"veyron.io/veyron/veyron/runtimes/google/ipc/stream/vc"
 	"veyron.io/veyron/veyron/runtimes/google/ipc/version"
 	inaming "veyron.io/veyron/veyron/runtimes/google/naming"
-	"veyron.io/veyron/veyron/runtimes/google/vtrace"
+	ivtrace "veyron.io/veyron/veyron/runtimes/google/vtrace"
 
 	"veyron.io/veyron/veyron2/context"
+	"veyron.io/veyron/veyron2/i18n"
 	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/ipc/stream"
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/options"
 	"veyron.io/veyron/veyron2/security"
 	"veyron.io/veyron/veyron2/vdl/vdlutil"
-	"veyron.io/veyron/veyron2/verror"
+	old_verror "veyron.io/veyron/veyron2/verror"
+	verror "veyron.io/veyron/veyron2/verror2"
 	"veyron.io/veyron/veyron2/vlog"
 	"veyron.io/veyron/veyron2/vom"
+	"veyron.io/veyron/veyron2/vom2"
+	"veyron.io/veyron/veyron2/vtrace"
 )
 
+const pkgPath = "veyron.io/veyron/veyron/runtimes/google/ipc"
+
 var (
-	errNoServers              = verror.NoExistf("ipc: no servers")
-	errNoAccess               = verror.NoAccessf("ipc: client unwilling to access to server")
-	errFlowClosed             = verror.Abortedf("ipc: flow closed")
-	errRemainingStreamResults = verror.BadProtocolf("ipc: Finish called with remaining streaming results")
-	errNonRootedName          = verror.BadArgf("ipc: cannot connect to a non-rooted name")
+	// Local errs that are used to provide details to the public ones.
+	errClientCloseAlreadyCalled = verror.Register(pkgPath+".closeAlreadyCalled", verror.NoRetry,
+		"ipc.Client.Close has already been called")
+
+	errClientFinishAlreadyCalled = verror.Register(pkgPath+".finishAlreadyCalled", verror.NoRetry, "ipc.Call.Finish has already been called")
+
+	errNonRootedName = verror.Register(pkgPath+".nonRootedName", verror.NoRetry, "{3} does not appear to contain an address")
+
+	errInvalidEndpoint = verror.Register(pkgPath+".invalidEndpoint", verror.RetryRefetch, "{3} is an invalid endpoint")
+
+	errIncompatibleEndpoint = verror.Register(pkgPath+".invalidEndpoint", verror.RetryRefetch, "{3} is an incompatible endpoint")
+
+	errNotTrusted = verror.Register(pkgPath+".notTrusted", verror.RetryConnection, "name {3} not trusted using blessings {4}{:5}")
+
+	errAuthError = verror.Register(pkgPath+".authError", verror.RetryRefetch, "authentication error from server {3}{:4}")
+
+	errSystemRetry   = verror.Register(pkgPath+".sysErrorRetryConnection", verror.RetryConnection, "{:3:}")
+	errSystemNoRetry = verror.Register(pkgPath+".sysErrorNoRetry", verror.NoRetry, "{:3:}")
+
+	errVomEncoder = verror.Register(pkgPath+".vomEncoder", verror.NoRetry, "failed to create vom encoder {:3}")
+	errVomDecoder = verror.Register(pkgPath+".vomDecoder", verror.NoRetry, "failed to create vom decoder {:3}")
+
+	errRequestEncoding = verror.Register(pkgPath+".requestEncoding", verror.NoRetry, "failed to encode request {3}{:4}")
+
+	errDischargeEncoding = verror.Register(pkgPath+".dischargeEncoding", verror.NoRetry, "failed to encode discharge {3}{:4}")
+
+	errArgEncoding = verror.Register(pkgPath+".argEncoding", verror.NoRetry, "failed to encode arg #{3}{:4:}")
+
+	errMismatchedResults = verror.Register(pkgPath+".mismatchedResults", verror.NoRetry, "expected {3} results, but got {4}")
+
+	errResultDecoding = verror.Register(pkgPath+".resultDecoding", verror.NoRetry, "failed to decode result #{3}{:4}")
+
+	errResponseDecoding = verror.Register(pkgPath+".responseDecoding", verror.NoRetry, "failed to decode response{:3}")
+
+	errRemainingStreamResults = verror.Register(pkgPath+".remaingStreamResults", verror.NoRetry, "stream closed with remaining stream results")
+
+	errNoBlessings = verror.Register(pkgPath+".noBlessings", verror.NoRetry, "server has not presented any blessings")
+
+	errAuthNoPatternMatch = verror.Register(pkgPath+".authNoPatternMatch",
+		verror.NoRetry, "server blessings {3} do not match pattern {4}")
+
+	errDefaultAuthDenied = verror.Register(pkgPath+".defaultAuthDenied", verror.NoRetry, "default authorization precludes talking to server with blessings{:3}")
+
+	errBlessingGrant = verror.Register(pkgPath+".blessingGrantFailed", verror.NoRetry, "failed to grant blessing to server with blessings {3}{:4}")
+
+	errBlessingAdd = verror.Register(pkgPath+".blessingAddFailed", verror.NoRetry, "failed to add blessing granted to server {3}{:4}")
 )
 
 var serverPatternRegexp = regexp.MustCompile("^\\[([^\\]]+)\\](.*)")
@@ -87,11 +134,11 @@
 	return c, nil
 }
 
-func (c *client) createFlow(ep naming.Endpoint) (stream.Flow, error) {
+func (c *client) createFlow(ctx context.T, ep naming.Endpoint, noDischarges bool) (stream.Flow, verror.E) {
 	c.vcMapMu.Lock()
 	defer c.vcMapMu.Unlock()
 	if c.vcMap == nil {
-		return nil, fmt.Errorf("client has been closed")
+		return nil, verror.Make(errClientCloseAlreadyCalled, ctx)
 	}
 	if vcinfo := c.vcMap[ep.String()]; vcinfo != nil {
 		if flow, err := vcinfo.vc.Connect(); err == nil {
@@ -109,14 +156,21 @@
 	vcOpts := make([]stream.VCOpt, len(c.vcOpts))
 	copy(vcOpts, c.vcOpts)
 	c.vcMapMu.Unlock()
-	vc, err := sm.Dial(ep, vcOpts...)
+	if noDischarges {
+		vcOpts = append(vcOpts, vc.NoDischarges{})
+	}
+	vc, err := sm.Dial(ep, append(vcOpts, vc.DialContext{ctx})...)
 	c.vcMapMu.Lock()
 	if err != nil {
-		return nil, err
+		if strings.Contains(err.Error(), "authentication failed") {
+			return nil, verror.Make(errAuthError, ctx, ep, err)
+		} else {
+			return nil, verror.Make(errSystemRetry, ctx, err)
+		}
 	}
 	if c.vcMap == nil {
 		sm.ShutdownEndpoint(ep)
-		return nil, fmt.Errorf("client has been closed")
+		return nil, verror.Make(errClientCloseAlreadyCalled, ctx)
 	}
 	if othervc, exists := c.vcMap[ep.String()]; exists {
 		vc = othervc.vc
@@ -125,33 +179,40 @@
 	} else {
 		c.vcMap[ep.String()] = &vcInfo{vc: vc, remoteEP: ep}
 	}
-	return vc.Connect()
+	flow, err := vc.Connect()
+	if err != nil {
+
+		return nil, verror.Make(errAuthError, ctx, ep, err)
+	}
+	return flow, nil
 }
 
 // connectFlow parses an endpoint and a suffix out of the server and establishes
 // a flow to the endpoint, returning the parsed suffix.
 // The server name passed in should be a rooted name, of the form "/ep/suffix" or
 // "/ep//suffix", or just "/ep".
-func (c *client) connectFlow(server string) (stream.Flow, string, error) {
+func (c *client) connectFlow(ctx context.T, server string, noDischarges bool) (stream.Flow, string, verror.E) {
 	address, suffix := naming.SplitAddressName(server)
 	if len(address) == 0 {
-		return nil, "", errNonRootedName
+		return nil, "", verror.Make(errNonRootedName, ctx, server)
 	}
 	ep, err := inaming.NewEndpoint(address)
 	if err != nil {
-		return nil, "", err
+		return nil, "", verror.Make(errInvalidEndpoint, ctx, address)
 	}
 	if err = version.CheckCompatibility(ep); err != nil {
-		return nil, "", err
+		return nil, "", verror.Make(errIncompatibleEndpoint, ctx, ep)
 	}
-	flow, err := c.createFlow(ep)
-	if err != nil {
-		return nil, "", err
+	flow, verr := c.createFlow(ctx, ep, noDischarges)
+	if verr != nil {
+		return nil, "", verr
 	}
 	return flow, suffix, nil
 }
 
 // A randomized exponential backoff.  The randomness deters error convoys from forming.
+// TODO(cnicolaou): rationalize this and the backoff in ipc.Server. Note
+// that rand is not thread safe and may crash.
 func backoff(n int, deadline time.Time) bool {
 	b := time.Duration(math.Pow(1.5+(rand.Float64()/2.0), float64(n)) * float64(time.Second))
 	if b > maxBackoff {
@@ -171,29 +232,6 @@
 	return true
 }
 
-// TODO(p): replace these checks with m3b's retry bit when it exists.  This is currently a colossal hack.
-func retriable(err error) bool {
-	e := err.Error()
-	// Authentication errors are permanent.
-	if strings.Contains(e, "authorized") {
-		return false
-	}
-	// Resolution errors are retriable.
-	if strings.Contains(e, "ipc: Resolve") {
-		return true
-	}
-	// Kernel level errors are retriable.
-	if strings.Contains(e, "errno") {
-		return true
-	}
-	// Connection refused is retriable.
-	if strings.Contains(e, "connection refused") {
-		return true
-	}
-
-	return false
-}
-
 func getRetryTimeoutOpt(opts []ipc.CallOpt) (time.Duration, bool) {
 	for _, o := range opts {
 		if r, ok := o.(options.RetryTimeout); ok {
@@ -217,6 +255,15 @@
 	return false
 }
 
+func shouldNotFetchDischarges(opts []ipc.CallOpt) bool {
+	for _, o := range opts {
+		if _, ok := o.(vc.NoDischarges); ok {
+			return true
+		}
+	}
+	return false
+}
+
 func mkDischargeImpetus(serverBlessings []string, method string, args []interface{}) security.DischargeImpetus {
 	var impetus security.DischargeImpetus
 	if len(serverBlessings) > 0 {
@@ -238,8 +285,10 @@
 // startCall ensures StartCall always returns verror.E.
 func (c *client) startCall(ctx context.T, name, method string, args []interface{}, opts []ipc.CallOpt) (ipc.Call, verror.E) {
 	if ctx == nil {
-		return nil, verror.BadArgf("ipc: %s.%s called with nil context", name, method)
+		return nil, verror.ExplicitMake(verror.BadArg, i18n.NoLangID, "ipc.Client", "StartCall")
 	}
+	ctx, span := ivtrace.WithNewSpan(ctx, fmt.Sprintf("<client>%q.%s", name, method))
+	ctx = verror.ContextWithComponentName(ctx, "ipc.Client")
 
 	// Context specified deadline.
 	deadline, hasDeadline := ctx.Deadline()
@@ -251,6 +300,9 @@
 		// Caller specified deadline.
 		deadline = time.Now().Add(time.Duration(r))
 	}
+
+	skipResolve := getNoResolveOpt(opts)
+
 	var lastErr verror.E
 	for retries := 0; ; retries++ {
 		if retries != 0 {
@@ -258,64 +310,95 @@
 				break
 			}
 		}
-		call, err := c.tryCall(ctx, name, method, args, opts)
+		call, err := c.tryCall(ctx, name, method, args, skipResolve, opts)
 		if err == nil {
 			return call, nil
 		}
 		lastErr = err
-		if time.Now().After(deadline) || !retriable(err) {
+
+		shouldRetry := true
+		switch {
+		case err.Action() != verror.RetryConnection && err.Action() != verror.RetryRefetch:
+			shouldRetry = false
+		case time.Now().After(deadline):
+			shouldRetry = false
+		case verror.Is(err, verror.NoServers.ID) && skipResolve:
+			// If we're skipping resolution and there are no servers for
+			// this call retrying is not going to help, we can't come up
+			// with new servers if there is no resolution.
+			shouldRetry = false
+		}
+
+		if !shouldRetry {
+			span.Annotatef("Cannot retry after error: %s", err)
 			break
 		}
+		span.Annotatef("Retrying due to error: %s", err)
 	}
 	return nil, lastErr
 }
 
 type serverStatus struct {
-	index     int
-	suffix    string
-	flow      stream.Flow
-	errConn   verror.E
-	errAccess verror.E
+	index  int
+	suffix string
+	flow   stream.Flow
+	err    verror.E
 }
 
 // TODO(cnicolaou): implement real, configurable load balancing.
-func (c *client) tryServer(index int, server string, ch chan<- *serverStatus) {
+func (c *client) tryServer(ctx context.T, index int, server string, ch chan<- *serverStatus, noDischarges bool) {
 	status := &serverStatus{index: index}
-	var err error
-	if status.flow, status.suffix, err = c.connectFlow(server); err != nil {
-		vlog.VI(2).Infof("ipc: couldn't connect to server %v: %v", server, err)
-		status.errConn = verror.NoExistf("ipc: %q: %s", server, err)
+	var err verror.E
+	var span vtrace.Span
+	ctx, span = ivtrace.WithNewSpan(ctx, "<client>connectFlow")
+	span.Annotatef("address:%v", server)
+	defer span.Finish()
+	if status.flow, status.suffix, err = c.connectFlow(ctx, server, noDischarges); err != nil {
+		vlog.VI(2).Infof("ipc: err: %s", err)
+		status.err = err
 		status.flow = nil
 	}
 	ch <- status
 }
 
 // tryCall makes a single attempt at a call, against possibly multiple servers.
-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>\"%s\".%s", name, method))
-	_, serverPattern, name := splitObjectName(name)
+func (c *client) tryCall(ctx context.T, name, method string, args []interface{}, skipResolve bool, opts []ipc.CallOpt) (ipc.Call, verror.E) {
+	mtPattern, serverPattern, name := splitObjectName(name)
+	noDischarges := shouldNotFetchDischarges(opts)
 	// Resolve name unless told not to.
 	var servers []string
-	if getNoResolveOpt(opts) {
+	if skipResolve {
 		servers = []string{name}
 	} else {
-		if resolved, err := c.ns.Resolve(ctx, name); err != nil {
-			return nil, verror.NoExistf("ipc: Resolve(%q) failed: %v", name, err)
+		if resolved, err := c.ns.Resolve(ctx, name, naming.RootBlessingPatternOpt(mtPattern)); err != nil {
+			if verror.Is(err, naming.ErrNoSuchName.ID) {
+				return nil, verror.Make(verror.NoServers, ctx, name)
+			}
+			return nil, verror.Make(verror.NoExist, ctx, name, err)
 		} else {
+			if len(resolved) == 0 {
+				return nil, verror.Make(verror.NoServers, ctx, name)
+			}
 			// An empty set of protocols means all protocols...
 			ordered, err := filterAndOrderServers(resolved, c.preferredProtocols)
-			if len(ordered) == 0 {
-				return nil, verror.NoExistf("ipc: %q: %s", name, err)
+			if err != nil {
+				return nil, verror.Make(verror.NoServers, ctx, name, err)
+			} else if len(ordered) == 0 {
+				// sooo annoying....
+				r := []interface{}{err}
+				r = append(r, name)
+				for _, s := range resolved {
+					r = append(r, s)
+				}
+				return nil, verror.Make(verror.NoServers, ctx, r)
 			}
 			servers = ordered
 		}
 	}
+
 	// servers is now orderd by the priority heurestic implemented in
 	// filterAndOrderServers.
 	attempts := len(servers)
-	if attempts == 0 {
-		return nil, errNoServers
-	}
 
 	// Try to connect to all servers in parallel.  Provide sufficient buffering
 	// for all of the connections to finish instantaneously. This is important
@@ -325,7 +408,7 @@
 	responses := make([]*serverStatus, attempts)
 	ch := make(chan *serverStatus, attempts)
 	for i, server := range servers {
-		go c.tryServer(i, server, ch)
+		go c.tryServer(ctx, i, server, ch, noDischarges)
 	}
 
 	delay := time.Duration(ipc.NoTimeout)
@@ -351,7 +434,7 @@
 			}
 		case <-timeoutChan:
 			vlog.VI(2).Infof("ipc: timeout on connection to server %v ", name)
-			return c.failedTryCall(name, method, servers, responses, ch)
+			return c.failedTryCall(ctx, name, method, servers, responses, ch)
 		}
 
 		// Process new responses, in priority order.
@@ -375,9 +458,10 @@
 			if r.flow.LocalPrincipal() != nil {
 				// Validate caveats on the server's identity for the context associated with this call.
 				var err error
-				if serverB, grantedB, err = c.authorizeServer(r.flow, name, method, serverPattern, opts); err != nil {
-					vlog.VI(2).Infof("ipc: client unwilling to invoke %q.%q on server %v: %v", name, method, r.flow.RemoteBlessings(), err)
-					r.errAccess = verror.NoAccessf("ipc: unwilling to invoke %q.%q on server %v: %v", name, method, r.flow.RemoteBlessings(), err)
+				if serverB, grantedB, err = c.authorizeServer(ctx, r.flow, name, method, serverPattern, opts); err != nil {
+					r.err = verror.Make(errNotTrusted, ctx,
+						name, r.flow.RemoteBlessings(), err)
+					vlog.VI(2).Infof("ipc: err: %s", r.err)
 					r.flow.Close()
 					r.flow = nil
 					continue
@@ -393,7 +477,10 @@
 			//
 			// We must ensure that all flows other than r.flow are closed.
 			go cleanupTryCall(r, responses, ch)
-			fc := newFlowClient(ctx, serverB, r.flow, c.dc)
+			fc, err := newFlowClient(ctx, serverB, r.flow, c.dc)
+			if err != nil {
+				return nil, err.(verror.E)
+			}
 
 			if doneChan := ctx.Done(); doneChan != nil {
 				go func() {
@@ -409,13 +496,16 @@
 			if deadline, hasDeadline := ctx.Deadline(); hasDeadline {
 				timeout = deadline.Sub(time.Now())
 			}
+			if noDischarges {
+				fc.dc = nil
+			}
 			if verr := fc.start(r.suffix, method, args, timeout, grantedB); verr != nil {
 				return nil, verr
 			}
 			return fc, nil
 		}
 		if numResponses == len(responses) {
-			return c.failedTryCall(name, method, servers, responses, ch)
+			return c.failedTryCall(ctx, name, method, servers, responses, ch)
 		}
 	}
 }
@@ -449,30 +539,38 @@
 // failedTryCall performs asynchronous cleanup for tryCall, and returns an
 // appropriate error from the responses we've already received.  All parallel
 // calls in tryCall failed or we timed out if we get here.
-func (c *client) failedTryCall(name, method string, servers []string, responses []*serverStatus, ch chan *serverStatus) (ipc.Call, verror.E) {
+func (c *client) failedTryCall(ctx context.T, name, method string, servers []string, responses []*serverStatus, ch chan *serverStatus) (ipc.Call, verror.E) {
 	go cleanupTryCall(nil, responses, ch)
 	c.ns.FlushCacheEntry(name)
-	// TODO(cnicolaou): introduce a third error code here for mixed
-	// conn/access errors.
-	var errs []verror.E
-	for _, r := range responses {
-		switch {
-		case r != nil && r.errConn != nil:
-			errs = append(errs, r.errConn)
-		case r != nil && r.errAccess != nil:
-			errs = append(errs, r.errAccess)
+	noconn, untrusted := []string{}, []string{}
+	for i, r := range responses {
+		if r != nil && r.err != nil {
+			vlog.VI(2).Infof("Server: %s: %s", servers[i], r.err)
+			switch {
+			case verror.Is(r.err, errNotTrusted.ID) || verror.Is(r.err, errAuthError.ID):
+				untrusted = append(untrusted, r.err.Error())
+			default:
+				noconn = append(noconn, r.err.Error())
+			}
 		}
 	}
-	return nil, verror.NoExistf("ipc: client failed to invoke %q.%q: on %v: %v", name, method, servers, errs)
+	switch {
+	case len(untrusted) > 0 && len(noconn) > 0:
+		return nil, verror.Make(verror.NoServersAndAuth, ctx, append(noconn, untrusted...))
+	case len(noconn) > 0:
+		return nil, verror.Make(verror.NoServers, ctx, noconn)
+	default:
+		return nil, verror.Make(verror.NotTrusted, ctx, untrusted)
+	}
 }
 
 // authorizeServer validates that the server (remote end of flow) has the credentials to serve
 // the RPC name.method for the client (local end of the flow). It returns the blessings at the
 // server that are authorized for this purpose and any blessings that are to be granted to
 // the server (via ipc.Granter implementations in opts.)
-func (c *client) authorizeServer(flow stream.Flow, name, method string, serverPattern security.BlessingPattern, opts []ipc.CallOpt) (serverBlessings []string, grantedBlessings security.Blessings, err error) {
+func (c *client) authorizeServer(ctx context.T, flow stream.Flow, name, method string, serverPattern security.BlessingPattern, opts []ipc.CallOpt) (serverBlessings []string, grantedBlessings security.Blessings, err verror.E) {
 	if flow.RemoteBlessings() == nil {
-		return nil, nil, fmt.Errorf("server has not presented any blessings")
+		return nil, nil, verror.Make(errNoBlessings, ctx)
 	}
 	ctxt := security.NewContext(&security.ContextParams{
 		LocalPrincipal:   flow.LocalPrincipal(),
@@ -486,20 +584,20 @@
 	serverBlessings = flow.RemoteBlessings().ForContext(ctxt)
 	if serverPattern != "" {
 		if !serverPattern.MatchedBy(serverBlessings...) {
-			return nil, nil, fmt.Errorf("server %v does not match the provided pattern %q", serverBlessings, serverPattern)
+			return nil, nil, verror.Make(errAuthNoPatternMatch, ctx, serverBlessings, serverPattern)
 		}
 	} else if enableSecureServerAuth {
 		if err := (defaultAuthorizer{}).Authorize(ctxt); err != nil {
-			return nil, nil, fmt.Errorf("default authorization precludes talking to server %v", serverBlessings)
+			return nil, nil, verror.Make(errDefaultAuthDenied, ctx, serverBlessings)
 		}
 	}
 	for _, o := range opts {
 		switch v := o.(type) {
 		case ipc.Granter:
 			if b, err := v.Grant(flow.RemoteBlessings()); err != nil {
-				return nil, nil, fmt.Errorf("failed to grant blessing to server %v: %v", serverBlessings, err)
+				return nil, nil, verror.Make(errBlessingGrant, ctx, serverBlessings, err)
 			} else if grantedBlessings, err = security.UnionOfBlessings(grantedBlessings, b); err != nil {
-				return nil, nil, fmt.Errorf("failed to add blessing granted to server %v: %v", serverBlessings, err)
+				return nil, nil, verror.Make(errBlessingAdd, ctx, serverBlessings, err)
 			}
 		}
 	}
@@ -525,8 +623,8 @@
 // flow that's already connected to the server.
 type flowClient struct {
 	ctx      context.T    // context to annotate with call details
-	dec      *vom.Decoder // to decode responses and results from the server
-	enc      *vom.Encoder // to encode requests and args to the server
+	dec      vomDecoder   // to decode responses and results from the server
+	enc      vomEncoder   // to encode requests and args to the server
 	server   []string     // Blessings bound to the server that authorize it to receive the IPC request from the client.
 	flow     stream.Flow  // the underlying flow
 	response ipc.Response // each decoded response message is kept here
@@ -543,8 +641,8 @@
 var _ ipc.Call = (*flowClient)(nil)
 var _ ipc.Stream = (*flowClient)(nil)
 
-func newFlowClient(ctx context.T, server []string, flow stream.Flow, dc vc.DischargeClient) *flowClient {
-	return &flowClient{
+func newFlowClient(ctx context.T, server []string, flow stream.Flow, dc vc.DischargeClient) (*flowClient, error) {
+	fc := &flowClient{
 		ctx:    ctx,
 		dec:    vom.NewDecoder(flow),
 		enc:    vom.NewEncoder(flow),
@@ -552,11 +650,24 @@
 		flow:   flow,
 		dc:     dc,
 	}
+	if vom2.IsEnabled() {
+		var err error
+		if fc.enc, err = vom2.NewBinaryEncoder(flow); err != nil {
+			return nil, fc.close(badProtocol(fc.ctx, verror.Make(errVomEncoder, fc.ctx, err)))
+		}
+		if fc.dec, err = vom2.NewDecoder(flow); err != nil {
+			return nil, fc.close(badProtocol(fc.ctx, verror.Make(errVomDecoder, fc.ctx, err)))
+		}
+	} else {
+		fc.dec = vom.NewDecoder(flow)
+		fc.enc = vom.NewEncoder(flow)
+	}
+	return fc, nil
 }
 
 func (fc *flowClient) close(verr verror.E) verror.E {
 	if err := fc.flow.Close(); err != nil && verr == nil {
-		verr = verror.Internalf("ipc: flow close failed: %v", err)
+		verr = verror.Make(errSystemNoRetry, fc.ctx, err)
 	}
 	return verr
 }
@@ -565,7 +676,7 @@
 	// Fetch any discharges for third-party caveats on the client's blessings
 	// if this client owns a discharge-client.
 	if self := fc.flow.LocalBlessings(); self != nil && fc.dc != nil {
-		fc.discharges = fc.dc.PrepareDischarges(self.ThirdPartyCaveats(), mkDischargeImpetus(fc.server, method, args))
+		fc.discharges = fc.dc.PrepareDischarges(fc.ctx, self.ThirdPartyCaveats(), mkDischargeImpetus(fc.server, method, args))
 	}
 	req := ipc.Request{
 		Suffix:           suffix,
@@ -574,19 +685,19 @@
 		Timeout:          int64(timeout),
 		GrantedBlessings: security.MarshalBlessings(blessings),
 		NumDischarges:    uint64(len(fc.discharges)),
-		TraceRequest:     vtrace.Request(fc.ctx),
+		TraceRequest:     ivtrace.Request(fc.ctx),
 	}
 	if err := fc.enc.Encode(req); err != nil {
-		return fc.close(verror.BadProtocolf("ipc: request encoding failed: %v", err))
+		return fc.close(badProtocol(fc.ctx, verror.Make(errRequestEncoding, fc.ctx, req, err)))
 	}
 	for _, d := range fc.discharges {
 		if err := fc.enc.Encode(d); err != nil {
-			return fc.close(verror.BadProtocolf("ipc: failed to encode discharge for %x: %v", d.ID(), err))
+			return fc.close(badProtocol(fc.ctx, verror.Make(errDischargeEncoding, fc.ctx, d.ID(), err)))
 		}
 	}
 	for ix, arg := range args {
 		if err := fc.enc.Encode(arg); err != nil {
-			return fc.close(verror.BadProtocolf("ipc: arg %d encoding failed: %v", ix, err))
+			return fc.close(badProtocol(fc.ctx, verror.Make(errArgEncoding, fc.ctx, ix, err)))
 		}
 	}
 	return nil
@@ -595,15 +706,15 @@
 func (fc *flowClient) Send(item interface{}) error {
 	defer vlog.LogCall()()
 	if fc.sendClosed {
-		return errFlowClosed
+		return verror.Make(verror.Aborted, fc.ctx)
 	}
 
 	// The empty request header indicates what follows is a streaming arg.
 	if err := fc.enc.Encode(ipc.Request{}); err != nil {
-		return fc.close(verror.BadProtocolf("ipc: streaming request header encoding failed: %v", err))
+		return fc.close(badProtocol(fc.ctx, verror.Make(errRequestEncoding, fc.ctx, ipc.Request{}, err)))
 	}
 	if err := fc.enc.Encode(item); err != nil {
-		return fc.close(verror.BadProtocolf("ipc: streaming arg encoding failed: %v", err))
+		return fc.close(badProtocol(fc.ctx, verror.Make(errArgEncoding, fc.ctx, -1, err)))
 	}
 	return nil
 }
@@ -619,7 +730,7 @@
 
 	// Decode the response header and handle errors and EOF.
 	if err := fc.dec.Decode(&fc.response); err != nil {
-		return fc.close(verror.BadProtocolf("ipc: response header decoding failed: %v", err))
+		return fc.close(badProtocol(fc.ctx, verror.Make(errResponseDecoding, fc.ctx, err)))
 	}
 	if fc.response.Error != nil {
 		return fc.response.Error
@@ -632,7 +743,7 @@
 	}
 	// Decode the streaming result.
 	if err := fc.dec.Decode(itemptr); err != nil {
-		return fc.close(verror.BadProtocolf("ipc: streaming result decoding failed: %v", err))
+		return fc.close(badProtocol(fc.ctx, verror.Make(errResponseDecoding, fc.ctx, err)))
 	}
 	return nil
 }
@@ -672,14 +783,19 @@
 func (fc *flowClient) Finish(resultptrs ...interface{}) error {
 	defer vlog.LogCall()()
 	err := fc.finish(resultptrs...)
-	vtrace.FromContext(fc.ctx).Finish()
+	ivtrace.FromContext(fc.ctx).Finish()
 	return err
 }
 
+func badProtocol(ctx context.T, err verror.E) verror.E {
+	return verror.Make(verror.BadProtocol, ctx, err)
+}
+
 // finish ensures Finish always returns verror.E.
 func (fc *flowClient) finish(resultptrs ...interface{}) verror.E {
 	if fc.finished {
-		return fc.close(verror.BadProtocolf("ipc: multiple calls to Finish not allowed"))
+		err := verror.Make(errClientFinishAlreadyCalled, fc.ctx)
+		return fc.close(verror.Make(verror.BadState, fc.ctx, err))
 	}
 	fc.finished = true
 	// Call closeSend implicitly, if the user hasn't already called it.  There are
@@ -701,19 +817,21 @@
 	// Decode the response header, if it hasn't already been decoded by Recv.
 	if fc.response.Error == nil && !fc.response.EndStreamResults {
 		if err := fc.dec.Decode(&fc.response); err != nil {
-			return fc.close(verror.BadProtocolf("ipc: response header decoding failed: %v", err))
+			return fc.close(badProtocol(fc.ctx, verror.Make(errResponseDecoding, fc.ctx, err)))
 		}
 		// The response header must indicate the streaming results have ended.
 		if fc.response.Error == nil && !fc.response.EndStreamResults {
-			return fc.close(errRemainingStreamResults)
+			return fc.close(badProtocol(fc.ctx, verror.Make(errRemainingStreamResults, fc.ctx)))
 		}
 	}
 
 	// Incorporate any VTrace info that was returned.
-	vtrace.MergeResponse(fc.ctx, &fc.response.TraceResponse)
+	ivtrace.MergeResponse(fc.ctx, &fc.response.TraceResponse)
 
 	if fc.response.Error != nil {
-		if verror.Is(fc.response.Error, verror.NoAccess) && fc.dc != nil {
+		// TODO(cnicolaou): remove verror.NoAccess with verror version
+		// when ipc.Server is converted.
+		if verror.Is(fc.response.Error, old_verror.NoAccess) && fc.dc != nil {
 			// In case the error was caused by a bad discharge, we do not want to get stuck
 			// with retrying again and again with this discharge. As there is no direct way
 			// to detect it, we conservatively flush all discharges we used from the cache.
@@ -721,14 +839,16 @@
 			vlog.VI(3).Infof("Discarging %d discharges as RPC failed with %v", len(fc.discharges), fc.response.Error)
 			fc.dc.Invalidate(fc.discharges...)
 		}
-		return fc.close(verror.ConvertWithDefault(verror.Internal, fc.response.Error))
+		// TODO(cnicolaou): we turn this into a non-retryable error until
+		// we have verror on the server side.
+		return fc.close(verror.Convert(verror.Internal, fc.ctx, fc.response.Error))
 	}
 	if got, want := fc.response.NumPosResults, uint64(len(resultptrs)); got != want {
-		return fc.close(verror.BadProtocolf("ipc: server sent %d results, client expected %d (%#v)", got, want, resultptrs))
+		return fc.close(badProtocol(fc.ctx, verror.Make(errMismatchedResults, fc.ctx, got, want)))
 	}
 	for ix, r := range resultptrs {
 		if err := fc.dec.Decode(r); err != nil {
-			return fc.close(verror.BadProtocolf("ipc: result #%d decoding failed: %v", ix, err))
+			return fc.close(badProtocol(fc.ctx, verror.Make(errResultDecoding, fc.ctx, ix, err)))
 		}
 	}
 	return fc.close(nil)
@@ -736,7 +856,7 @@
 
 func (fc *flowClient) Cancel() {
 	defer vlog.LogCall()()
-	vtrace.FromContext(fc.ctx).Annotate("Cancelled")
+	ivtrace.FromContext(fc.ctx).Annotate("Cancelled")
 	fc.flow.Cancel()
 }
 
diff --git a/runtimes/google/ipc/client_test.go b/runtimes/google/ipc/client_test.go
index c4e8b8a..aa159a7 100644
--- a/runtimes/google/ipc/client_test.go
+++ b/runtimes/google/ipc/client_test.go
@@ -26,7 +26,10 @@
 }
 
 func runMountTable(t *testing.T) (*modules.Shell, func()) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	root, err := sh.Start(core.RootMTCommand, nil, testArgs()...)
 	if err != nil {
 		t.Fatalf("unexpected error for root mt: %s", err)
diff --git a/runtimes/google/ipc/context_test.go b/runtimes/google/ipc/context_test.go
index 515ee26..cdc7e0e 100644
--- a/runtimes/google/ipc/context_test.go
+++ b/runtimes/google/ipc/context_test.go
@@ -16,9 +16,13 @@
 // so we use a fake one that panics if used.  The runtime
 // implementation should not ever use the Runtime from a context.
 func testContext() context.T {
+	ctx, _ := testContextWithoutDeadline().WithTimeout(20 * time.Second)
+	return ctx
+}
+
+func testContextWithoutDeadline() context.T {
 	ctx := InternalNewContext(&runtime.PanicRuntime{})
 	ctx, _ = vtrace.WithNewRootSpan(ctx, nil, false)
-	ctx, _ = ctx.WithDeadline(time.Now().Add(20 * time.Second))
 	return ctx
 }
 
diff --git a/runtimes/google/ipc/discharges.go b/runtimes/google/ipc/discharges.go
index 40459fd..37bb62d 100644
--- a/runtimes/google/ipc/discharges.go
+++ b/runtimes/google/ipc/discharges.go
@@ -1,9 +1,11 @@
 package ipc
 
 import (
+	"fmt"
 	"sync"
 
 	"veyron.io/veyron/veyron/runtimes/google/ipc/stream/vc"
+	ivtrace "veyron.io/veyron/veyron/runtimes/google/vtrace"
 
 	"veyron.io/veyron/veyron2/context"
 	"veyron.io/veyron/veyron2/ipc"
@@ -12,24 +14,35 @@
 	"veyron.io/veyron/veyron2/security"
 	"veyron.io/veyron/veyron2/vdl/vdlutil"
 	"veyron.io/veyron/veyron2/vlog"
+	"veyron.io/veyron/veyron2/vtrace"
 )
 
 // discharger implements vc.DischargeClient.
 type dischargeClient struct {
-	c     ipc.Client
-	ctx   context.T
-	cache dischargeCache
+	c          ipc.Client
+	defaultCtx context.T
+	cache      dischargeCache
 }
 
-func InternalNewDischargeClient(streamMgr stream.Manager, ns naming.Namespace, ctx context.T, opts ...ipc.ClientOpt) (vc.DischargeClient, error) {
+// InternalNewDischargeClient creates a vc.DischargeClient that will be used to
+// fetch discharges to support blessings presented to a remote process.
+//
+// defaultCtx is the context used when none (nil) is explicitly provided to the
+// PrepareDischarges call. This typically happens when fetching discharges on
+// behalf of a server accepting connections, i.e., before any notion of the
+// "context" of an API call has been established.
+func InternalNewDischargeClient(streamMgr stream.Manager, ns naming.Namespace, defaultCtx context.T, opts ...ipc.ClientOpt) (vc.DischargeClient, error) {
+	if defaultCtx == nil {
+		return nil, fmt.Errorf("must provide a non-nil context to InternalNewDischargeClient")
+	}
 	c, err := InternalNewClient(streamMgr, ns, opts...)
 	if err != nil {
 		return nil, err
 	}
 	return &dischargeClient{
-		c:     c,
-		ctx:   ctx,
-		cache: dischargeCache{cache: make(map[string]security.Discharge)},
+		c:          c,
+		defaultCtx: defaultCtx,
+		cache:      dischargeCache{cache: make(map[string]security.Discharge)},
 	}, nil
 }
 
@@ -43,7 +56,7 @@
 // options, or requested from the discharge issuer indicated on the caveat.
 // Note that requesting a discharge is an ipc call, so one copy of this
 // function must be able to successfully terminate while another is blocked.
-func (d *dischargeClient) PrepareDischarges(forcaveats []security.ThirdPartyCaveat, impetus security.DischargeImpetus) (ret []security.Discharge) {
+func (d *dischargeClient) PrepareDischarges(ctx context.T, forcaveats []security.ThirdPartyCaveat, impetus security.DischargeImpetus) (ret []security.Discharge) {
 	if len(forcaveats) == 0 {
 		return
 	}
@@ -59,7 +72,16 @@
 
 	// Fetch discharges for caveats for which no discharges were found
 	// in the cache.
-	d.fetchDischarges(d.ctx, caveats, impetus, discharges)
+	if ctx == nil {
+		ctx = d.defaultCtx
+	}
+	if ctx != nil {
+		var span vtrace.Span
+		ctx, span = ivtrace.WithNewSpan(ctx, "Fetching Discharges")
+		defer span.Finish()
+	}
+
+	d.fetchDischarges(ctx, caveats, impetus, discharges)
 	for _, d := range discharges {
 		if d != nil {
 			ret = append(ret, d)
@@ -89,10 +111,10 @@
 				continue
 			}
 			wg.Add(1)
-			go func(i int, cav security.ThirdPartyCaveat) {
+			go func(i int, ctx context.T, cav security.ThirdPartyCaveat) {
 				defer wg.Done()
 				vlog.VI(3).Infof("Fetching discharge for %v", cav)
-				call, err := d.c.StartCall(ctx, cav.Location(), "Discharge", []interface{}{cav, filteredImpetus(cav.Requirements(), impetus)})
+				call, err := d.c.StartCall(ctx, cav.Location(), "Discharge", []interface{}{cav, filteredImpetus(cav.Requirements(), impetus)}, vc.NoDischarges{})
 				if err != nil {
 					vlog.VI(3).Infof("Discharge fetch for %v failed: %v", cav, err)
 					return
@@ -107,7 +129,7 @@
 					vlog.Errorf("fetchDischarges: server at %s sent a %T (%v) instead of a Discharge", cav.Location(), dAny, dAny)
 				}
 				discharges <- fetched{i, d}
-			}(i, caveats[i])
+			}(i, ctx, caveats[i])
 		}
 		wg.Wait()
 		close(discharges)
diff --git a/runtimes/google/ipc/flow_test.go b/runtimes/google/ipc/flow_test.go
deleted file mode 100644
index 703a44f..0000000
--- a/runtimes/google/ipc/flow_test.go
+++ /dev/null
@@ -1,167 +0,0 @@
-package ipc
-
-import (
-	"bytes"
-	"errors"
-	"fmt"
-	"testing"
-
-	"veyron.io/veyron/veyron/lib/testutil"
-	tsecurity "veyron.io/veyron/veyron/lib/testutil/security"
-
-	"veyron.io/veyron/veyron2/ipc"
-	"veyron.io/veyron/veyron2/naming"
-	"veyron.io/veyron/veyron2/security"
-	"veyron.io/veyron/veyron2/verror"
-)
-
-func init() { testutil.Init() }
-
-// newTestFlows returns the two ends of a bidirectional flow.  Each end has its
-// own bookkeeping, to allow testing of method calls.
-func newTestFlows() (*testFlow, *testFlow) {
-	var (
-		p0, p1               = tsecurity.NewPrincipal("p0"), tsecurity.NewPrincipal("p1")
-		blessing0, blessing1 = p0.BlessingStore().Default(), p1.BlessingStore().Default()
-		b0, b1               = new(bytes.Buffer), new(bytes.Buffer)
-	)
-	return &testFlow{r: b0, w: b1, p: p0, lb: blessing0, rb: blessing1}, &testFlow{r: b1, w: b0, p: p1, lb: blessing1, rb: blessing0}
-}
-
-type testFlow struct {
-	r, w          *bytes.Buffer
-	p             security.Principal
-	lb, rb        security.Blessings
-	numCloseCalls int
-	errClose      error
-}
-
-func (f *testFlow) Read(b []byte) (int, error)                    { return f.r.Read(b) }
-func (f *testFlow) Write(b []byte) (int, error)                   { return f.w.Write(b) }
-func (*testFlow) LocalEndpoint() naming.Endpoint                  { return nil }
-func (*testFlow) RemoteEndpoint() naming.Endpoint                 { return nil }
-func (f *testFlow) LocalPrincipal() security.Principal            { return f.p }
-func (f *testFlow) LocalBlessings() security.Blessings            { return f.lb }
-func (f *testFlow) RemoteBlessings() security.Blessings           { return f.rb }
-func (*testFlow) RemoteDischarges() map[string]security.Discharge { return nil }
-func (*testFlow) SetDeadline(<-chan struct{})                     {}
-func (*testFlow) IsClosed() bool                                  { return false }
-func (*testFlow) Closed() <-chan struct{}                         { return nil }
-func (*testFlow) Cancel()                                         {}
-
-func (f *testFlow) Close() error {
-	f.numCloseCalls++
-	return f.errClose
-}
-
-// testDisp implements a simple test dispatcher, that uses the newInvoker
-// factory function to create an underlying invoker on each Lookup.
-type testDisp struct {
-	newInvoker func(suffix string) ipc.Invoker
-}
-
-func (td testDisp) Lookup(suffix string) (interface{}, security.Authorizer, error) {
-	return td.newInvoker(suffix), testServerAuthorizer{}, nil
-}
-
-// closureInvoker serves a method with no user args or results:
-//    func(ipc.ServerCall) error
-type closureInvoker struct{ suffix string }
-
-func newClosureInvoker(suffix string) ipc.Invoker {
-	return closureInvoker{suffix}
-}
-
-func (closureInvoker) Prepare(method string, numArgs int) (argptrs, tags []interface{}, err error) {
-	return nil, []interface{}{security.AdminLabel}, nil
-}
-func (inv closureInvoker) Invoke(method string, call ipc.ServerCall, argptrs []interface{}) (results []interface{}, err error) {
-	if inv.suffix == "" {
-		return nil, nil
-	}
-	return nil, errors.New(inv.suffix)
-}
-func (closureInvoker) Signature(ctx ipc.ServerContext) ([]ipc.InterfaceSig, error) {
-	return nil, nil
-}
-func (closureInvoker) MethodSignature(ctx ipc.ServerContext, method string) (ipc.MethodSig, error) {
-	return ipc.MethodSig{}, nil
-}
-func (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 }
-
-func newEchoInvoker(suffix string) ipc.Invoker {
-	return echoInvoker{suffix}
-}
-
-func (echoInvoker) Prepare(method string, numArgs int) (argptrs, tags []interface{}, err error) {
-	var arg string
-	return []interface{}{&arg}, []interface{}{security.AdminLabel}, nil
-}
-func (inv echoInvoker) Invoke(method string, call ipc.ServerCall, argptrs []interface{}) (results []interface{}, err error) {
-	result := fmt.Sprintf("method:%q,suffix:%q,arg:%q", method, inv.suffix, *argptrs[0].(*string))
-	return []interface{}{result}, nil
-}
-func (echoInvoker) Signature(ctx ipc.ServerContext) ([]ipc.InterfaceSig, error) {
-	return nil, nil
-}
-func (echoInvoker) MethodSignature(ctx ipc.ServerContext, method string) (ipc.MethodSig, error) {
-	return ipc.MethodSig{}, nil
-}
-func (echoInvoker) VGlob() *ipc.GlobState {
-	return nil
-}
-
-func TestFlowClientServer(t *testing.T) {
-	type v []interface{}
-	type testcase struct {
-		suffix string
-		method string
-		args   []interface{}
-		expect []interface{}
-		err    error
-	}
-	tests := []testcase{
-		{"echo", "A", v{""}, v{`method:"A",suffix:"echo",arg:""`}, nil},
-		{"echo", "B", v{"foo"}, v{`method:"B",suffix:"echo",arg:"foo"`}, nil},
-		{"echo/abc", "C", v{""}, v{`method:"C",suffix:"echo/abc",arg:""`}, nil},
-		{"echo/abc", "D", v{"foo"}, v{`method:"D",suffix:"echo/abc",arg:"foo"`}, nil},
-	}
-	name := func(t testcase) string {
-		return fmt.Sprintf("%s.%s%v", t.suffix, t.method, t.args)
-	}
-
-	ipcServer := &server{
-		ctx:   testContext(),
-		disp:  testDisp{newEchoInvoker},
-		stats: newIPCStats(""),
-	}
-	for _, test := range tests {
-		clientFlow, serverFlow := newTestFlows()
-		client := newFlowClient(testContext(), []string{"p0"}, clientFlow, nil)
-		server := newFlowServer(serverFlow, ipcServer)
-		err := client.start(test.suffix, test.method, test.args, 0, nil)
-		if err != nil {
-			t.Errorf("%s client.start unexpected error: %v", name(test), err)
-		}
-		if err := server.serve(); !verror.Equal(err, test.err) {
-			t.Errorf("%s server.server returned %v want %v", name(test), err, test.err)
-		}
-		results := makeResultPtrs(test.expect)
-		if err := client.Finish(results...); !verror.Equal(err, test.err) {
-			t.Errorf(`%s client.Finish got error "%v", want "%v"`, name(test), err, test.err)
-		}
-		checkResultPtrs(t, name(test), results, test.expect)
-		if clientFlow.numCloseCalls != 1 {
-			t.Errorf("%s got %d client close calls, want 1", name(test), clientFlow.numCloseCalls)
-		}
-		if serverFlow.numCloseCalls != 1 {
-			t.Errorf("%s got %d server close calls, want 1", name(test), serverFlow.numCloseCalls)
-		}
-	}
-}
diff --git a/runtimes/google/ipc/full_test.go b/runtimes/google/ipc/full_test.go
index 045bd84..82199f8 100644
--- a/runtimes/google/ipc/full_test.go
+++ b/runtimes/google/ipc/full_test.go
@@ -1,10 +1,12 @@
 package ipc
 
 import (
+	"encoding/hex"
 	"errors"
 	"fmt"
 	"io"
 	"net"
+	"os"
 	"path/filepath"
 	"reflect"
 	"runtime"
@@ -18,10 +20,11 @@
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/options"
 	"veyron.io/veyron/veyron2/security"
+	"veyron.io/veyron/veyron2/services/security/access"
+	"veyron.io/veyron/veyron2/uniqueid"
 	"veyron.io/veyron/veyron2/vdl/vdlutil"
-	"veyron.io/veyron/veyron2/verror"
+	verror "veyron.io/veyron/veyron2/verror2"
 	"veyron.io/veyron/veyron2/vlog"
-	"veyron.io/veyron/veyron2/vom"
 
 	"veyron.io/veyron/veyron/lib/netstate"
 	"veyron.io/veyron/veyron/lib/testutil"
@@ -33,7 +36,7 @@
 	"veyron.io/veyron/veyron/runtimes/google/lib/publisher"
 	inaming "veyron.io/veyron/veyron/runtimes/google/naming"
 	tnaming "veyron.io/veyron/veyron/runtimes/google/testing/mocks/naming"
-	vsecurity "veyron.io/veyron/veyron/security"
+	ivtrace "veyron.io/veyron/veyron/runtimes/google/vtrace"
 )
 
 func init() {
@@ -41,7 +44,7 @@
 }
 
 var (
-	errMethod  = verror.Abortedf("server returned an error")
+	errMethod  = verror.Make(verror.Aborted, nil)
 	clock      = new(fakeClock)
 	listenSpec = ipc.ListenSpec{Protocol: "tcp", Address: "127.0.0.1:0"}
 )
@@ -150,10 +153,9 @@
 		authorizer = nil
 	case "aclAuth":
 		// Only authorize clients matching patterns "client" or "server/...".
-		authorizer = vsecurity.NewACLAuthorizer(security.ACL{In: map[security.BlessingPattern]security.LabelSet{
-			"server/...": security.LabelSet(security.AdminLabel),
-			"client":     security.LabelSet(security.AdminLabel),
-		}})
+		authorizer = &access.ACL{
+			In: []security.BlessingPattern{"client", "server/..."},
+		}
 	default:
 		authorizer = testServerAuthorizer{}
 	}
@@ -290,11 +292,17 @@
 	return
 }
 
-func matchesErrorPattern(err error, pattern string) bool {
-	if (len(pattern) == 0) != (err == nil) {
-		return false
+func matchesErrorPattern(err error, id verror.IDAction, pattern string) bool {
+	if len(pattern) > 0 && err != nil {
+		if strings.Index(err.Error(), pattern) < 0 {
+			fmt.Fprintf(os.Stderr, "got error msg: %q, expected: %q\n", err, pattern)
+		}
 	}
-	return err == nil || strings.Index(err.Error(), pattern) >= 0
+	// TODO(cnicolaou): Move this special case into verror.Is.
+	if reflect.DeepEqual(id, verror.IDAction{}) {
+		return err == nil
+	}
+	return verror.Is(err, id.ID)
 }
 
 func TestMultipleCallsToServeAndName(t *testing.T) {
@@ -365,7 +373,7 @@
 func TestRPCServerAuthorization(t *testing.T) {
 	const (
 		vcErr   = "VC handshake failed"
-		nameErr = "does not match the provided pattern"
+		nameErr = "do not match pattern"
 	)
 	var (
 		pprovider, pclient, pserver = tsecurity.NewPrincipal("root"), tsecurity.NewPrincipal(), tsecurity.NewPrincipal()
@@ -391,35 +399,39 @@
 		tests = []struct {
 			server  security.Blessings       // blessings presented by the server to the client.
 			pattern security.BlessingPattern // pattern on the server identity expected by the client.
+			errID   verror.IDAction
 			err     string
 		}{
 			// Client accepts talking to the server only if the server's blessings match the provided pattern
-			{bServer, security.AllPrincipals, ""},
-			{bServer, "root/server", ""},
-			{bServer, "root/otherserver", nameErr},
-			{bServer, "otherroot/server", nameErr},
+			{bServer, security.AllPrincipals, verror.Success, ""},
+			{bServer, "root/server", verror.Success, ""},
+			{bServer, "root/otherserver", verror.NotTrusted, nameErr},
+			{bServer, "otherroot/server", verror.NotTrusted, nameErr},
 
 			// and, if the server's blessing has third-party caveats then the server provides
 			// appropriate discharges.
-			{bServerTPValid, security.AllPrincipals, ""},
-			{bServerTPValid, "root/serverWithTPCaveats", ""},
-			{bServerTPValid, "root/otherserver", nameErr},
-			{bServerTPValid, "otherroot/server", nameErr},
+			{bServerTPValid, security.AllPrincipals, verror.Success, ""},
+			{bServerTPValid, "root/serverWithTPCaveats", verror.Success, ""},
+			{bServerTPValid, "root/otherserver", verror.NotTrusted, nameErr},
+			{bServerTPValid, "otherroot/server", verror.NotTrusted, nameErr},
 
 			// Client does not talk to a server that presents expired blessings.
-			{bServerExpired, security.AllPrincipals, vcErr},
+			{bServerExpired, security.AllPrincipals, verror.NotTrusted, vcErr},
 
 			// Client does not talk to a server that fails to provide discharges for
 			// third-party caveats on the blessings presented by it.
-			{bServerTPExpired, security.AllPrincipals, vcErr},
+			{bServerTPExpired, security.AllPrincipals, verror.NotTrusted, vcErr},
 		}
 	)
 
+	ctx := testContextWithoutDeadline()
+
 	// Start the main server.
-	dc, err := InternalNewDischargeClient(mgr, ns, testContext(), vc.LocalPrincipal{pserver})
+	dc, err := InternalNewDischargeClient(mgr, ns, ctx, vc.LocalPrincipal{pserver})
 	if err != nil {
 		t.Errorf("InternalNewDischargeClient failed: %v", err)
 	}
+
 	_, server := startServer(t, pserver, mgr, ns, serverName, testServerDisp{&testServer{}}, dc)
 	defer stopServer(t, server, ns, serverName)
 
@@ -433,7 +445,7 @@
 	// Set a blessing that the client is willing to share with servers with blessings
 	// from pprovider.
 	pclient.BlessingStore().Set(bless(pprovider, pclient, "client"), "root/...")
-	for _, test := range tests {
+	for i, test := range tests {
 		name := fmt.Sprintf("(%q@%q)", test.pattern, test.server)
 		if err := pserver.BlessingStore().SetDefault(test.server); err != nil {
 			t.Fatalf("SetDefault failed on server's BlessingStore: %v", err)
@@ -447,8 +459,10 @@
 			t.Errorf("%s: failed to create client: %v", name, err)
 			continue
 		}
-		if call, err := client.StartCall(testContext(), fmt.Sprintf("[%s]%s/suffix", test.pattern, serverName), "Method", nil); !matchesErrorPattern(err, test.err) {
-			t.Errorf(`%s: client.StartCall: got error "%v", want to match "%v"`, name, err, test.err)
+		dctx, cancel := ctx.WithTimeout(10 * time.Second)
+		call, err := client.StartCall(dctx, fmt.Sprintf("[%s]%s/suffix", test.pattern, serverName), "Method", nil)
+		if !matchesErrorPattern(err, test.errID, test.err) {
+			t.Errorf(`%d: %s: client.StartCall: got error "%v", want to match "%v"`, i, name, err, test.err)
 		} else if call != nil {
 			blessings, proof := call.RemoteBlessings()
 			if proof == nil {
@@ -458,8 +472,8 @@
 				t.Errorf("%s: %q.MatchedBy(%v) failed", name, test.pattern, blessings)
 			}
 		}
+		cancel()
 		client.Close()
-
 	}
 }
 
@@ -600,9 +614,8 @@
 		t.Fatalf(`call.Finish got error "%v"`, err)
 	}
 	// Calling Finish a second time should result in a useful error.
-	err = call.Finish(&results)
-	if got, want := err, verror.BadProtocolf("ipc: multiple calls to Finish not allowed"); got != want {
-		t.Fatalf(`call.Finish got error "%v", want "%v"`, got, want)
+	if err = call.Finish(&results); !matchesErrorPattern(err, verror.BadState, "xxx") {
+		t.Fatalf(`got "%v", want "%v"`, err, verror.BadState)
 	}
 }
 
@@ -625,23 +638,24 @@
 
 	tests := []struct {
 		granter                       ipc.Granter
+		startErrID, finishErrID       verror.IDAction
 		blessing, starterr, finisherr string
 	}{
 		{blessing: "<nil>"},
 		{granter: granter{b: bless(pclient, pserver, "blessed")}, blessing: "client/blessed"},
-		{granter: granter{err: errors.New("hell no")}, starterr: "hell no"},
-		{granter: granter{b: pclient.BlessingStore().Default()}, finisherr: "blessing granted not bound to this server"},
+		{granter: granter{err: errors.New("hell no")}, startErrID: verror.NotTrusted, starterr: "hell no"},
+		{granter: granter{b: pclient.BlessingStore().Default()}, finishErrID: verror.NoAccess, finisherr: "blessing granted not bound to this server"},
 	}
-	for _, test := range tests {
+	for i, test := range tests {
 		call, err := b.client.StartCall(testContext(), "mountpoint/server/suffix", "EchoGrantedBlessings", []interface{}{"argument"}, test.granter)
-		if !matchesErrorPattern(err, test.starterr) {
-			t.Errorf("%+v: StartCall returned error %v", test, err)
+		if !matchesErrorPattern(err, test.startErrID, test.starterr) {
+			t.Errorf("%d: %+v: StartCall returned error %v", i, test, err)
 		}
 		if err != nil {
 			continue
 		}
 		var result, blessing string
-		if err = call.Finish(&result, &blessing); !matchesErrorPattern(err, test.finisherr) {
+		if err = call.Finish(&result, &blessing); !matchesErrorPattern(err, test.finishErrID, test.finisherr) {
 			t.Errorf("%+v: Finish returned error %v", test, err)
 		}
 		if err != nil {
@@ -661,53 +675,37 @@
 	return newCaveat(tpc)
 }
 
-// dischargeImpetusServer implements the discharge service. Always fails to
-// issue a discharge, but records the impetus.
-type dischargeImpetusServer struct {
-	mu      sync.Mutex
-	impetus []security.DischargeImpetus // GUARDED_BY(mu)
+// dischargeTestServer implements the discharge service. Always fails to
+// issue a discharge, but records the impetus and traceid of the RPC call.
+type dischargeTestServer struct {
+	p       security.Principal
+	impetus []security.DischargeImpetus
+	traceid []uniqueid.ID
 }
 
-func (s *dischargeImpetusServer) Discharge(ctx ipc.ServerContext, cav vdlutil.Any, impetus security.DischargeImpetus) (vdlutil.Any, error) {
-	s.mu.Lock()
-	defer s.mu.Unlock()
+func (s *dischargeTestServer) Discharge(ctx ipc.ServerContext, cav vdlutil.Any, impetus security.DischargeImpetus) (vdlutil.Any, error) {
 	s.impetus = append(s.impetus, impetus)
+	s.traceid = append(s.traceid, ivtrace.FromContext(ctx).Trace().ID())
 	return nil, fmt.Errorf("discharges not issued")
 }
 
-// TestAndClearImpetus checks if all the recorded impetuses match want.
-// Returns an error if they do not.
-// Error or no error, it clears the set of recorded impetuses.
-func (s *dischargeImpetusServer) TestAndClearImpetus(want security.DischargeImpetus) error {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	defer func() { s.impetus = nil }()
-	for idx, imp := range s.impetus {
-		if !reflect.DeepEqual(imp, want) {
-			return fmt.Errorf("impetus %d of %d: Got [%v] want [%v]", idx, len(s.impetus), imp, want)
-		}
-	}
-	return nil
+func (s *dischargeTestServer) Release() ([]security.DischargeImpetus, []uniqueid.ID) {
+	impetus, traceid := s.impetus, s.traceid
+	s.impetus, s.traceid = nil, nil
+	return impetus, traceid
 }
 
-func names2patterns(names []string) []security.BlessingPattern {
-	ret := make([]security.BlessingPattern, len(names))
-	for idx, n := range names {
-		ret[idx] = security.BlessingPattern(n)
-	}
-	return ret
-}
-
-func TestDischargeImpetus(t *testing.T) {
+func TestDischargeImpetusAndContextPropagation(t *testing.T) {
 	var (
 		pserver     = tsecurity.NewPrincipal("server")
-		pdischarger = pserver // In general, the discharger can be a separate principal. In this test, it happens to be the server.
+		pdischarger = tsecurity.NewPrincipal("discharger")
+		pclient     = tsecurity.NewPrincipal("client")
 		sm          = imanager.InternalNew(naming.FixedRoutingID(0x555555555))
 		ns          = tnaming.NewSimpleNamespace()
 
 		mkClient = func(req security.ThirdPartyRequirements) vc.LocalPrincipal {
-			pclient := tsecurity.NewPrincipal()
-			tpc, err := security.NewPublicKeyCaveat(pdischarger.PublicKey(), "mountpoint/server/discharger", req, security.UnconstrainedUse())
+			// Setup the client so that it shares a blessing with a third-party caveat with the server.
+			tpc, err := security.NewPublicKeyCaveat(pdischarger.PublicKey(), "mountpoint/discharger", req, security.UnconstrainedUse())
 			if err != nil {
 				t.Fatalf("Failed to create ThirdPartyCaveat(%+v): %v", req, err)
 			}
@@ -715,29 +713,77 @@
 			if err != nil {
 				t.Fatal(err)
 			}
-			b, err := pclient.BlessSelf("client", cav)
+			b, err := pclient.BlessSelf("client_for_server", cav)
 			if err != nil {
 				t.Fatalf("BlessSelf failed: %v", err)
 			}
-			pclient.AddToRoots(pserver.BlessingStore().Default()) // make the client recognize the server.
 			pclient.BlessingStore().Set(b, "server")
 			return vc.LocalPrincipal{pclient}
 		}
 	)
-	server, err := InternalNewServer(testContext(), sm, ns, nil, vc.LocalPrincipal{pserver})
+	// Initialize the client principal.
+	// It trusts both the application server and the discharger.
+	pclient.AddToRoots(pserver.BlessingStore().Default())
+	pclient.AddToRoots(pdischarger.BlessingStore().Default())
+	// Share a blessing without any third-party caveats with the discharger.
+	// It could share the same blessing as generated by setupClientBlessing, but
+	// that will lead to possibly debugging confusion (since it will try to fetch
+	// a discharge to talk to the discharge service).
+	if b, err := pclient.BlessSelf("client_for_discharger"); err != nil {
+		t.Fatalf("BlessSelf failed: %v", err)
+	} else {
+		pclient.BlessingStore().Set(b, "discharger")
+	}
+
+	// Setup the discharge server.
+	var tester dischargeTestServer
+	dischargeServer, err := InternalNewServer(testContext(), sm, ns, nil, vc.LocalPrincipal{pdischarger})
 	if err != nil {
 		t.Fatal(err)
 	}
-	defer server.Stop()
-	if _, err := server.Listen(listenSpec); err != nil {
+	defer dischargeServer.Stop()
+	if _, err := dischargeServer.Listen(listenSpec); err != nil {
+		t.Fatal(err)
+	}
+	if err := dischargeServer.Serve("mountpoint/discharger", &tester, &testServerAuthorizer{}); err != nil {
 		t.Fatal(err)
 	}
 
-	var tester dischargeImpetusServer
-	if err := server.Serve("mountpoint", &tester, testServerAuthorizer{}); err != nil {
-		t.Fatal(err)
+	// DischargeClient used to fetch discharges.
+	dc, err := InternalNewDischargeClient(sm, ns, testContext(), vc.LocalPrincipal{pclient})
+	if err != nil {
+		t.Fatalf("InternalDischargeNewClient failed: %v", err)
 	}
 
+	// Setup the application server.
+	appServer, err := InternalNewServer(testContext(), sm, ns, nil, vc.LocalPrincipal{pserver})
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer appServer.Stop()
+	ep, err := appServer.Listen(listenSpec)
+	if err != nil {
+		t.Fatal(err)
+	}
+	// TODO(bjornick,cnicolaou,ashankar): This is a hack to workaround the
+	// fact that a single Listen on the "tcp" protocol followed by a call
+	// to Serve(<name>, ...) transparently creates two endpoints (one for
+	// tcp, one for websockets) and maps both to <name> via a mount.
+	// Because all endpoints to a name are tried in a parallel, this
+	// transparency makes this test hard to follow (many discharge fetch
+	// attempts are made - one for VIF authentication, one for VC
+	// authentication and one for the actual RPC - and having them be made
+	// to two different endpoints in parallel leads to a lot of
+	// non-determinism). The last plan of record known by the author of
+	// this comment was to stop this sly creation of two endpoints and
+	// require that they be done explicitly. When that happens, this hack
+	// can go away, but till then, this workaround allows the test to be
+	// more predictable by ensuring there is only one VIF/VC/Flow to the
+	// server.
+	object := naming.JoinAddressName(ep.String(), "object") // instead of "mountpoint/object"
+	if err := appServer.Serve("mountpoint/object", &testServer{}, &testServerAuthorizer{}); err != nil {
+		t.Fatal(err)
+	}
 	tests := []struct {
 		Requirements security.ThirdPartyRequirements
 		Impetus      security.DischargeImpetus
@@ -756,24 +802,52 @@
 		},
 	}
 
-	for _, test := range tests {
+	for testidx, test := range tests {
 		pclient := mkClient(test.Requirements)
-		dc, err := InternalNewDischargeClient(sm, ns, testContext(), pclient)
-		if err != nil {
-			t.Fatalf("InternalDischargeNewClient failed: %v", err)
-		}
 		client, err := InternalNewClient(sm, ns, pclient, dc)
 		if err != nil {
 			t.Fatalf("InternalNewClient(%+v) failed: %v", test.Requirements, err)
 		}
 		defer client.Close()
+		ctx := testContext()
+		tid := ivtrace.FromContext(ctx).Trace().ID()
 		// StartCall should fetch the discharge, do not worry about finishing the RPC - do not care about that for this test.
-		if _, err := client.StartCall(testContext(), "mountpoint/object", "Method", []interface{}{"argument"}); err != nil {
+		if _, err := client.StartCall(ctx, object, "Method", []interface{}{"argument"}); err != nil {
 			t.Errorf("StartCall(%+v) failed: %v", test.Requirements, err)
 			continue
 		}
-		if err := tester.TestAndClearImpetus(test.Impetus); err != nil {
-			t.Errorf("Test %+v: %v", test.Requirements, err)
+		impetus, traceid := tester.Release()
+		// There should have been 2 or 3 attempts to fetch a discharge
+		// (since the discharge service doesn't actually issue a valid
+		// discharge, there is no re-usable discharge between these attempts):
+		// (1) When creating a VIF with the server hosting the remote object.
+		//     (This will happen only for the first test, where the stream.Manager
+		//     authenticates at the VIF level for the very first time).
+		// (2) When creating a VC with the server hosting the remote object.
+		// (3) When making the RPC to the remote object.
+		num := 3
+		if testidx > 0 {
+			num = 2
+		}
+		if want := num; len(impetus) != want || len(traceid) != want {
+			t.Errorf("Test %+v: Got (%d, %d) (#impetus, #traceid), wanted %d each", test.Requirements, len(impetus), len(traceid), want)
+			continue
+		}
+		// VC creation does not have any "impetus", it is established without
+		// knowledge of the context of the RPC. So ignore that.
+		//
+		// TODO(ashankar): Should the impetus of the RPC that initiated the
+		// VIF/VC creation be propagated?
+		if got, want := impetus[len(impetus)-1], test.Impetus; !reflect.DeepEqual(got, want) {
+			t.Errorf("Test %+v: Got impetus %v, want %v", test.Requirements, got, want)
+		}
+		// But the context used for all of this should be the same
+		// (thereby allowing debug traces to link VIF/VC creation with
+		// the RPC that initiated them).
+		for idx, got := range traceid {
+			if !reflect.DeepEqual(got, tid) {
+				t.Errorf("Test %+v: %d - Got trace id %q, want %q", test.Requirements, idx, hex.EncodeToString(got[:]), hex.EncodeToString(tid[:]))
+			}
 		}
 	}
 }
@@ -911,8 +985,8 @@
 			t.Errorf(`%s call.Finish got error: "%v", wanted the RPC to succeed`, name, err)
 		} else if err == nil && !test.authorized {
 			t.Errorf("%s call.Finish succeeded, expected authorization failure", name)
-		} else if !test.authorized && !verror.Is(err, verror.NoAccess) {
-			t.Errorf("%s. call.Finish returned error %v(%v), wanted %v", name, verror.Convert(err).ErrorID(), err, verror.NoAccess)
+		} else if !test.authorized && !verror.Is(err, verror.NoAccess.ID) {
+			t.Errorf("%s. call.Finish returned error %v(%v), wanted %v", name, verror.Convert(verror.NoAccess, nil, err).ErrorID(), err, verror.NoAccess)
 		}
 	}
 }
@@ -940,17 +1014,17 @@
 	if b.client, err = InternalNewClient(b.sm, b.ns, vc.LocalPrincipal{pclient}, dc); err != nil {
 		t.Fatalf("InternalNewClient failed: %v", err)
 	}
-	call := func() error {
+	call := func() verror.E {
 		call, err := b.client.StartCall(testContext(), "mountpoint/server/aclAuth", "Echo", []interface{}{"batman"})
 		if err != nil {
-			return fmt.Errorf("client.StartCall failed: %v", err)
+			return err.(verror.E) //fmt.Errorf("client.StartCall failed: %v", err)
 		}
 		var got string
 		if err := call.Finish(&got); err != nil {
-			return fmt.Errorf("client.Finish failed: %v", err)
+			return err.(verror.E) //fmt.Errorf("client.Finish failed: %v", err)
 		}
 		if want := `method:"Echo",suffix:"aclAuth",arg:"batman"`; got != want {
-			return fmt.Errorf("Got [%v] want [%v]", got, want)
+			return verror.Convert(verror.BadArg, nil, fmt.Errorf("Got [%v] want [%v]", got, want))
 		}
 		return nil
 	}
@@ -961,7 +1035,7 @@
 	}
 	// Advance virtual clock, which will invalidate the discharge
 	clock.Advance(1)
-	if err, want := call(), "not authorized"; !matchesErrorPattern(err, want) {
+	if err, want := call(), "not authorized"; !matchesErrorPattern(err, verror.NoAccess, want) {
 		t.Errorf("Got error [%v] wanted to match pattern %q", err, want)
 	}
 	// But retrying will succeed since the discharge should be purged from cache and refreshed
@@ -1218,7 +1292,7 @@
 		t.Fatalf("InternalNewClient failed: %v", err)
 	}
 	// When using VCSecurityNone, all authorization checks should be skipped, so
-	// unauthorized methods shoudl be callable.
+	// unauthorized methods should be callable.
 	call, err := client.StartCall(testContext(), "mp/server", "Unauthorized", nil)
 	if err != nil {
 		t.Fatalf("client.StartCall failed: %v", err)
@@ -1245,8 +1319,8 @@
 	if call != nil {
 		t.Errorf("Expected nil interface got: %#v", call)
 	}
-	if !verror.Is(err, verror.BadArg) {
-		t.Errorf("Expected a BadArg error, got: %s", err.Error())
+	if !verror.Is(err, verror.BadArg.ID) {
+		t.Errorf("Expected an BadArg error, got: %s", err.Error())
 	}
 }
 
@@ -1362,7 +1436,176 @@
 	}
 }
 
+type mockDischarger struct {
+	mu     sync.Mutex
+	called bool
+}
+
+func (m *mockDischarger) Discharge(ctx ipc.ServerContext, caveatAny vdlutil.Any, _ security.DischargeImpetus) (vdlutil.Any, error) {
+	m.mu.Lock()
+	m.called = true
+	m.mu.Unlock()
+	caveat, ok := caveatAny.(security.ThirdPartyCaveat)
+	if !ok {
+		return nil, fmt.Errorf("type %T does not implement security.ThirdPartyCaveat", caveatAny)
+	}
+	return ctx.LocalPrincipal().MintDischarge(caveat, security.UnconstrainedUse())
+}
+
+func TestNoDischargesOpt(t *testing.T) {
+	var (
+		pdischarger = tsecurity.NewPrincipal("discharger")
+		pserver     = tsecurity.NewPrincipal("server")
+		pclient     = tsecurity.NewPrincipal("client")
+	)
+	// Make the client recognize all server blessings
+	if err := pclient.AddToRoots(pserver.BlessingStore().Default()); err != nil {
+		t.Fatal(err)
+	}
+	if err := pclient.AddToRoots(pdischarger.BlessingStore().Default()); err != nil {
+		t.Fatal(err)
+	}
+
+	// Bless the client with a ThirdPartyCaveat.
+	tpcav := mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/discharger", mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
+	blessings, err := pserver.Bless(pclient.PublicKey(), pserver.BlessingStore().Default(), "tpcav", tpcav)
+	if err != nil {
+		t.Fatalf("failed to create Blessings: %v", err)
+	}
+	if _, err = pclient.BlessingStore().Set(blessings, "server"); err != nil {
+		t.Fatalf("failed to set blessings: %v", err)
+	}
+
+	ns := tnaming.NewSimpleNamespace()
+	runServer := func(name string, obj interface{}, principal security.Principal) stream.Manager {
+		rid, err := naming.NewRoutingID()
+		if err != nil {
+			t.Fatal(err)
+		}
+		sm := imanager.InternalNew(rid)
+		server, err := InternalNewServer(testContext(), sm, ns, nil, vc.LocalPrincipal{principal})
+		if err != nil {
+			t.Fatal(err)
+		}
+		if _, err := server.Listen(listenSpec); err != nil {
+			t.Fatal(err)
+		}
+		if err := server.Serve(name, obj, acceptAllAuthorizer{}); err != nil {
+			t.Fatal(err)
+		}
+		return sm
+	}
+
+	// Setup the disharger and test server.
+	discharger := &mockDischarger{}
+	defer runServer("mountpoint/discharger", discharger, pdischarger).Shutdown()
+	defer runServer("mountpoint/testServer", &testServer{}, pserver).Shutdown()
+
+	runClient := func(noDischarges bool) {
+		rid, err := naming.NewRoutingID()
+		if err != nil {
+			t.Fatal(err)
+		}
+		smc := imanager.InternalNew(rid)
+		defer smc.Shutdown()
+		dc, err := InternalNewDischargeClient(smc, ns, testContext())
+		if err != nil {
+			t.Fatal(err)
+		}
+		client, err := InternalNewClient(smc, ns, vc.LocalPrincipal{pclient}, dc)
+		if err != nil {
+			t.Fatalf("failed to create client: %v", err)
+		}
+		defer client.Close()
+		var opts []ipc.CallOpt
+		if noDischarges {
+			opts = append(opts, vc.NoDischarges{})
+		}
+		if _, err = client.StartCall(testContext(), "mountpoint/testServer", "Closure", nil, opts...); err != nil {
+			t.Fatalf("failed to StartCall: %v", err)
+		}
+	}
+
+	// Test that when the NoDischarges option is set, mockDischarger does not get called.
+	if runClient(true); discharger.called {
+		t.Errorf("did not expect discharger to be called")
+	}
+	discharger.called = false
+	// Test that when the Nodischarges option is not set, mockDischarger does get called.
+	if runClient(false); !discharger.called {
+		t.Errorf("expected discharger to be called")
+	}
+}
+
+func TestNoImplicitDischargeFetching(t *testing.T) {
+	// This test ensures that discharge clients only fetch discharges for the specified tp caveats and not its own.
+	var (
+		pdischarger1     = tsecurity.NewPrincipal("discharger1")
+		pdischarger2     = tsecurity.NewPrincipal("discharger2")
+		pdischargeClient = tsecurity.NewPrincipal("dischargeClient")
+	)
+
+	// Bless the client with a ThirdPartyCaveat from discharger1.
+	tpcav1 := mkThirdPartyCaveat(pdischarger1.PublicKey(), "mountpoint/discharger1", mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
+	blessings, err := pdischarger1.Bless(pdischargeClient.PublicKey(), pdischarger1.BlessingStore().Default(), "tpcav1", tpcav1)
+	if err != nil {
+		t.Fatalf("failed to create Blessings: %v", err)
+	}
+	if err = pdischargeClient.BlessingStore().SetDefault(blessings); err != nil {
+		t.Fatalf("failed to set blessings: %v", err)
+	}
+
+	ns := tnaming.NewSimpleNamespace()
+	runServer := func(name string, obj interface{}, principal security.Principal) stream.Manager {
+		rid, err := naming.NewRoutingID()
+		if err != nil {
+			t.Fatal(err)
+		}
+		sm := imanager.InternalNew(rid)
+		server, err := InternalNewServer(testContext(), sm, ns, nil, vc.LocalPrincipal{principal})
+		if err != nil {
+			t.Fatal(err)
+		}
+		if _, err := server.Listen(listenSpec); err != nil {
+			t.Fatal(err)
+		}
+		if err := server.Serve(name, obj, acceptAllAuthorizer{}); err != nil {
+			t.Fatal(err)
+		}
+		return sm
+	}
+
+	// Setup the disharger and test server.
+	discharger1 := &mockDischarger{}
+	discharger2 := &mockDischarger{}
+	defer runServer("mountpoint/discharger1", discharger1, pdischarger1).Shutdown()
+	defer runServer("mountpoint/discharger2", discharger2, pdischarger2).Shutdown()
+
+	rid, err := naming.NewRoutingID()
+	if err != nil {
+		t.Fatal(err)
+	}
+	sm := imanager.InternalNew(rid)
+	dc, err := InternalNewDischargeClient(sm, ns, testContext(), vc.LocalPrincipal{pdischargeClient})
+	if err != nil {
+		t.Fatal(err)
+	}
+	tpcav2, err := security.NewPublicKeyCaveat(pdischarger2.PublicKey(), "mountpoint/discharger2", security.ThirdPartyRequirements{}, mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
+	if err != nil {
+		t.Error(err)
+	}
+	dc.PrepareDischarges(testContext(), []security.ThirdPartyCaveat{tpcav2}, security.DischargeImpetus{})
+
+	// Ensure that discharger1 was not called and discharger2 was called.
+	if discharger1.called {
+		t.Errorf("discharge for caveat on discharge client should not have been fetched.")
+	}
+	if !discharger2.called {
+		t.Errorf("discharge for caveat passed to PrepareDischarges should have been fetched.")
+	}
+}
+
 func init() {
 	testutil.Init()
-	vom.Register(fakeTimeCaveat(0))
+	vdlutil.Register(fakeTimeCaveat(0))
 }
diff --git a/runtimes/google/ipc/glob.go b/runtimes/google/ipc/glob.go
index 9dba1e4..33c897c 100644
--- a/runtimes/google/ipc/glob.go
+++ b/runtimes/google/ipc/glob.go
@@ -8,6 +8,7 @@
 	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/security"
+	"veyron.io/veyron/veyron2/services/security/access"
 	"veyron.io/veyron/veyron2/verror"
 	"veyron.io/veyron/veyron2/vlog"
 
@@ -145,23 +146,23 @@
 // response if the double underscore is explicitly part of the pattern, e.g.
 // "".Glob("__*/*"), or "".Glob("__debug/...").
 //
-// Service objects may choose to implement either VAllGlobber or
-// VChildrenGlobber. VAllGlobber is more flexible, but VChildrenGlobber is
-// simpler to implement and less prone to errors.
+// Service objects may choose to implement either AllGlobber or ChildrenGlobber.
+// AllGlobber is more flexible, but ChildrenGlobber is simpler to implement and
+// less prone to errors.
 //
-// If objects implement VAllGlobber, it must be able to handle recursive pattern
+// If objects implement AllGlobber, it must be able to handle recursive pattern
 // for the entire namespace below the receiver object, i.e. "a/b".Glob("...")
 // must return the name of all the objects under "a/b".
 //
-// If they implement VChildrenGlobber, it provides a list of the receiver's
+// If they implement ChildrenGlobber, it provides a list of the receiver's
 // immediate children names, or a non-nil error if the receiver doesn't exist.
 //
 // globInternal constructs the Glob response by internally accessing the
-// VAllGlobber or VChildrenGlobber interface of objects as many times as needed.
+// AllGlobber or ChildrenGlobber interface of objects as many times as needed.
 //
 // Before accessing an object, globInternal ensures that the requester is
-// authorized to access it. Internal objects require either security.DebugLabel
-// or security.MonitoringLabel. Service objects require security.ResolveLabel.
+// authorized to access it. Internal objects require access.Debug. Service
+// objects require access.Resolve.
 type globInternal struct {
 	dispNormal   ipc.Dispatcher
 	dispReserved ipc.Dispatcher
@@ -182,75 +183,95 @@
 	}
 	disp := i.dispNormal
 	call.M.Method = ipc.GlobMethod
-	call.M.MethodTags = []interface{}{security.ResolveLabel}
+	call.M.MethodTags = []interface{}{access.Resolve}
 	if naming.IsReserved(i.receiver) || (i.receiver == "" && naming.IsReserved(pattern)) {
 		disp = i.dispReserved
-		call.M.MethodTags = []interface{}{security.DebugLabel | security.MonitoringLabel}
+		call.M.MethodTags = []interface{}{access.Debug}
 	}
 	if disp == nil {
 		return verror.NoExistf("ipc: Glob is not implemented by %q", i.receiver)
 	}
-	return i.globStep(call, disp, "", g, 0)
-}
 
-func (i *globInternal) globStep(call *mutableCall, disp ipc.Dispatcher, name string, g *glob.Glob, depth int) error {
-	call.M.Suffix = naming.Join(i.receiver, name)
-	if depth > maxRecursiveGlobDepth {
-		err := verror.Internalf("ipc: Glob exceeded its recursion limit (%d): %q", maxRecursiveGlobDepth, call.Suffix())
-		vlog.Error(err)
-		return err
+	type gState struct {
+		name  string
+		glob  *glob.Glob
+		depth int
 	}
-	obj, auth, err := disp.Lookup(call.Suffix())
-	switch {
-	case err != nil:
-		return err
-	case obj == nil:
-		return verror.NoExistf("ipc: invoker not found for %q.%s", call.Suffix(), ipc.GlobMethod)
-	}
+	queue := []gState{gState{glob: g}}
 
-	// Verify that that requester is authorized for the current object.
-	if err := authorize(call, auth); err != nil {
-		return err
-	}
-
-	// If the object implements both VAllGlobber and VChildrenGlobber, we'll
-	// use VAllGlobber.
-	gs := objectToInvoker(obj).VGlob()
-	if gs == nil || (gs.VAllGlobber == nil && gs.VChildrenGlobber == nil) {
-		if g.Len() == 0 {
-			call.Send(naming.VDLMountEntry{Name: name})
+	for len(queue) != 0 {
+		select {
+		case <-call.Done():
+			// RPC timed out or was canceled.
+			return nil
+		default:
 		}
-		return nil
-	}
-	if gs.VAllGlobber != nil {
-		vlog.VI(3).Infof("ipc Glob: %q implements VAllGlobber", call.Suffix())
-		childCtx := &ipc.GlobContextStub{&localServerCall{call, name}}
-		return gs.VAllGlobber.Glob(childCtx, g.String())
-	}
-	vlog.VI(3).Infof("ipc Glob: %q implements VChildrenGlobber", call.Suffix())
-	children, err := gs.VChildrenGlobber.VGlobChildren()
-	if err != nil {
-		return nil
-	}
-	if g.Len() == 0 {
-		call.Send(naming.VDLMountEntry{Name: name})
-	}
-	if g.Finished() {
-		return nil
-	}
-	if g.Len() == 0 {
-		// This is a recursive pattern. Make sure we don't recurse forever.
-		depth++
-	}
-	for _, child := range children {
-		if len(child) == 0 || strings.Contains(child, "/") {
-			vlog.Errorf("ipc: %q.VGlobChildren() returned an invalid child name: %q", call.Suffix(), child)
+		state := queue[0]
+		queue = queue[1:]
+
+		call.M.Suffix = naming.Join(i.receiver, state.name)
+		if state.depth > maxRecursiveGlobDepth {
+			vlog.Errorf("ipc Glob: exceeded recursion limit (%d): %q", maxRecursiveGlobDepth, call.Suffix())
 			continue
 		}
-		if ok, _, left := g.MatchInitialSegment(child); ok {
-			next := naming.Join(name, child)
-			if err := i.globStep(call, disp, next, left, depth); err != nil {
-				vlog.VI(1).Infof("ipc Glob: globStep(%q, %q): %v", next, left, err)
+		obj, auth, err := disp.Lookup(call.Suffix())
+		if err != nil {
+			vlog.VI(3).Infof("ipc Glob: Lookup failed for %q: %v", call.Suffix(), err)
+			continue
+		}
+		if obj == nil {
+			vlog.VI(3).Infof("ipc Glob: object not found for %q", call.Suffix())
+			continue
+		}
+
+		// Verify that that requester is authorized for the current object.
+		if err := authorize(call, auth); err != nil {
+			vlog.VI(3).Infof("ipc Glob: client is not authorized for %q: %v", call.Suffix(), err)
+			continue
+		}
+
+		// If the object implements both AllGlobber and ChildrenGlobber, we'll
+		// use AllGlobber.
+		gs := objectToInvoker(obj).VGlob()
+		if gs == nil || (gs.AllGlobber == nil && gs.ChildrenGlobber == nil) {
+			if state.glob.Len() == 0 {
+				call.Send(naming.VDLMountEntry{Name: state.name})
+			}
+			continue
+		}
+		if gs.AllGlobber != nil {
+			vlog.VI(3).Infof("ipc Glob: %q implements AllGlobber", call.Suffix())
+			childCtx := &ipc.GlobContextStub{&localServerCall{call, state.name}}
+			gs.AllGlobber.Glob(childCtx, state.glob.String())
+			continue
+		}
+		vlog.VI(3).Infof("ipc Glob: %q implements ChildrenGlobber", call.Suffix())
+		children, err := gs.ChildrenGlobber.GlobChildren__()
+		// The requested object doesn't exist.
+		if err != nil {
+			continue
+		}
+		// The glob pattern matches the current object.
+		if state.glob.Len() == 0 {
+			call.Send(naming.VDLMountEntry{Name: state.name})
+		}
+		// The current object has no children.
+		if children == nil {
+			continue
+		}
+		depth := state.depth
+		// This is a recursive pattern. Make sure we don't recurse forever.
+		if state.glob.Len() == 0 {
+			depth++
+		}
+		for child := range children {
+			if len(child) == 0 || strings.Contains(child, "/") {
+				vlog.Errorf("ipc Glob: %q.GlobChildren__() sent an invalid child name: %q", call.Suffix(), child)
+				continue
+			}
+			if ok, _, left := state.glob.MatchInitialSegment(child); ok {
+				next := naming.Join(state.name, child)
+				queue = append(queue, gState{next, left, depth})
 			}
 		}
 	}
@@ -308,14 +329,11 @@
 	}
 }
 
-func (c *mutableContext) Timestamp() time.Time      { return c.M.Timestamp }
-func (c *mutableContext) Method() string            { return c.M.Method }
-func (c *mutableContext) MethodTags() []interface{} { return c.M.MethodTags }
-func (c *mutableContext) Name() string              { return c.M.Suffix }
-func (c *mutableContext) Suffix() string            { return c.M.Suffix }
-func (c *mutableContext) Label() security.Label {
-	return security.LabelFromMethodTags(c.M.MethodTags)
-}
+func (c *mutableContext) Timestamp() time.Time                            { return c.M.Timestamp }
+func (c *mutableContext) Method() string                                  { return c.M.Method }
+func (c *mutableContext) MethodTags() []interface{}                       { return c.M.MethodTags }
+func (c *mutableContext) Name() string                                    { return c.M.Suffix }
+func (c *mutableContext) Suffix() string                                  { return c.M.Suffix }
 func (c *mutableContext) LocalPrincipal() security.Principal              { return c.M.LocalPrincipal }
 func (c *mutableContext) LocalBlessings() security.Blessings              { return c.M.LocalBlessings }
 func (c *mutableContext) RemoteBlessings() security.Blessings             { return c.M.RemoteBlessings }
diff --git a/runtimes/google/ipc/glob_test.go b/runtimes/google/ipc/glob_test.go
index 5d497e8..79e9859 100644
--- a/runtimes/google/ipc/glob_test.go
+++ b/runtimes/google/ipc/glob_test.go
@@ -34,7 +34,10 @@
 }
 
 func TestGlob(t *testing.T) {
-	runtime := rt.Init()
+	runtime, err := rt.New()
+	if err != nil {
+		panic(err)
+	}
 	defer runtime.Cleanup()
 
 	namespace := []string{
@@ -158,7 +161,7 @@
 	}
 	for _, tc := range testcases {
 		name := naming.JoinAddressName(ep, tc.name)
-		results, err := testutil.GlobName(name, tc.pattern)
+		results, err := testutil.GlobName(runtime.NewContext(), name, tc.pattern)
 		if err != nil {
 			t.Errorf("unexpected Glob error for (%q, %q): %v", tc.name, tc.pattern, err)
 			continue
@@ -177,7 +180,7 @@
 	elems := strings.Split(suffix, "/")
 	if len(elems) != 0 && elems[0] == "muah" {
 		// Infinite space. Each node has one child named "ha".
-		return ipc.VChildrenGlobberInvoker("ha"), nil, nil
+		return ipc.ChildrenGlobberInvoker("ha"), nil, nil
 
 	}
 	if len(elems) != 0 && elems[0] == "leaf" {
@@ -226,18 +229,17 @@
 	suffix []string
 }
 
-func (o *vChildrenObject) VGlobChildren() ([]string, error) {
+func (o *vChildrenObject) GlobChildren__() (<-chan string, error) {
 	n := o.n.find(o.suffix, false)
 	if n == nil {
 		return nil, fmt.Errorf("object does not exist")
 	}
-	children := make([]string, len(n.children))
-	index := 0
+	ch := make(chan string, len(n.children))
 	for child, _ := range n.children {
-		children[index] = child
-		index++
+		ch <- child
 	}
-	return children, nil
+	close(ch)
+	return ch, nil
 }
 
 type node struct {
diff --git a/runtimes/google/ipc/server.go b/runtimes/google/ipc/server.go
index abd5986..ca392b5 100644
--- a/runtimes/google/ipc/server.go
+++ b/runtimes/google/ipc/server.go
@@ -16,9 +16,11 @@
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/options"
 	"veyron.io/veyron/veyron2/security"
+	"veyron.io/veyron/veyron2/services/security/access"
 	"veyron.io/veyron/veyron2/verror"
 	"veyron.io/veyron/veyron2/vlog"
 	"veyron.io/veyron/veyron2/vom"
+	"veyron.io/veyron/veyron2/vom2"
 	"veyron.io/veyron/veyron2/vtrace"
 
 	"veyron.io/veyron/veyron/lib/netstate"
@@ -35,18 +37,19 @@
 
 type server struct {
 	sync.Mutex
-	ctx              context.T                         // context used by the server to make internal RPCs.
-	streamMgr        stream.Manager                    // stream manager to listen for new flows.
-	publisher        publisher.Publisher               // publisher to publish mounttable mounts.
-	listenerOpts     []stream.ListenerOpt              // listener opts passed to Listen.
-	listeners        map[stream.Listener]*dhcpListener // listeners created by Listen.
-	disp             ipc.Dispatcher                    // dispatcher to serve RPCs
-	dispReserved     ipc.Dispatcher                    // dispatcher for reserved methods
-	active           sync.WaitGroup                    // active goroutines we've spawned.
-	stopped          bool                              // whether the server has been stopped.
-	stoppedChan      chan struct{}                     // closed when the server has been stopped.
-	ns               naming.Namespace
-	servesMountTable bool
+	ctx                context.T                         // context used by the server to make internal RPCs.
+	streamMgr          stream.Manager                    // stream manager to listen for new flows.
+	publisher          publisher.Publisher               // publisher to publish mounttable mounts.
+	listenerOpts       []stream.ListenerOpt              // listener opts passed to Listen.
+	listeners          map[stream.Listener]*dhcpListener // listeners created by Listen.
+	disp               ipc.Dispatcher                    // dispatcher to serve RPCs
+	dispReserved       ipc.Dispatcher                    // dispatcher for reserved methods
+	active             sync.WaitGroup                    // active goroutines we've spawned.
+	stopped            bool                              // whether the server has been stopped.
+	stoppedChan        chan struct{}                     // closed when the server has been stopped.
+	preferredProtocols []string                          // protocols to use when resolving proxy name to endpoint.
+	ns                 naming.Namespace
+	servesMountTable   bool
 	// 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.
@@ -68,6 +71,12 @@
 	ch        chan config.Setting // channel to receive settings over
 }
 
+// This option is used to sort and filter the endpoints when resolving the
+// proxy name from a mounttable.
+type PreferredServerResolveProtocols []string
+
+func (PreferredServerResolveProtocols) IPCServerOpt() {}
+
 func InternalNewServer(ctx context.T, streamMgr stream.Manager, ns naming.Namespace, store *ivtrace.Store, opts ...ipc.ServerOpt) (ipc.Server, error) {
 	ctx, _ = ivtrace.WithNewSpan(ctx, "NewServer")
 	statsPrefix := naming.Join("ipc", "server", "routing-id", streamMgr.RoutingID().String())
@@ -100,6 +109,8 @@
 			s.servesMountTable = bool(opt)
 		case options.ReservedNameDispatcher:
 			s.dispReserved = opt.Dispatcher
+		case PreferredServerResolveProtocols:
+			s.preferredProtocols = []string(opt)
 		}
 	}
 	blessingsStatsName := naming.Join(statsPrefix, "security", "blessings")
@@ -140,7 +151,12 @@
 	} else {
 		names = append(names, address)
 	}
-	for _, n := range names {
+	// An empty set of protocols means all protocols...
+	ordered, err := filterAndOrderServers(names, s.preferredProtocols)
+	if err != nil {
+		return "", err
+	}
+	for _, n := range ordered {
 		address, suffix := naming.SplitAddressName(n)
 		if suffix != "" {
 			continue
@@ -417,12 +433,17 @@
 		}
 		calls.Add(1)
 		go func(flow stream.Flow) {
-			if err := newFlowServer(flow, s).serve(); err != nil {
+			defer calls.Done()
+			fs, err := newFlowServer(flow, s)
+			if err != nil {
+				vlog.Errorf("newFlowServer on %v failed: %v", ln, err)
+				return
+			}
+			if err := fs.serve(); err != nil {
 				// TODO(caprita): Logging errors here is too spammy. For example, "not
 				// authorized" errors shouldn't be logged as server errors.
 				vlog.Errorf("Flow serve on %v failed: %v", ln, err)
 			}
-			calls.Done()
 		}(flow)
 	}
 }
@@ -612,14 +633,23 @@
 	return firstErr
 }
 
+// TODO(toddw): Remove these interfaces after the vom2 transition.
+type vomEncoder interface {
+	Encode(v interface{}) error
+}
+
+type vomDecoder interface {
+	Decode(v interface{}) error
+}
+
 // flowServer implements the RPC server-side protocol for a single RPC, over a
 // flow that's already connected to the client.
 type flowServer struct {
 	context.T
 	server *server        // ipc.Server that this flow server belongs to
 	disp   ipc.Dispatcher // ipc.Dispatcher that will serve RPCs on this flow
-	dec    *vom.Decoder   // to decode requests and args from the client
-	enc    *vom.Encoder   // to encode responses and results to the client
+	dec    vomDecoder     // to decode requests and args from the client
+	enc    vomEncoder     // to encode responses and results to the client
 	flow   stream.Flow    // underlying flow
 
 	// Fields filled in during the server invocation.
@@ -634,21 +664,33 @@
 
 var _ ipc.Stream = (*flowServer)(nil)
 
-func newFlowServer(flow stream.Flow, server *server) *flowServer {
+func newFlowServer(flow stream.Flow, server *server) (*flowServer, error) {
 	server.Lock()
 	disp := server.disp
 	server.Unlock()
 
-	return &flowServer{
-		T:      server.ctx,
-		server: server,
-		disp:   disp,
-		// TODO(toddw): Support different codecs
-		dec:        vom.NewDecoder(flow),
-		enc:        vom.NewEncoder(flow),
+	fs := &flowServer{
+		T:          server.ctx,
+		server:     server,
+		disp:       disp,
 		flow:       flow,
 		discharges: make(map[string]security.Discharge),
 	}
+	if vom2.IsEnabled() {
+		var err error
+		if fs.dec, err = vom2.NewDecoder(flow); err != nil {
+			flow.Close()
+			return nil, err
+		}
+		if fs.enc, err = vom2.NewBinaryEncoder(flow); err != nil {
+			flow.Close()
+			return nil, err
+		}
+	} else {
+		fs.dec = vom.NewDecoder(flow)
+		fs.enc = vom.NewEncoder(flow)
+	}
+	return fs, nil
 }
 
 // Vom does not encode untyped nils.
@@ -662,7 +704,7 @@
 // - Server methods return 0 or more results
 // - Any values returned by the server that have an interface type are either
 //   non-nil or of type error.
-func result2vom(res interface{}) vom.Value {
+func vomErrorHack(res interface{}) vom.Value {
 	v := vom.ValueOf(res)
 	if !v.IsValid() {
 		// Untyped nils are assumed to be nil-errors.
@@ -678,6 +720,22 @@
 	return v
 }
 
+// TODO(toddw): Remove this function and encodeValueHack after the vom2 transition.
+func vom2ErrorHack(res interface{}) interface{} {
+	if err, ok := res.(error); ok {
+		return &err
+	}
+	return res
+}
+
+// TODO(toddw): Remove this function and vom2ErrorHack after the vom2 transition.
+func (fs *flowServer) encodeValueHack(res interface{}) error {
+	if vom2.IsEnabled() {
+		return fs.enc.Encode(vom2ErrorHack(res))
+	}
+	return fs.enc.(*vom.Encoder).EncodeValue(vomErrorHack(res))
+}
+
 func (fs *flowServer) serve() error {
 	defer fs.flow.Close()
 
@@ -704,7 +762,7 @@
 		return response.Error
 	}
 	for ix, res := range results {
-		if err := fs.enc.EncodeValue(result2vom(res)); err != nil {
+		if err := fs.encodeValueHack(res); err != nil {
 			return verror.BadProtocolf("ipc: result #%d [%T=%v] encoding failed: %v", ix, res, res, err)
 		}
 	}
@@ -796,7 +854,7 @@
 		return nil, verr
 	}
 	// Check if the caller is permitted to view debug information.
-	// TODO(mattr): Is DebugLabel the right thing to check?
+	// TODO(mattr): Is access.Debug the right thing to check?
 	fs.allowDebug = authorize(debugContext{fs}, auth) == nil
 	// Invoke the method.
 	results, err := invoker.Invoke(fs.method, fs, argptrs)
@@ -873,7 +931,7 @@
 	// this - should servers be able to assume that a blessing is something that
 	// does not have the authorizations that the server's own identity has?
 	if blessings != nil && !reflect.DeepEqual(blessings.PublicKey(), fs.flow.LocalPrincipal().PublicKey()) {
-		return verror.BadProtocolf("ipc: blessing granted not bound to this server(%v vs %v)", blessings.PublicKey(), fs.flow.LocalPrincipal().PublicKey())
+		return verror.NoAccessf("ipc: blessing granted not bound to this server(%v vs %v)", blessings.PublicKey(), fs.flow.LocalPrincipal().PublicKey())
 	}
 	// Receive third party caveat discharges the client sent
 	for i := uint64(0); i < req.NumDischarges; i++ {
@@ -909,12 +967,14 @@
 }
 
 // debugContext is a context which wraps another context but always returns
-// the debug label.
+// the debug tag.
 type debugContext struct {
 	security.Context
 }
 
-func (debugContext) Label() security.Label { return security.DebugLabel }
+func (debugContext) MethodTags() []interface{} {
+	return []interface{}{access.Debug}
+}
 
 // Send implements the ipc.Stream method.
 func (fs *flowServer) Send(item interface{}) error {
@@ -973,10 +1033,6 @@
 	//nologcall
 	return fs.suffix
 }
-func (fs *flowServer) Label() security.Label {
-	//nologcall
-	return security.LabelFromMethodTags(fs.tags)
-}
 func (fs *flowServer) LocalPrincipal() security.Principal {
 	//nologcall
 	return fs.flow.LocalPrincipal()
diff --git a/runtimes/google/ipc/server_test.go b/runtimes/google/ipc/server_test.go
index a918f00..8e43cca 100644
--- a/runtimes/google/ipc/server_test.go
+++ b/runtimes/google/ipc/server_test.go
@@ -29,7 +29,10 @@
 func TestReconnect(t *testing.T) {
 	b := createBundle(t, tsecurity.NewPrincipal("client"), nil, nil) // We only need the client from the bundle.
 	defer b.cleanup(t)
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 	server, err := sh.Start("runServer", nil, "127.0.0.1:0")
 	if err != nil {
@@ -86,7 +89,10 @@
 }
 
 func (h *proxyHandle) Start(t *testing.T) error {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	server, err := sh.Start("runProxy", nil)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
diff --git a/runtimes/google/ipc/sort_internal_test.go b/runtimes/google/ipc/sort_internal_test.go
index c234557..1995c16 100644
--- a/runtimes/google/ipc/sort_internal_test.go
+++ b/runtimes/google/ipc/sort_internal_test.go
@@ -73,10 +73,10 @@
 
 	// Just foobar and tcp4
 	want := []string{
-		"/@2@foobar@127.0.0.10@00000000000000000000000000000000@@@@",
-		"/@2@foobar@127.0.0.11@00000000000000000000000000000000@@@@",
-		"/@2@tcp4@127.0.0.1@00000000000000000000000000000000@@@@",
-		"/@2@tcp4@127.0.0.2@00000000000000000000000000000000@@@@",
+		"/@3@foobar@127.0.0.10@00000000000000000000000000000000@@@m@@",
+		"/@3@foobar@127.0.0.11@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp4@127.0.0.1@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp4@127.0.0.2@00000000000000000000000000000000@@@m@@",
 	}
 	if !reflect.DeepEqual(got, want) {
 		t.Errorf("got: %v, want %v", got, want)
@@ -88,10 +88,10 @@
 	}
 	// tcp or tcp4
 	want = []string{
-		"/@2@tcp4@127.0.0.1@00000000000000000000000000000000@@@@",
-		"/@2@tcp4@127.0.0.2@00000000000000000000000000000000@@@@",
-		"/@2@tcp@127.0.0.3@00000000000000000000000000000000@@@@",
-		"/@2@tcp@127.0.0.4@00000000000000000000000000000000@@@@",
+		"/@3@tcp4@127.0.0.1@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp4@127.0.0.2@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp@127.0.0.3@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp@127.0.0.4@00000000000000000000000000000000@@@m@@",
 	}
 
 	// Everything, since we didn't specify a protocol
@@ -103,14 +103,14 @@
 	// original ordering within each protocol, with protocols that
 	// are not in the default ordering list at the end.
 	want = []string{
-		"/@2@tcp@127.0.0.3@00000000000000000000000000000000@@@@",
-		"/@2@tcp@127.0.0.4@00000000000000000000000000000000@@@@",
-		"/@2@tcp4@127.0.0.1@00000000000000000000000000000000@@@@",
-		"/@2@tcp4@127.0.0.2@00000000000000000000000000000000@@@@",
-		"/@2@tcp6@127.0.0.7@00000000000000000000000000000000@@@@",
-		"/@2@tcp6@127.0.0.8@00000000000000000000000000000000@@@@",
-		"/@2@foobar@127.0.0.10@00000000000000000000000000000000@@@@",
-		"/@2@foobar@127.0.0.11@00000000000000000000000000000000@@@@",
+		"/@3@tcp@127.0.0.3@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp@127.0.0.4@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp4@127.0.0.1@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp4@127.0.0.2@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp6@127.0.0.7@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp6@127.0.0.8@00000000000000000000000000000000@@@m@@",
+		"/@3@foobar@127.0.0.10@00000000000000000000000000000000@@@m@@",
+		"/@3@foobar@127.0.0.11@00000000000000000000000000000000@@@m@@",
 	}
 	if !reflect.DeepEqual(got, want) {
 		t.Errorf("got: %v, want %v", got, want)
@@ -132,13 +132,13 @@
 		t.Fatalf("unexpected error: %s", err)
 	}
 	want = []string{
-		"/@2@tcp@127.0.0.3@00000000000000000000000000000000@@@@",
-		"/@2@tcp@127.0.0.1@00000000000000000000000000000000@@@@",
-		"/@2@tcp@74.125.69.139@00000000000000000000000000000000@@@@",
-		"/@2@tcp@192.168.1.10@00000000000000000000000000000000@@@@",
-		"/@2@tcp@74.125.142.83@00000000000000000000000000000000@@@@",
-		"/@2@foobar@127.0.0.10@00000000000000000000000000000000@@@@",
-		"/@2@foobar@127.0.0.11@00000000000000000000000000000000@@@@",
+		"/@3@tcp@127.0.0.3@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp@127.0.0.1@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp@74.125.69.139@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp@192.168.1.10@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp@74.125.142.83@00000000000000000000000000000000@@@m@@",
+		"/@3@foobar@127.0.0.10@00000000000000000000000000000000@@@m@@",
+		"/@3@foobar@127.0.0.11@00000000000000000000000000000000@@@m@@",
 	}
 	if !reflect.DeepEqual(got, want) {
 		t.Errorf("got: %v, want %v", got, want)
@@ -156,11 +156,11 @@
 		t.Fatalf("unexpected error: %s", err)
 	}
 	want := []string{
-		"/@2@tcp@127.0.0.3@00000000000000000000000000000000@@@@",
-		"/@2@tcp@127.0.0.1@00000000000000000000000000000000@@@@",
-		"/@2@tcp@74.125.69.139@00000000000000000000000000000000@@@@",
-		"/@2@tcp@192.168.1.10@00000000000000000000000000000000@@@@",
-		"/@2@tcp@74.125.142.83@00000000000000000000000000000000@@@@",
+		"/@3@tcp@127.0.0.3@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp@127.0.0.1@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp@74.125.69.139@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp@192.168.1.10@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp@74.125.142.83@00000000000000000000000000000000@@@m@@",
 	}
 	if !reflect.DeepEqual(got, want) {
 		t.Errorf("got: %v, want %v", got, want)
@@ -175,16 +175,16 @@
 		t.Fatalf("unexpected error: %s", err)
 	}
 	want = []string{
-		"/@2@ws@127.0.0.3:123@00000000000000000000000000000000@@@@",
-		"/@2@ws@127.0.0.1@00000000000000000000000000000000@@@@",
-		"/@2@ws@74.125.69.139@00000000000000000000000000000000@@@@",
-		"/@2@ws@192.168.1.10@00000000000000000000000000000000@@@@",
-		"/@2@ws@74.125.142.83@00000000000000000000000000000000@@@@",
-		"/@2@tcp@127.0.0.3@00000000000000000000000000000000@@@@",
-		"/@2@tcp@127.0.0.1@00000000000000000000000000000000@@@@",
-		"/@2@tcp@74.125.69.139@00000000000000000000000000000000@@@@",
-		"/@2@tcp@192.168.1.10@00000000000000000000000000000000@@@@",
-		"/@2@tcp@74.125.142.83@00000000000000000000000000000000@@@@",
+		"/@3@ws@127.0.0.3:123@00000000000000000000000000000000@@@m@@",
+		"/@3@ws@127.0.0.1@00000000000000000000000000000000@@@m@@",
+		"/@3@ws@74.125.69.139@00000000000000000000000000000000@@@m@@",
+		"/@3@ws@192.168.1.10@00000000000000000000000000000000@@@m@@",
+		"/@3@ws@74.125.142.83@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp@127.0.0.3@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp@127.0.0.1@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp@74.125.69.139@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp@192.168.1.10@00000000000000000000000000000000@@@m@@",
+		"/@3@tcp@74.125.142.83@00000000000000000000000000000000@@@m@@",
 	}
 	if !reflect.DeepEqual(got, want) {
 		t.Errorf("got: %v, want %v", got, want)
diff --git a/runtimes/google/ipc/stream/manager/manager_test.go b/runtimes/google/ipc/stream/manager/manager_test.go
index 8d4d872..829800f 100644
--- a/runtimes/google/ipc/stream/manager/manager_test.go
+++ b/runtimes/google/ipc/stream/manager/manager_test.go
@@ -544,7 +544,10 @@
 
 func TestServerRestartDuringClientLifetime(t *testing.T) {
 	client := InternalNew(naming.FixedRoutingID(0xcccccccc))
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(nil, nil)
 	h, err := sh.Start("runServer", nil, "127.0.0.1:0")
 	if err != nil {
@@ -583,7 +586,10 @@
 
 func TestServerRestartDuringClientLifetimeWS(t *testing.T) {
 	client := InternalNew(naming.FixedRoutingID(0xcccccccc))
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(nil, nil)
 	h, err := sh.Start("runServer", nil, "127.0.0.1:0")
 	if err != nil {
diff --git a/runtimes/google/ipc/stream/proxy/protocol.vdl.go b/runtimes/google/ipc/stream/proxy/protocol.vdl.go
index c5d943f..fefef65 100644
--- a/runtimes/google/ipc/stream/proxy/protocol.vdl.go
+++ b/runtimes/google/ipc/stream/proxy/protocol.vdl.go
@@ -3,12 +3,22 @@
 
 package proxy
 
+import (
+	// The non-user imports are prefixed with "__" to prevent collisions.
+	__vdl "veyron.io/veyron/veyron2/vdl"
+)
+
 // Request is the message sent by a server to request that the proxy route
 // traffic intended for the server's RoutingID to the network connection
 // between the server and the proxy.
 type Request struct {
 }
 
+func (Request) __VDLReflect(struct {
+	Name string "veyron.io/veyron/veyron/runtimes/google/ipc/stream/proxy.Request"
+}) {
+}
+
 // Response is sent by the proxy to the server after processing Request.
 type Response struct {
 	// Error is a description of why the proxy refused to proxy the server.
@@ -18,3 +28,13 @@
 	// used to communicate with the server through the proxy.
 	Endpoint string
 }
+
+func (Response) __VDLReflect(struct {
+	Name string "veyron.io/veyron/veyron/runtimes/google/ipc/stream/proxy.Response"
+}) {
+}
+
+func init() {
+	__vdl.Register(Request{})
+	__vdl.Register(Response{})
+}
diff --git a/runtimes/google/ipc/stream/vc/auth.go b/runtimes/google/ipc/stream/vc/auth.go
index cf83fff..5ecc6ca 100644
--- a/runtimes/google/ipc/stream/vc/auth.go
+++ b/runtimes/google/ipc/stream/vc/auth.go
@@ -9,6 +9,7 @@
 	"veyron.io/veyron/veyron/runtimes/google/ipc/stream/crypto"
 	"veyron.io/veyron/veyron/runtimes/google/lib/iobuf"
 
+	"veyron.io/veyron/veyron2/context"
 	"veyron.io/veyron/veyron2/ipc/version"
 	"veyron.io/veyron/veyron2/security"
 	"veyron.io/veyron/veyron2/vom"
@@ -37,7 +38,7 @@
 	}
 	var discharges []security.Discharge
 	if tpcavs := server.ThirdPartyCaveats(); len(tpcavs) > 0 && dc != nil {
-		discharges = dc.PrepareDischarges(tpcavs, security.DischargeImpetus{})
+		discharges = dc.PrepareDischarges(nil, tpcavs, security.DischargeImpetus{})
 	}
 	if err = writeBlessings(conn, authServerContextTag, crypter, principal, server, discharges, v); err != nil {
 		return
@@ -56,7 +57,7 @@
 //
 // TODO(ashankar): Seems like there is no way the blessing store
 // can say that it does NOT want to share the default blessing with the server?
-func AuthenticateAsClient(conn io.ReadWriteCloser, principal security.Principal, dc DischargeClient, crypter crypto.Crypter, v version.IPCVersion) (server, client security.Blessings, serverDischarges map[string]security.Discharge, err error) {
+func AuthenticateAsClient(ctx context.T, conn io.ReadWriteCloser, principal security.Principal, dc DischargeClient, crypter crypto.Crypter, v version.IPCVersion) (server, client security.Blessings, serverDischarges map[string]security.Discharge, err error) {
 	defer conn.Close()
 	if server, serverDischarges, err = readBlessings(conn, authServerContextTag, crypter, v); err != nil {
 		return
@@ -79,7 +80,7 @@
 	}
 	var discharges []security.Discharge
 	if dc != nil {
-		discharges = dc.PrepareDischarges(client.ThirdPartyCaveats(), security.DischargeImpetus{})
+		discharges = dc.PrepareDischarges(ctx, client.ThirdPartyCaveats(), security.DischargeImpetus{})
 	}
 	if err = writeBlessings(conn, authClientContextTag, crypter, principal, client, discharges, v); err != nil {
 		return
diff --git a/runtimes/google/ipc/stream/vc/vc.go b/runtimes/google/ipc/stream/vc/vc.go
index f5783cb..4460e6e 100644
--- a/runtimes/google/ipc/stream/vc/vc.go
+++ b/runtimes/google/ipc/stream/vc/vc.go
@@ -16,13 +16,16 @@
 	"veyron.io/veyron/veyron/runtimes/google/lib/bqueue"
 	"veyron.io/veyron/veyron/runtimes/google/lib/iobuf"
 	vsync "veyron.io/veyron/veyron/runtimes/google/lib/sync"
+	ivtrace "veyron.io/veyron/veyron/runtimes/google/vtrace"
 
+	"veyron.io/veyron/veyron2/context"
 	"veyron.io/veyron/veyron2/ipc/stream"
 	"veyron.io/veyron/veyron2/ipc/version"
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/options"
 	"veyron.io/veyron/veyron2/security"
 	"veyron.io/veyron/veyron2/vlog"
+	"veyron.io/veyron/veyron2/vtrace"
 )
 
 var (
@@ -62,6 +65,12 @@
 	version version.IPCVersion
 }
 
+// NoDischarges specifies that the RPC call should not fetch discharges.
+type NoDischarges struct{}
+
+func (NoDischarges) IPCCallOpt()     {}
+func (NoDischarges) IPCStreamVCOpt() {}
+
 var _ stream.VC = (*VC)(nil)
 
 // Helper is the interface for functionality required by the stream.VC
@@ -111,7 +120,7 @@
 //
 // TODO(ataly, ashankar): What should be the impetus for obtaining the discharges?
 type DischargeClient interface {
-	PrepareDischarges(forcaveats []security.ThirdPartyCaveat, impetus security.DischargeImpetus) []security.Discharge
+	PrepareDischarges(ctx context.T, forcaveats []security.ThirdPartyCaveat, impetus security.DischargeImpetus) []security.Discharge
 	// Invalidate marks the provided discharges as invalid, and therefore unfit
 	// for being returned by a subsequent PrepareDischarges call.
 	Invalidate(discharges ...security.Discharge)
@@ -121,6 +130,11 @@
 	IPCStreamVCOpt()
 }
 
+// DialContext establishes the context under which a VC Dial was initiated.
+type DialContext struct{ context.T }
+
+func (DialContext) IPCStreamVCOpt() {}
+
 // InternalNew creates a new VC, which implements the stream.VC interface.
 //
 // As the name suggests, this method is intended for use only within packages
@@ -361,9 +375,13 @@
 		tlsSessionCache crypto.TLSClientSessionCache
 		securityLevel   options.VCSecurityLevel
 		dischargeClient DischargeClient
+		ctx             context.T
+		noDischarges    bool
 	)
 	for _, o := range opts {
 		switch v := o.(type) {
+		case DialContext:
+			ctx = v.T
 		case DischargeClient:
 			dischargeClient = v
 		case LocalPrincipal:
@@ -372,8 +390,19 @@
 			securityLevel = v
 		case crypto.TLSClientSessionCache:
 			tlsSessionCache = v
+		case NoDischarges:
+			noDischarges = true
 		}
 	}
+	if ctx != nil {
+		var span vtrace.Span
+		ctx, span = ivtrace.WithNewSpan(ctx, "vc.HandshakeDialedVC")
+		defer span.Finish()
+	}
+	// If noDischarge is provided, disable the dischargeClient.
+	if noDischarges {
+		dischargeClient = nil
+	}
 	switch securityLevel {
 	case options.VCSecurityConfidential:
 		if principal == nil {
@@ -410,7 +439,7 @@
 	if err != nil {
 		return vc.err(fmt.Errorf("failed to create a Flow for authentication: %v", err))
 	}
-	rBlessings, lBlessings, rDischarges, err := AuthenticateAsClient(authConn, principal, dischargeClient, crypter, vc.version)
+	rBlessings, lBlessings, rDischarges, err := AuthenticateAsClient(ctx, authConn, principal, dischargeClient, crypter, vc.version)
 	if err != nil {
 		return vc.err(fmt.Errorf("authentication failed: %v", err))
 	}
diff --git a/runtimes/google/ipc/stream/vc/vc_test.go b/runtimes/google/ipc/stream/vc/vc_test.go
index 4e3b376..4ac541e 100644
--- a/runtimes/google/ipc/stream/vc/vc_test.go
+++ b/runtimes/google/ipc/stream/vc/vc_test.go
@@ -21,6 +21,7 @@
 	"veyron.io/veyron/veyron/runtimes/google/lib/bqueue/drrqueue"
 	"veyron.io/veyron/veyron/runtimes/google/lib/iobuf"
 
+	"veyron.io/veyron/veyron2/context"
 	"veyron.io/veyron/veyron2/ipc/stream"
 	"veyron.io/veyron/veyron2/ipc/version"
 	"veyron.io/veyron/veyron2/naming"
@@ -164,7 +165,7 @@
 
 type mockDischargeClient []security.Discharge
 
-func (m mockDischargeClient) PrepareDischarges(forcaveats []security.ThirdPartyCaveat, impetus security.DischargeImpetus) []security.Discharge {
+func (m mockDischargeClient) PrepareDischarges(_ context.T, forcaveats []security.ThirdPartyCaveat, impetus security.DischargeImpetus) []security.Discharge {
 	return m
 }
 func (mockDischargeClient) Invalidate(...security.Discharge) {}
diff --git a/runtimes/google/ipc/stream/vif/auth.go b/runtimes/google/ipc/stream/vif/auth.go
index 6a05496..53a4b71 100644
--- a/runtimes/google/ipc/stream/vif/auth.go
+++ b/runtimes/google/ipc/stream/vif/auth.go
@@ -14,6 +14,7 @@
 	"veyron.io/veyron/veyron/runtimes/google/ipc/stream/vc"
 	"veyron.io/veyron/veyron/runtimes/google/ipc/version"
 	"veyron.io/veyron/veyron/runtimes/google/lib/iobuf"
+	"veyron.io/veyron/veyron2/context"
 	"veyron.io/veyron/veyron2/ipc/stream"
 	ipcversion "veyron.io/veyron/veyron2/ipc/version"
 	"veyron.io/veyron/veyron2/options"
@@ -60,7 +61,7 @@
 // including a hash of the HopSetup message in the encrypted stream.  It is
 // likely that this will be addressed in subsequent protocol versions (or it may
 // not be addressed at all if IPCVersion6 becomes the only supported version).
-func AuthenticateAsClient(conn net.Conn, versions *version.Range, principal security.Principal, dc vc.DischargeClient) (crypto.ControlCipher, error) {
+func AuthenticateAsClient(ctx context.T, conn net.Conn, versions *version.Range, principal security.Principal, dc vc.DischargeClient) (crypto.ControlCipher, error) {
 	if versions == nil {
 		versions = version.SupportedRange
 	}
@@ -110,13 +111,13 @@
 	// Perform the authentication.
 	switch v {
 	case ipcversion.IPCVersion6:
-		return authenticateAsClientIPC6(conn, reader, principal, dc, &pvt, &pub, ppub)
+		return authenticateAsClientIPC6(ctx, conn, reader, principal, dc, &pvt, &pub, ppub)
 	default:
 		return nil, errUnsupportedEncryptVersion
 	}
 }
 
-func authenticateAsClientIPC6(writer io.Writer, reader *iobuf.Reader, principal security.Principal, dc vc.DischargeClient,
+func authenticateAsClientIPC6(ctx context.T, writer io.Writer, reader *iobuf.Reader, principal security.Principal, dc vc.DischargeClient,
 	pvt *privateData, pub, ppub *message.HopSetup) (crypto.ControlCipher, error) {
 	pbox := ppub.NaclBox()
 	if pbox == nil {
@@ -125,7 +126,7 @@
 	c := crypto.NewControlCipherIPC6(&pbox.PublicKey, &pvt.naclBoxPrivateKey, false)
 	sconn := newSetupConn(writer, reader, c)
 	// TODO(jyh): act upon the authentication results.
-	_, _, _, err := vc.AuthenticateAsClient(sconn, principal, dc, crypto.NewNullCrypter(), ipcversion.IPCVersion6)
+	_, _, _, err := vc.AuthenticateAsClient(ctx, sconn, principal, dc, crypto.NewNullCrypter(), ipcversion.IPCVersion6)
 	if err != nil {
 		return nil, err
 	}
@@ -229,18 +230,26 @@
 
 // clientAuthOptions extracts the client authentication options from the options
 // list.
-func clientAuthOptions(lopts []stream.VCOpt) (principal security.Principal, dischargeClient vc.DischargeClient, err error) {
+func clientAuthOptions(lopts []stream.VCOpt) (ctx context.T, principal security.Principal, dischargeClient vc.DischargeClient, err error) {
 	var securityLevel options.VCSecurityLevel
+	var noDischarges bool
 	for _, o := range lopts {
 		switch v := o.(type) {
+		case vc.DialContext:
+			ctx = v.T
 		case vc.DischargeClient:
 			dischargeClient = v
 		case vc.LocalPrincipal:
 			principal = v.Principal
 		case options.VCSecurityLevel:
 			securityLevel = v
+		case vc.NoDischarges:
+			noDischarges = true
 		}
 	}
+	if noDischarges {
+		dischargeClient = nil
+	}
 	switch securityLevel {
 	case options.VCSecurityConfidential:
 		if principal == nil {
diff --git a/runtimes/google/ipc/stream/vif/vif.go b/runtimes/google/ipc/stream/vif/vif.go
index 355ea0b..6447009 100644
--- a/runtimes/google/ipc/stream/vif/vif.go
+++ b/runtimes/google/ipc/stream/vif/vif.go
@@ -25,10 +25,12 @@
 	"veyron.io/veyron/veyron/runtimes/google/lib/pcqueue"
 	vsync "veyron.io/veyron/veyron/runtimes/google/lib/sync"
 	"veyron.io/veyron/veyron/runtimes/google/lib/upcqueue"
+	ivtrace "veyron.io/veyron/veyron/runtimes/google/vtrace"
 	"veyron.io/veyron/veyron2/ipc/stream"
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/verror"
 	"veyron.io/veyron/veyron2/vlog"
+	"veyron.io/veyron/veyron2/vtrace"
 )
 
 // VIF implements a "virtual interface" over an underlying network connection
@@ -107,11 +109,17 @@
 // placed inside veyron/runtimes/google. Code outside the
 // veyron2/runtimes/google/* packages should never call this method.
 func InternalNewDialedVIF(conn net.Conn, rid naming.RoutingID, versions *version.Range, opts ...stream.VCOpt) (*VIF, error) {
-	principal, dc, err := clientAuthOptions(opts)
+	ctx, principal, dc, err := clientAuthOptions(opts)
 	if err != nil {
 		return nil, err
 	}
-	c, err := AuthenticateAsClient(conn, versions, principal, dc)
+	if ctx != nil {
+		var span vtrace.Span
+		ctx, span = ivtrace.WithNewSpan(ctx, "InternalNewDialedVIF")
+		span.Annotatef("(%v, %v)", conn.RemoteAddr().Network(), conn.RemoteAddr())
+		defer span.Finish()
+	}
+	c, err := AuthenticateAsClient(ctx, conn, versions, principal, dc)
 	if err != nil {
 		return nil, err
 	}
diff --git a/runtimes/google/ipc/testutil_test.go b/runtimes/google/ipc/testutil_test.go
index 4144d97..02f07c7 100644
--- a/runtimes/google/ipc/testutil_test.go
+++ b/runtimes/google/ipc/testutil_test.go
@@ -4,10 +4,10 @@
 	"reflect"
 	"testing"
 
-	"veyron.io/veyron/veyron/lib/testutil"
-
 	"veyron.io/veyron/veyron2/security"
-	"veyron.io/veyron/veyron2/verror"
+	"veyron.io/veyron/veyron2/verror2"
+
+	"veyron.io/veyron/veyron/lib/testutil"
 )
 
 func init() { testutil.Init() }
@@ -22,7 +22,7 @@
 			// reasons for this check and conditions for when it
 			// can be removed can be seen in the comments for
 			// result2vom.
-			var verr verror.E
+			var verr verror2.E
 			typ = reflect.ValueOf(&verr).Elem().Type()
 		}
 		outs[ix] = reflect.New(typ).Interface()
@@ -34,9 +34,23 @@
 	for ix, res := range gotptrs {
 		got := reflect.ValueOf(res).Elem().Interface()
 		want := want[ix]
-		if !reflect.DeepEqual(got, want) {
-			t.Errorf("%s result %d got %v, want %v", name, ix, got, want)
+		switch g := got.(type) {
+		case verror2.Standard:
+			w, ok := want.(verror2.Standard)
+			// don't use reflect deep equal on verror's since they contain
+			// a list of stack PCs which will be different.
+			if !ok {
+				t.Errorf("%s result %d got type %T, want %T", name, ix, g, w)
+			}
+			if !verror2.Is(g, w.IDAction.ID) {
+				t.Errorf("%s result %d got %v, want %v", name, ix, g, w)
+			}
+		default:
+			if !reflect.DeepEqual(got, want) {
+				t.Errorf("%s result %d got %v, want %v", name, ix, got, want)
+			}
 		}
+
 	}
 }
 
diff --git a/runtimes/google/naming/endpoint.go b/runtimes/google/naming/endpoint.go
index e2fefd9..2552bc2 100644
--- a/runtimes/google/naming/endpoint.go
+++ b/runtimes/google/naming/endpoint.go
@@ -36,6 +36,9 @@
 func NewEndpoint(input string) (*Endpoint, error) {
 	var ep Endpoint
 
+	// We have to guess this is a mount table if we don't know.
+	ep.IsMountTable = true
+
 	// The prefix and suffix are optional.
 	input = strings.TrimPrefix(strings.TrimSuffix(input, suffix), separator)
 
@@ -116,7 +119,10 @@
 }
 
 func parseMountTableFlag(input string) (bool, error) {
-	if len(input) == 1 {
+	switch len(input) {
+	case 0:
+		return true, nil
+	case 1:
 		switch f := input[0]; f {
 		case 'm':
 			return true, nil
@@ -169,7 +175,7 @@
 	return Network
 }
 
-var defaultVersion = 2
+var defaultVersion = 3
 
 func (ep *Endpoint) VersionedString(version int) string {
 	switch version {
@@ -205,7 +211,7 @@
 
 func (ep *Endpoint) ServesMountTable() bool {
 	//nologcall
-	return true
+	return ep.IsMountTable
 }
 
 type addr struct {
diff --git a/runtimes/google/naming/endpoint_test.go b/runtimes/google/naming/endpoint_test.go
index 00135c5..1aaca1b 100644
--- a/runtimes/google/naming/endpoint_test.go
+++ b/runtimes/google/naming/endpoint_test.go
@@ -11,9 +11,10 @@
 
 func TestEndpoint(t *testing.T) {
 	v1 := &Endpoint{
-		Protocol: "tcp",
-		Address:  "batman.com:1234",
-		RID:      naming.FixedRoutingID(0xdabbad00),
+		Protocol:     "tcp",
+		Address:      "batman.com:1234",
+		RID:          naming.FixedRoutingID(0xdabbad00),
+		IsMountTable: true,
 	}
 	v2 := &Endpoint{
 		Protocol:      "tcp",
@@ -21,6 +22,7 @@
 		RID:           naming.FixedRoutingID(0xdabbad00),
 		MinIPCVersion: 1,
 		MaxIPCVersion: 10,
+		IsMountTable:  true,
 	}
 	v2hp := &Endpoint{
 		Protocol:      "tcp",
@@ -28,13 +30,22 @@
 		RID:           naming.FixedRoutingID(0x0),
 		MinIPCVersion: 2,
 		MaxIPCVersion: 3,
+		IsMountTable:  true,
 	}
-	v3 := &Endpoint{
+	v3s := &Endpoint{
 		Protocol:      "tcp",
 		Address:       "batman.com:2345",
 		RID:           naming.FixedRoutingID(0x0),
 		MinIPCVersion: 2,
 		MaxIPCVersion: 3,
+		IsMountTable:  false,
+	}
+	v3m := &Endpoint{
+		Protocol:      "tcp",
+		Address:       "batman.com:2345",
+		RID:           naming.FixedRoutingID(0xdabbad00),
+		MinIPCVersion: 2,
+		MaxIPCVersion: 3,
 		IsMountTable:  true,
 	}
 
@@ -56,6 +67,45 @@
 		}
 	}
 
+	// Test v3 endpoints.
+	defaultVersion = 3
+	testcasesC := []struct {
+		Endpoint naming.Endpoint
+		String   string
+		Input    string
+		min, max version.IPCVersion
+		servesMT bool
+	}{
+		{v3s, "@3@tcp@batman.com:2345@00000000000000000000000000000000@2@3@s@@", "", 2, 3, false},
+		{v3m, "@3@tcp@batman.com:2345@000000000000000000000000dabbad00@2@3@m@@", "", 2, 3, true},
+	}
+
+	for _, test := range testcasesC {
+		if got, want := test.Endpoint.String(), test.String; got != want {
+			t.Errorf("Got %q want %q for endpoint %T = %#v", got, want, test.Endpoint, test.Endpoint)
+		}
+		str := test.Input
+		var ep naming.Endpoint
+		var err error
+		if str == "" {
+			str = test.String
+			ep, err = NewEndpoint(str)
+		} else {
+			ep, err = NewEndpoint(naming.FormatEndpoint("tcp", str,
+				version.IPCVersionRange{test.min, test.max},
+				naming.ServesMountTableOpt(test.servesMT)))
+		}
+		if err != nil {
+			t.Errorf("Endpoint(%q) failed with %v", str, err)
+			continue
+		}
+		if !reflect.DeepEqual(ep, test.Endpoint) {
+			t.Errorf("Got endpoint %T = %#v, want %T = %#v for string %q", ep, ep, test.Endpoint, test.Endpoint, str)
+		}
+	}
+
+	// Make sure we can continue to parse and create v2 endpoints.
+	defaultVersion = 2
 	testcasesB := []struct {
 		Endpoint naming.Endpoint
 		String   string
@@ -63,11 +113,9 @@
 		min, max version.IPCVersion
 		servesMT bool
 	}{
-		{v1, "@2@tcp@batman.com:1234@000000000000000000000000dabbad00@@@@", "", version.UnknownIPCVersion, version.UnknownIPCVersion, false},
-		{v2, "@2@tcp@batman.com:2345@000000000000000000000000dabbad00@1@10@@", "", 1, 10, false},
-		{v2hp, "@2@tcp@batman.com:2345@00000000000000000000000000000000@2@3@@", "batman.com:2345", 2, 3, false},
-		// the v3 format is ignored unless explicitly enabled.
-		{v3, "@2@tcp@batman.com:2345@00000000000000000000000000000000@2@3@@", "batman.com:2345", 2, 3, true},
+		{v1, "@2@tcp@batman.com:1234@000000000000000000000000dabbad00@@@@", "", version.UnknownIPCVersion, version.UnknownIPCVersion, true},
+		{v2, "@2@tcp@batman.com:2345@000000000000000000000000dabbad00@1@10@@", "", 1, 10, true},
+		{v2hp, "@2@tcp@batman.com:2345@00000000000000000000000000000000@2@3@@", "batman.com:2345", 2, 3, true},
 	}
 
 	for _, test := range testcasesB {
@@ -93,25 +141,7 @@
 			t.Errorf("Got endpoint %T = %#v, want %T = %#v for string %q", ep, ep, test.Endpoint, test.Endpoint, str)
 		}
 	}
-
-	// Enable V3 endpoints.
 	defaultVersion = 3
-	for _, c := range []struct {
-		servesMT bool
-		str      string
-	}{
-		{true, "@3@tcp@a:10@00000000000000000000000000000000@1@3@m@@"},
-		{false, "@3@tcp@a:10@00000000000000000000000000000000@1@3@s@@"},
-	} {
-		ep, _ := NewEndpoint(naming.FormatEndpoint("tcp", "a:10",
-			version.IPCVersionRange{1, 3},
-			naming.ServesMountTableOpt(c.servesMT)))
-		if got, want := ep.String(), c.str; got != want {
-			t.Errorf("got: %s, want: %s", got, want)
-		}
-	}
-	// Disable V3 endpoints.
-	defaultVersion = 2
 }
 
 type endpointTest struct {
@@ -121,15 +151,17 @@
 
 func TestEndpointDefaults(t *testing.T) {
 	testcases := []endpointTest{
-		{"@1@tcp@batman@@@", "@2@tcp@batman@00000000000000000000000000000000@@@@", nil},
-		{"@2@tcp@robin@@@@@", "@2@tcp@robin@00000000000000000000000000000000@@@@", nil},
-		{"@1@@@@@", "@2@tcp@:0@00000000000000000000000000000000@@@@", nil},
-		{"@2@@@@@@@", "@2@tcp@:0@00000000000000000000000000000000@@@@", nil},
-		{"@1@tcp@batman:12@@@", "@2@tcp@batman:12@00000000000000000000000000000000@@@@", nil},
-		{"@host:10@@", "@2@tcp@host:10@00000000000000000000000000000000@@@@", nil},
-		{"@2@tcp@foo:12@@9@@@", "@2@tcp@foo:12@00000000000000000000000000000000@9@@@", nil},
-		{"@2@tcp@foo:12@@@4@@", "@2@tcp@foo:12@00000000000000000000000000000000@@4@@", nil},
-		{"@2@tcp@foo:12@@2@4@@", "@2@tcp@foo:12@00000000000000000000000000000000@2@4@@", nil},
+		{"@1@tcp@batman@@@", "@3@tcp@batman@00000000000000000000000000000000@@@m@@", nil},
+		{"@2@tcp@robin@@@@@", "@3@tcp@robin@00000000000000000000000000000000@@@m@@", nil},
+		{"@1@@@@@", "@3@tcp@:0@00000000000000000000000000000000@@@m@@", nil},
+		{"@2@@@@@@@", "@3@tcp@:0@00000000000000000000000000000000@@@m@@", nil},
+		{"@1@tcp@batman:12@@@", "@3@tcp@batman:12@00000000000000000000000000000000@@@m@@", nil},
+		{"@host:10@@", "@3@tcp@host:10@00000000000000000000000000000000@@@m@@", nil},
+		{"@2@tcp@foo:12@@9@@@", "@3@tcp@foo:12@00000000000000000000000000000000@9@@m@@", nil},
+		{"@2@tcp@foo:12@@@4@@", "@3@tcp@foo:12@00000000000000000000000000000000@@4@m@@", nil},
+		{"@2@tcp@foo:12@@2@4@@", "@3@tcp@foo:12@00000000000000000000000000000000@2@4@m@@", nil},
+		{"@3@@host:11@@@@m@@", "@3@tcp@host:11@00000000000000000000000000000000@@@m@@", nil},
+		{"@3@@host:12@@@@@@", "@3@tcp@host:12@00000000000000000000000000000000@@@m@@", nil},
 	}
 	runEndpointTests(t, testcases)
 }
@@ -156,8 +188,8 @@
 
 func TestHostPortEndpoint(t *testing.T) {
 	testcases := []endpointTest{
-		{"localhost:10", "@2@tcp@localhost:10@00000000000000000000000000000000@@@@", nil},
-		{"localhost:", "@2@tcp@localhost:@00000000000000000000000000000000@@@@", nil},
+		{"localhost:10", "@3@tcp@localhost:10@00000000000000000000000000000000@@@m@@", nil},
+		{"localhost:", "@3@tcp@localhost:@00000000000000000000000000000000@@@m@@", nil},
 		{"localhost", "", errInvalidEndpointString},
 	}
 	runEndpointTests(t, testcases)
@@ -170,18 +202,21 @@
 		Address:       "batman.com:4444",
 		MinIPCVersion: min,
 		MaxIPCVersion: max,
+		IsMountTable:  true,
 	}
 	ipv4 := &Endpoint{
 		Protocol:      "tcp",
 		Address:       "192.168.1.1:4444",
 		MinIPCVersion: min,
 		MaxIPCVersion: max,
+		IsMountTable:  true,
 	}
 	ipv6 := &Endpoint{
 		Protocol:      "tcp",
 		Address:       "[01:02::]:4444",
 		MinIPCVersion: min,
 		MaxIPCVersion: max,
+		IsMountTable:  true,
 	}
 	testcases := []struct {
 		Endpoint   naming.Endpoint
diff --git a/runtimes/google/naming/namespace/all_test.go b/runtimes/google/naming/namespace/all_test.go
index 645050a..c85a1d1 100644
--- a/runtimes/google/naming/namespace/all_test.go
+++ b/runtimes/google/naming/namespace/all_test.go
@@ -9,6 +9,7 @@
 	"time"
 
 	"veyron.io/veyron/veyron2"
+	"veyron.io/veyron/veyron2/context"
 	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/ipc/stream"
 	"veyron.io/veyron/veyron2/naming"
@@ -24,6 +25,7 @@
 	"veyron.io/veyron/veyron/lib/websocket"
 	_ "veyron.io/veyron/veyron/profiles"
 	"veyron.io/veyron/veyron/runtimes/google/naming/namespace"
+	vsecurity "veyron.io/veyron/veyron/security"
 	service "veyron.io/veyron/veyron/services/mounttable/lib"
 )
 
@@ -148,20 +150,28 @@
 	}
 }
 
-func testResolveToMountTable(t *testing.T, r veyron2.Runtime, ns naming.Namespace, name string, want ...string) {
-	servers, err := ns.ResolveToMountTable(r.NewContext(), name)
+func doResolveTest(t *testing.T, fname string, f func(context.T, string, ...naming.ResolveOpt) ([]string, error), ctx context.T, name string, want []string, opts ...naming.ResolveOpt) {
+	servers, err := f(ctx, name, opts...)
 	if err != nil {
-		boom(t, "Failed to ResolveToMountTable %q: %s", name, err)
+		boom(t, "Failed to %s %s: %s", fname, name, err)
 	}
-	compare(t, "ResolveToMountTable", name, servers, want)
+	compare(t, fname, name, servers, want)
+}
+
+func testResolveToMountTable(t *testing.T, r veyron2.Runtime, ns naming.Namespace, name string, want ...string) {
+	doResolveTest(t, "ResolveToMountTable", ns.ResolveToMountTable, r.NewContext(), name, want)
+}
+
+func testResolveToMountTableWithPattern(t *testing.T, r veyron2.Runtime, ns naming.Namespace, name string, pattern naming.ResolveOpt, want ...string) {
+	doResolveTest(t, "ResolveToMountTable", ns.ResolveToMountTable, r.NewContext(), name, want, pattern)
 }
 
 func testResolve(t *testing.T, r veyron2.Runtime, ns naming.Namespace, name string, want ...string) {
-	servers, err := ns.Resolve(r.NewContext(), name)
-	if err != nil {
-		boom(t, "Failed to Resolve %q: %s", name, err)
-	}
-	compare(t, "Resolve", name, servers, want)
+	doResolveTest(t, "Resolve", ns.Resolve, r.NewContext(), name, want)
+}
+
+func testResolveWithPattern(t *testing.T, r veyron2.Runtime, ns naming.Namespace, name string, pattern naming.ResolveOpt, want ...string) {
+	doResolveTest(t, "Resolve", ns.Resolve, r.NewContext(), name, want, pattern)
 }
 
 func testUnresolve(t *testing.T, r veyron2.Runtime, ns naming.Namespace, name string, want ...string) {
@@ -623,3 +633,66 @@
 		t.Errorf("namespace.New should have failed with an unrooted name")
 	}
 }
+
+func bless(blesser, delegate security.Principal, extension string) {
+	b, err := blesser.Bless(delegate.PublicKey(), blesser.BlessingStore().Default(), extension, security.UnconstrainedUse())
+	if err != nil {
+		panic(err)
+	}
+	delegate.BlessingStore().SetDefault(b)
+}
+
+func TestRootBlessing(t *testing.T) {
+	// We need the default runtime for the server-side mounttable code
+	// which references rt.R() to create new endpoints
+	cr := rt.Init()
+	r, _ := rt.New() // We use a different runtime for the client side.
+
+	proot, err := vsecurity.NewPrincipal()
+	if err != nil {
+		panic(err)
+	}
+	b, err := proot.BlessSelf("root")
+	if err != nil {
+		panic(err)
+	}
+	proot.BlessingStore().SetDefault(b)
+
+	bless(proot, r.Principal(), "server")
+	bless(proot, cr.Principal(), "client")
+
+	cr.Principal().AddToRoots(proot.BlessingStore().Default())
+	r.Principal().AddToRoots(proot.BlessingStore().Default())
+
+	root, mts, _, stopper := createNamespace(t, r)
+	defer stopper()
+	ns := r.Namespace()
+
+	name := naming.Join(root.name, mt2MP)
+	// First check with a non-matching blessing pattern.
+	println("********")
+	_, err = ns.Resolve(r.NewContext(), name, naming.RootBlessingPatternOpt("root/foobar"))
+	if !verror.Is(err, verror.NotTrusted.ID) {
+		t.Errorf("Resolve expected NotTrusted error, got %v", err)
+	}
+	_, err = ns.ResolveToMountTable(r.NewContext(), name, naming.RootBlessingPatternOpt("root/foobar"))
+	if !verror.Is(err, verror.NotTrusted.ID) {
+		t.Errorf("ResolveToMountTable expected NotTrusted error, got %v", err)
+	}
+
+	// Now check a matching pattern.
+	testResolveWithPattern(t, r, ns, name, naming.RootBlessingPatternOpt("root/server"), addWSName(mts[mt2MP].name)...)
+	testResolveToMountTableWithPattern(t, r, ns, name, naming.RootBlessingPatternOpt("root/server"), name)
+
+	// After successful lookup it should be cached, so the pattern doesn't matter.
+	testResolveWithPattern(t, r, ns, name, naming.RootBlessingPatternOpt("root/foobar"), addWSName(mts[mt2MP].name)...)
+
+	// Test calling a method.
+	jokeName := naming.Join(root.name, mt4MP, j1MP)
+	runServer(t, r, &dispatcher{}, naming.Join(mts["mt4"].name, j1MP))
+	_, err = r.Client().StartCall(r.NewContext(), "[root/foobar]"+jokeName, "KnockKnock", nil)
+	if err == nil {
+		t.Errorf("StartCall expected NoAccess error, got %v", err)
+	}
+	knockKnock(t, r, "[root/server]"+jokeName)
+}
diff --git a/runtimes/google/naming/namespace/namespace.go b/runtimes/google/naming/namespace/namespace.go
index 26cc469..9d58742 100644
--- a/runtimes/google/naming/namespace/namespace.go
+++ b/runtimes/google/naming/namespace/namespace.go
@@ -4,6 +4,8 @@
 	"sync"
 	"time"
 
+	inaming "veyron.io/veyron/veyron/runtimes/google/naming"
+
 	"veyron.io/veyron/veyron2"
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/verror"
@@ -125,9 +127,11 @@
 		}
 		return e, false
 	}
-	// TODO(p): right now I assume any address handed to me to be resolved is a mount table.
-	// Eventually we should do something like the following:
-	e.SetServesMountTable(true)
+	servesMT := true
+	if ep, err := inaming.NewEndpoint(address); err == nil {
+		servesMT = ep.ServesMountTable()
+	}
+	e.SetServesMountTable(servesMT)
 	e.Name = suffix
 	e.Servers = append(e.Servers, naming.MountedServer{Server: naming.JoinAddressName(address, ""), Expires: expiration})
 	return e, true
diff --git a/runtimes/google/naming/namespace/resolve.go b/runtimes/google/naming/namespace/resolve.go
index eb69a3c..110dcbf 100644
--- a/runtimes/google/naming/namespace/resolve.go
+++ b/runtimes/google/naming/namespace/resolve.go
@@ -2,6 +2,7 @@
 
 import (
 	"errors"
+	"fmt"
 	"runtime"
 
 	"veyron.io/veyron/veyron2/context"
@@ -12,11 +13,17 @@
 	"veyron.io/veyron/veyron2/vlog"
 )
 
-func (ns *namespace) resolveAgainstMountTable(ctx context.T, client ipc.Client, e *naming.MountEntry) (*naming.MountEntry, error) {
+func (ns *namespace) resolveAgainstMountTable(ctx context.T, client ipc.Client, e *naming.MountEntry, pattern string) (*naming.MountEntry, error) {
 	// Try each server till one answers.
 	finalErr := errors.New("no servers to resolve query")
 	for _, s := range e.Servers {
+		var pattern_and_name string
 		name := naming.JoinAddressName(s.Server, e.Name)
+		if pattern != "" {
+			pattern_and_name = naming.JoinAddressName(s.Server, fmt.Sprintf("[%s]%s", pattern, e.Name))
+		} else {
+			pattern_and_name = name
+		}
 		// First check the cache.
 		if ne, err := ns.resolutionCache.lookup(name); err == nil {
 			vlog.VI(2).Infof("resolveAMT %s from cache -> %v", name, convertServersToStrings(ne.Servers, ne.Name))
@@ -24,7 +31,7 @@
 		}
 		// Not in cache, call the real server.
 		callCtx, _ := ctx.WithTimeout(callTimeout)
-		call, err := client.StartCall(callCtx, name, "ResolveStepX", nil, options.NoResolve(true))
+		call, err := client.StartCall(callCtx, pattern_and_name, "ResolveStepX", nil, options.NoResolve(true))
 		if err != nil {
 			finalErr = err
 			vlog.VI(2).Infof("ResolveStep.StartCall %s failed: %s", name, err)
@@ -61,7 +68,7 @@
 }
 
 // ResolveX implements veyron2/naming.Namespace.
-func (ns *namespace) ResolveX(ctx context.T, name string) (*naming.MountEntry, error) {
+func (ns *namespace) ResolveX(ctx context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
 	defer vlog.LogCall()()
 	e, _ := ns.rootMountEntry(name)
 	if vlog.V(2) {
@@ -72,6 +79,7 @@
 	if len(e.Servers) == 0 {
 		return nil, verror.Make(naming.ErrNoSuchName, ctx, name)
 	}
+	pattern := getRootPattern(opts)
 	// Iterate walking through mount table servers.
 	for remaining := ns.maxResolveDepth; remaining > 0; remaining-- {
 		vlog.VI(2).Infof("ResolveX(%s) loop %v", name, *e)
@@ -81,7 +89,7 @@
 		}
 		var err error
 		curr := e
-		if e, err = ns.resolveAgainstMountTable(ctx, ns.rt.Client(), curr); err != nil {
+		if e, err = ns.resolveAgainstMountTable(ctx, ns.rt.Client(), curr, pattern); err != nil {
 			// If the name could not be found in the mount table, return an error.
 			if verror.Is(err, naming.ErrNoSuchNameRoot.ID) {
 				err = verror.Make(naming.ErrNoSuchName, ctx, name)
@@ -90,20 +98,26 @@
 				vlog.VI(1).Infof("ResolveX(%s) -> (NoSuchName: %v)", name, curr)
 				return nil, err
 			}
+			if verror.Is(err, verror.NotTrusted.ID) {
+				vlog.VI(1).Infof("ResolveX(%s) -> (NotTrusted: %v)", name, curr)
+				return nil, err
+
+			}
 			// Any other failure (server not found, no ResolveStep
 			// method, etc.) are a sign that iterative resolution can
 			// stop.
 			vlog.VI(1).Infof("ResolveX(%s) -> %v", name, curr)
 			return curr, nil
 		}
+		pattern = ""
 	}
 	return nil, verror.Make(naming.ErrResolutionDepthExceeded, ctx)
 }
 
 // Resolve implements veyron2/naming.Namespace.
-func (ns *namespace) Resolve(ctx context.T, name string) ([]string, error) {
+func (ns *namespace) Resolve(ctx context.T, name string, opts ...naming.ResolveOpt) ([]string, error) {
 	defer vlog.LogCall()()
-	e, err := ns.ResolveX(ctx, name)
+	e, err := ns.ResolveX(ctx, name, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -111,7 +125,7 @@
 }
 
 // ResolveToMountTableX implements veyron2/naming.Namespace.
-func (ns *namespace) ResolveToMountTableX(ctx context.T, name string) (*naming.MountEntry, error) {
+func (ns *namespace) ResolveToMountTableX(ctx context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
 	defer vlog.LogCall()()
 	e, _ := ns.rootMountEntry(name)
 	if vlog.V(2) {
@@ -122,6 +136,7 @@
 	if len(e.Servers) == 0 {
 		return nil, verror.Make(naming.ErrNoMountTable, ctx)
 	}
+	pattern := getRootPattern(opts)
 	last := e
 	for remaining := ns.maxResolveDepth; remaining > 0; remaining-- {
 		vlog.VI(2).Infof("ResolveToMountTableX(%s) loop %v", name, e)
@@ -132,7 +147,7 @@
 			vlog.VI(1).Infof("ResolveToMountTableX(%s) -> %v", name, last)
 			return last, nil
 		}
-		if e, err = ns.resolveAgainstMountTable(ctx, ns.rt.Client(), e); err != nil {
+		if e, err = ns.resolveAgainstMountTable(ctx, ns.rt.Client(), e, pattern); err != nil {
 			if verror.Is(err, naming.ErrNoSuchNameRoot.ID) {
 				vlog.VI(1).Infof("ResolveToMountTableX(%s) -> %v (NoSuchRoot: %v)", name, last, curr)
 				return last, nil
@@ -157,14 +172,15 @@
 			return nil, err
 		}
 		last = curr
+		pattern = ""
 	}
 	return nil, verror.Make(naming.ErrResolutionDepthExceeded, ctx)
 }
 
 // ResolveToMountTable implements veyron2/naming.Namespace.
-func (ns *namespace) ResolveToMountTable(ctx context.T, name string) ([]string, error) {
+func (ns *namespace) ResolveToMountTable(ctx context.T, name string, opts ...naming.ResolveOpt) ([]string, error) {
 	defer vlog.LogCall()()
-	e, err := ns.ResolveToMountTableX(ctx, name)
+	e, err := ns.ResolveToMountTableX(ctx, name, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -254,3 +270,12 @@
 	}
 	return flushed
 }
+
+func getRootPattern(opts []naming.ResolveOpt) string {
+	for _, opt := range opts {
+		if pattern, ok := opt.(naming.RootBlessingPatternOpt); ok {
+			return string(pattern)
+		}
+	}
+	return ""
+}
diff --git a/runtimes/google/rt/ipc.go b/runtimes/google/rt/ipc.go
index 9214839..98c1f91 100644
--- a/runtimes/google/rt/ipc.go
+++ b/runtimes/google/rt/ipc.go
@@ -109,14 +109,20 @@
 		otherOpts = append(otherOpts, rt.reservedOpts...)
 	}
 
+	// Add the preferred protocols from the runtime if there are any.
+	if len(rt.preferredProtocols) > 0 {
+		otherOpts = append(otherOpts, iipc.PreferredServerResolveProtocols(rt.preferredProtocols))
+	}
+
 	// Add the option that provides a discharge client to the server.
 	// TODO(cnicolaou): extend the timeout when parallel connections are
 	// going.
-	dc, err := iipc.InternalNewDischargeClient(sm, ns, rt.NewContext(), vc.LocalPrincipal{rt.principal}, &imanager.DialTimeout{5 * time.Second})
+	ctx := rt.NewContext()
+	dc, err := iipc.InternalNewDischargeClient(sm, ns, ctx, vc.LocalPrincipal{rt.principal}, &imanager.DialTimeout{5 * time.Second})
 	if err != nil {
 		return nil, fmt.Errorf("failed to create discharge-client: %v", err)
 	}
-	return iipc.InternalNewServer(rt.NewContext(), sm, ns, rt.traceStore, append(otherOpts, dc)...)
+	return iipc.InternalNewServer(ctx, sm, ns, rt.traceStore, append(otherOpts, dc)...)
 }
 
 func (rt *vrt) NewStreamManager(opts ...stream.ManagerOpt) (stream.Manager, error) {
diff --git a/runtimes/google/rt/ipc_test.go b/runtimes/google/rt/ipc_test.go
index 018817b..7f7c589 100644
--- a/runtimes/google/rt/ipc_test.go
+++ b/runtimes/google/rt/ipc_test.go
@@ -15,7 +15,6 @@
 	"veyron.io/veyron/veyron/lib/testutil"
 	tsecurity "veyron.io/veyron/veyron/lib/testutil/security"
 	"veyron.io/veyron/veyron/profiles"
-	vsecurity "veyron.io/veyron/veyron/security"
 	"veyron.io/veyron/veyron2/vdl/vdlutil"
 	"veyron.io/veyron/veyron2/verror"
 )
@@ -96,7 +95,7 @@
 		return nil, "", err
 	}
 	serverObjectName := naming.JoinAddressName(endpoint.String(), "")
-	if err := server.Serve("", s, vsecurity.NewACLAuthorizer(vsecurity.OpenACL())); err != nil {
+	if err := server.Serve("", s, allowEveryone{}); err != nil {
 		return nil, "", err
 	}
 	return server, serverObjectName, nil
@@ -277,3 +276,7 @@
 		t.Errorf("client.StartCall passed unexpectedly with remote end authenticated as: %v", remoteBlessings)
 	}
 }
+
+type allowEveryone struct{}
+
+func (allowEveryone) Authorize(security.Context) error { return nil }
diff --git a/runtimes/google/rt/mgmt_test.go b/runtimes/google/rt/mgmt_test.go
index defc3c7..cae8d50 100644
--- a/runtimes/google/rt/mgmt_test.go
+++ b/runtimes/google/rt/mgmt_test.go
@@ -116,7 +116,10 @@
 // TestNoWaiters verifies that the child process exits in the absence of any
 // wait channel being registered with its runtime.
 func TestNoWaiters(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 	h, err := sh.Start(noWaitersCmd, nil)
 	if err != nil {
@@ -143,7 +146,10 @@
 // TestForceStop verifies that ForceStop causes the child process to exit
 // immediately.
 func TestForceStop(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 	h, err := sh.Start(forceStopCmd, nil)
 	if err != nil {
@@ -295,7 +301,10 @@
 
 	childcreds := security.NewVeyronCredentials(r.Principal(), appCmd)
 	configServer, configServiceName, ch := createConfigServer(t, r)
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	sh.SetVar(consts.VeyronCredentials, childcreds)
 	sh.SetConfigKey(mgmt.ParentNameConfigKey, configServiceName)
 	sh.SetConfigKey(mgmt.ProtocolConfigKey, "tcp")
@@ -335,7 +344,6 @@
 	if err == nil || err.Error() != want {
 		t.Errorf("got %v, want %s", err, want)
 	}
-
 }
 
 // TestRemoteStop verifies that the child shuts down cleanly when sending it
diff --git a/runtimes/google/rt/rt_test.go b/runtimes/google/rt/rt_test.go
index 3f244fb..eb8e14b 100644
--- a/runtimes/google/rt/rt_test.go
+++ b/runtimes/google/rt/rt_test.go
@@ -26,7 +26,6 @@
 	testutil.Init()
 	modules.RegisterChild("child", "", child)
 	modules.RegisterChild("principal", "", principal)
-	modules.RegisterChild("mutate", "", mutatePrincipal)
 	modules.RegisterChild("runner", "", runner)
 }
 
@@ -43,7 +42,7 @@
 	args := fmt.Sprintf("%s", l)
 	expected := regexp.MustCompile("name=veyron logdirs=\\[/tmp\\] logtostderr=true|false alsologtostderr=false|true max_stack_buf_size=4292608 v=[0-9] stderrthreshold=2 vmodule= log_backtrace_at=:0")
 	if !expected.MatchString(args) {
-		t.Errorf("unexpected default args: %q", args)
+		t.Errorf("unexpected default args: %s", args)
 	}
 	p := r.Principal()
 	if p == nil {
@@ -70,9 +69,12 @@
 }
 
 func TestInitArgs(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
-	h, err := sh.Start("child", nil, "--logtostderr=true", "--vv=3", "--", "foobar")
+	h, err := sh.Start("child", nil, "--logtostderr=true", "--vmodule=*=3", "--", "foobar")
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -82,9 +84,9 @@
 		"logtostderr=true "+
 		"alsologtostderr=true "+
 		"max_stack_buf_size=4292608 "+
-		"v=3 "+
+		"v=0 "+
 		"stderrthreshold=2 "+
-		"vmodule= "+
+		"vmodule=*=3 "+
 		"log_backtrace_at=:0",
 		os.TempDir()))
 	h.CloseStdin()
@@ -100,7 +102,6 @@
 	blessings := p.BlessingStore().Default()
 	if blessings == nil {
 		return fmt.Errorf("rt.Principal().BlessingStore().Default() returned nil")
-
 	}
 	ctx := security.NewContext(&security.ContextParams{LocalPrincipal: p})
 	if n := len(blessings.ForContext(ctx)); n != 1 {
@@ -109,6 +110,10 @@
 	return nil
 }
 
+func defaultBlessing(p security.Principal) string {
+	return p.BlessingStore().Default().ForContext(security.NewContext(&security.ContextParams{LocalPrincipal: p}))[0]
+}
+
 func tmpDir(t *testing.T) string {
 	dir, err := ioutil.TempDir("", "rt_test_dir")
 	if err != nil {
@@ -119,10 +124,10 @@
 
 func principal(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
 	r := rt.Init()
-	err := validatePrincipal(r.Principal())
-	fmt.Fprintf(stdout, "ERROR=%v\n", err)
-	fmt.Fprintf(stdout, "PUBKEY=%s\n", r.Principal().PublicKey())
-	modules.WaitForEOF(stdin)
+	if err := validatePrincipal(r.Principal()); err != nil {
+		return err
+	}
+	fmt.Fprintf(stdout, "DEFAULT_BLESSING=%s\n", defaultBlessing(r.Principal()))
 	return nil
 }
 
@@ -130,77 +135,48 @@
 // own security info and it's childs.
 func runner(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
 	r := rt.Init()
-	err := validatePrincipal(r.Principal())
-	fmt.Fprintf(stdout, "RUNNER_ERROR=%v\n", err)
-	fmt.Fprintf(stdout, "RUNNER_PUBKEY=%s\n", r.Principal().PublicKey())
+	if err := validatePrincipal(r.Principal()); err != nil {
+		return err
+	}
+	fmt.Fprintf(stdout, "RUNNER_DEFAULT_BLESSING=%v\n", defaultBlessing(r.Principal()))
+	sh, err := modules.NewShell(nil)
 	if err != nil {
 		return err
 	}
-	sh := modules.NewShell()
-	_, err = sh.Start("principal", nil, args[1:]...)
-	if err != nil {
+	if _, err := sh.Start("principal", nil, args[1:]...); err != nil {
 		return err
 	}
 	// Cleanup copies the output of sh to these Writers.
 	sh.Cleanup(stdout, stderr)
-	modules.WaitForEOF(stdin)
 	return nil
 }
 
-func mutatePrincipal(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
-	r := rt.Init()
-
-	rtPrincipal := r.Principal()
-	err := validatePrincipal(rtPrincipal)
-	fmt.Fprintf(stdout, "ERROR=%v\n", err)
-
-	// Mutate the roots and store of this principal.
-	blessing, err := rtPrincipal.BlessSelf("irrelevant")
-	if err != nil {
-		return err
-	}
-	if _, err := rtPrincipal.BlessingStore().Set(blessing, security.AllPrincipals); err != nil {
-		return err
-	}
-	if err := rtPrincipal.AddToRoots(blessing); err != nil {
-		return err
-	}
-	newRT, err := rt.New(profileOpt)
-	if err != nil {
-		return fmt.Errorf("rt.New failed: %v", err)
-	}
-	// Test that the same principal gets initialized on creating a new runtime
-	// from the same credentials directory.
-	if got := newRT.Principal(); !reflect.DeepEqual(got, rtPrincipal) {
-		return fmt.Errorf("Initialized Principal: %v, expected: %v", got.PublicKey(), rtPrincipal.PublicKey())
-	}
-	fmt.Fprintf(stdout, "PUBKEY=%s\n", newRT.Principal().PublicKey())
-	modules.WaitForEOF(stdin)
-	return nil
-}
-
-func createCredentialsInDir(t *testing.T, dir string) security.Principal {
+func createCredentialsInDir(t *testing.T, dir string, blessing string) {
 	principal, err := vsecurity.CreatePersistentPrincipal(dir, nil)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
-	vsecurity.InitDefaultBlessings(principal, "test")
-	return principal
+	if err := vsecurity.InitDefaultBlessings(principal, blessing); err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 }
 
 func TestPrincipalInheritance(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer func() {
 		sh.Cleanup(os.Stdout, os.Stderr)
 	}()
 
-	// Test that the child inherits the parent's credentials correctly.
+	// Test that the child inherits from the parent's credentials correctly.
 	// The running test process may or may not have a credentials directory set
 	// up so we have to use a 'runner' process to ensure the correct setup.
 	cdir := tmpDir(t)
 	defer os.RemoveAll(cdir)
 
-	principal := createCredentialsInDir(t, cdir)
+	createCredentialsInDir(t, cdir, "test")
 
 	// directory supplied by the environment.
 	credEnv := []string{consts.VeyronCredentials + "=" + cdir}
@@ -209,41 +185,33 @@
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
-	s := expect.NewSession(t, h.Stdout(), 2*time.Second) //time.Minute)
-	runnerErr := s.ExpectVar("RUNNER_ERROR")
-	runnerPubKey := s.ExpectVar("RUNNER_PUBKEY")
-	principalErr := s.ExpectVar("ERROR")
-	principalPubKey := s.ExpectVar("PUBKEY")
+
+	s := expect.NewSession(t, h.Stdout(), time.Minute)
+	runnerBlessing := s.ExpectVar("RUNNER_DEFAULT_BLESSING")
+	principalBlessing := s.ExpectVar("DEFAULT_BLESSING")
 	if err := s.Error(); err != nil {
 		t.Fatalf("failed to read input from children: %s", err)
 	}
 	h.Shutdown(os.Stdout, os.Stderr)
-	if runnerErr != "<nil>" || principalErr != "<nil>" {
-		t.Fatalf("unexpected error: runner %q, principal %q", runnerErr, principalErr)
-	}
-	pubKey := principal.PublicKey().String()
-	if runnerPubKey != pubKey || principalPubKey != pubKey {
-		t.Fatalf("unexpected pubkeys: expected %s: runner %s, principal %s",
-			pubKey, runnerPubKey, principalPubKey)
+
+	wantRunnerBlessing := "test"
+	wantPrincipalBlessing := "test/child"
+	if runnerBlessing != wantRunnerBlessing || principalBlessing != wantPrincipalBlessing {
+		t.Fatalf("unexpected default blessing: got runner %s, principal %s, want runner %s, principal %s", runnerBlessing, principalBlessing, wantRunnerBlessing, wantPrincipalBlessing)
 	}
 
 }
 
 func TestPrincipalInit(t *testing.T) {
-	// Collet the process' public key and error status
-	collect := func(sh *modules.Shell, cmd string, env []string, args ...string) (string, error) {
-		h, err := sh.Start(cmd, env, args...)
+	// Collect the process' public key and error status
+	collect := func(sh *modules.Shell, env []string, args ...string) string {
+		h, err := sh.Start("principal", env, args...)
 		if err != nil {
 			t.Fatalf("unexpected error: %s", err)
 		}
 		s := expect.NewSession(t, h.Stdout(), time.Minute)
 		s.SetVerbosity(testing.Verbose())
-		errstr := s.ExpectVar("ERROR")
-		pubkey := s.ExpectVar("PUBKEY")
-		if errstr != "<nil>" {
-			return pubkey, fmt.Errorf("%s", errstr)
-		}
-		return pubkey, nil
+		return s.ExpectVar("DEFAULT_BLESSING")
 	}
 
 	// A credentials directory may, or may, not have been already specified.
@@ -257,55 +225,36 @@
 		t.Fatal(err)
 	}
 
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 
-	pubkey, err := collect(sh, "principal", nil)
-	if err != nil {
-		t.Fatalf("child failed to create+validate principal: %v", err)
-	}
-	if len(pubkey) == 0 {
-		t.Fatalf("child failed to return a public key")
+	blessing := collect(sh, nil)
+	if len(blessing) == 0 {
+		t.Fatalf("child returned an empty default blessings set")
 	}
 
-	// Test specifying credentials via VEYRON_CREDENTIALS
+	// Test specifying credentials via VEYRON_CREDENTIALS environment.
 	cdir1 := tmpDir(t)
 	defer os.RemoveAll(cdir1)
-	principal := createCredentialsInDir(t, cdir1)
-	// directory supplied by the environment.
+	createCredentialsInDir(t, cdir1, "test_env")
 	credEnv := []string{consts.VeyronCredentials + "=" + cdir1}
 
-	pubkey, err = collect(sh, "principal", credEnv)
-	if err != nil {
-		t.Errorf("unexpected error: %s", err)
-	}
-
-	if got, want := pubkey, principal.PublicKey().String(); got != want {
-		t.Errorf("got %q, want %q", got, want)
+	blessing = collect(sh, credEnv)
+	if got, want := blessing, "test_env"; got != want {
+		t.Errorf("got default blessings: %q, want %q", got, want)
 	}
 
 	// Test specifying credentials via the command line and that the
 	// comand line overrides the environment
 	cdir2 := tmpDir(t)
 	defer os.RemoveAll(cdir2)
-	clPrincipal := createCredentialsInDir(t, cdir2)
+	createCredentialsInDir(t, cdir2, "test_cmd")
 
-	pubkey, err = collect(sh, "principal", credEnv, "--veyron.credentials="+cdir2)
-	if err != nil {
-		t.Errorf("unexpected error: %s", err)
-	}
-
-	if got, want := pubkey, clPrincipal.PublicKey().String(); got != want {
-		t.Errorf("got %q, want %q", got, want)
-	}
-
-	// Mutate the roots and store of the principal in the child process.
-	pubkey, err = collect(sh, "mutate", credEnv, "--veyron.credentials="+cdir2)
-	if err != nil {
-		t.Errorf("unexpected error: %s", err)
-	}
-
-	if got, want := pubkey, clPrincipal.PublicKey().String(); got != want {
+	blessing = collect(sh, credEnv, "--veyron.credentials="+cdir2)
+	if got, want := blessing, "test_cmd"; got != want {
 		t.Errorf("got %q, want %q", got, want)
 	}
 }
diff --git a/runtimes/google/rt/shutdown_servers_test.go b/runtimes/google/rt/shutdown_servers_test.go
index 3e3f730..cba2006 100644
--- a/runtimes/google/rt/shutdown_servers_test.go
+++ b/runtimes/google/rt/shutdown_servers_test.go
@@ -47,7 +47,6 @@
 func remoteCmdLoop(stdin io.Reader) func() {
 	done := make(chan struct{})
 	go func() {
-		defer close(done)
 		scanner := bufio.NewScanner(stdin)
 		for scanner.Scan() {
 			switch scanner.Text() {
@@ -57,6 +56,7 @@
 				fmt.Println("straight exit")
 				rt.R().AppCycle().ForceStop()
 			case "close":
+				close(done)
 				return
 			}
 		}
@@ -76,7 +76,7 @@
 	// commands from the parent process to simulate Stop and
 	// RemoteStop commands that would normally be issued from
 	// application code.
-	go remoteCmdLoop(stdin)()
+	defer remoteCmdLoop(stdin)()
 
 	// r.Cleanup is optional, but it's a good idea to clean up, especially
 	// since it takes care of flushing the logs before exiting.
@@ -128,7 +128,7 @@
 		case <-stopChan:
 		}
 		<-blockingCh
-		os.Exit(1)
+		os.Exit(signals.DoubleStopExitCode)
 	}()
 
 	// This communicates to the parent test driver process in our unit test
@@ -219,7 +219,7 @@
 	// commands from the parent process to simulate Stop and
 	// RemoteStop commands that would normally be issued from
 	// application code.
-	go remoteCmdLoop(stdin)()
+	defer remoteCmdLoop(stdin)()
 
 	// r.Cleanup is optional, but it's a good idea to clean up, especially
 	// since it takes care of flushing the logs before exiting.
@@ -238,7 +238,7 @@
 	// Note, if the developer wants to exit immediately upon receiving a
 	// signal or stop command, they can skip this, in which case the default
 	// behavior is for the process to exit.
-	waiter := signals.ShutdownOnSignals()
+	waiter := signals.ShutdownOnSignals(r)
 
 	// This communicates to the parent test driver process in our unit test
 	// that this server is ready and waiting on signals or stop commands.
diff --git a/runtimes/google/rt/shutdown_test.go b/runtimes/google/rt/shutdown_test.go
index f0a57aa..4ee9468 100644
--- a/runtimes/google/rt/shutdown_test.go
+++ b/runtimes/google/rt/shutdown_test.go
@@ -25,10 +25,18 @@
 	}
 }
 
+func newShell(t *testing.T) *modules.Shell {
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
+	return sh
+}
+
 // TestSimpleServerSignal verifies that sending a signal to the simple server
 // causes it to exit cleanly.
 func TestSimpleServerSignal(t *testing.T) {
-	sh := modules.NewShell()
+	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("simpleServerProgram", nil)
 	s := expect.NewSession(t, h.Stdout(), time.Minute)
@@ -44,7 +52,7 @@
 // TestSimpleServerLocalStop verifies that sending a local stop command to the
 // simple server causes it to exit cleanly.
 func TestSimpleServerLocalStop(t *testing.T) {
-	sh := modules.NewShell()
+	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("simpleServerProgram", nil)
 	s := expect.NewSession(t, h.Stdout(), time.Minute)
@@ -61,7 +69,7 @@
 // signals to the simple server causes it to initiate the cleanup sequence on
 // the first signal and then exit immediately on the second signal.
 func TestSimpleServerDoubleSignal(t *testing.T) {
-	sh := modules.NewShell()
+	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("simpleServerProgram", nil)
 	s := expect.NewSession(t, h.Stdout(), time.Minute)
@@ -81,7 +89,7 @@
 // TestSimpleServerLocalForceStop verifies that sending a local ForceStop
 // command to the simple server causes it to exit immediately.
 func TestSimpleServerLocalForceStop(t *testing.T) {
-	sh := modules.NewShell()
+	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("simpleServerProgram", nil)
 	s := expect.NewSession(t, h.Stdout(), time.Minute)
@@ -100,7 +108,7 @@
 // TestSimpleServerKill demonstrates that a SIGKILL still forces the server
 // to exit regardless of our signal handling.
 func TestSimpleServerKill(t *testing.T) {
-	sh := modules.NewShell()
+	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("simpleServerProgram", nil)
 	s := expect.NewSession(t, h.Stdout(), time.Minute)
@@ -120,7 +128,7 @@
 // corresponding to all the simulated sequential/parallel and
 // blocking/interruptible shutdown steps), and then exits cleanly.
 func TestComplexServerSignal(t *testing.T) {
-	sh := modules.NewShell()
+	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("complexServerProgram", nil)
 	s := expect.NewSession(t, h.Stdout(), time.Minute)
@@ -142,7 +150,7 @@
 // printouts corresponding to all the simulated sequential/parallel and
 // blocking/interruptible shutdown steps), and then exits cleanly.
 func TestComplexServerLocalStop(t *testing.T) {
-	sh := modules.NewShell()
+	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("complexServerProgram", nil)
 	s := expect.NewSession(t, h.Stdout(), time.Minute)
@@ -169,7 +177,7 @@
 // the corresponding printouts from the server).  Note that we have no
 // expectations on whether or not the interruptible shutdown steps execute.
 func TestComplexServerDoubleSignal(t *testing.T) {
-	sh := modules.NewShell()
+	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("complexServerProgram", nil)
 	s := expect.NewSession(t, h.Stdout(), time.Minute)
@@ -193,7 +201,7 @@
 // TestComplexServerLocalForceStop verifies that sending a local ForceStop
 // command to the complex server forces it to exit immediately.
 func TestComplexServerLocalForceStop(t *testing.T) {
-	sh := modules.NewShell()
+	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("complexServerProgram", nil)
 	s := expect.NewSession(t, h.Stdout(), time.Minute)
@@ -212,7 +220,7 @@
 // TestComplexServerKill demonstrates that a SIGKILL still forces the server to
 // exit regardless of our signal handling.
 func TestComplexServerKill(t *testing.T) {
-	sh := modules.NewShell()
+	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("complexServerProgram", nil)
 	s := expect.NewSession(t, h.Stdout(), time.Minute)
diff --git a/runtimes/google/rt/signal_test.go b/runtimes/google/rt/signal_test.go
index df93748..2d819a9 100644
--- a/runtimes/google/rt/signal_test.go
+++ b/runtimes/google/rt/signal_test.go
@@ -73,7 +73,10 @@
 }
 
 func TestWithRuntime(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 	h, err := sh.Start("withRuntime", nil)
 	if err != nil {
@@ -90,7 +93,10 @@
 }
 
 func TestWithoutRuntime(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 	h, err := sh.Start("withoutRuntime", nil)
 	if err != nil {
diff --git a/runtimes/google/testing/mocks/naming/namespace.go b/runtimes/google/testing/mocks/naming/namespace.go
index bff47f6..e3403e5 100644
--- a/runtimes/google/testing/mocks/naming/namespace.go
+++ b/runtimes/google/testing/mocks/naming/namespace.go
@@ -8,7 +8,7 @@
 
 	"veyron.io/veyron/veyron2/context"
 	"veyron.io/veyron/veyron2/naming"
-	"veyron.io/veyron/veyron2/verror"
+	verror "veyron.io/veyron/veyron2/verror2"
 	"veyron.io/veyron/veyron2/vlog"
 )
 
@@ -57,7 +57,7 @@
 	return nil
 }
 
-func (ns *namespace) Resolve(ctx context.T, name string) ([]string, error) {
+func (ns *namespace) Resolve(ctx context.T, name string, opts ...naming.ResolveOpt) ([]string, error) {
 	defer vlog.LogCall()()
 	if address, _ := naming.SplitAddressName(name); len(address) > 0 {
 		return []string{name}, nil
@@ -74,10 +74,10 @@
 			return ret, nil
 		}
 	}
-	return nil, verror.NoExistf("Resolve name %q not found in %v", name, ns.mounts)
+	return nil, verror.Make(naming.ErrNoSuchName, ctx, fmt.Sprintf("Resolve name %q not found in %v", name, ns.mounts))
 }
 
-func (ns *namespace) ResolveX(ctx context.T, name string) (*naming.MountEntry, error) {
+func (ns *namespace) ResolveX(ctx context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
 	defer vlog.LogCall()()
 	e := new(naming.MountEntry)
 	if address, _ := naming.SplitAddressName(name); len(address) > 0 {
@@ -95,17 +95,17 @@
 			return e, nil
 		}
 	}
-	return nil, verror.NoExistf("Resolve name %q not found in %v", name, ns.mounts)
+	return nil, verror.Make(naming.ErrNoSuchName, ctx, fmt.Sprintf("Resolve name %q not found in %v", name, ns.mounts))
 }
 
-func (ns *namespace) ResolveToMountTableX(ctx context.T, name string) (*naming.MountEntry, error) {
+func (ns *namespace) ResolveToMountTableX(ctx context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
 	defer vlog.LogCall()()
 	// TODO(mattr): Implement this method for tests that might need it.
 	panic("ResolveToMountTable not implemented")
 	return nil, nil
 }
 
-func (ns *namespace) ResolveToMountTable(ctx context.T, name string) ([]string, error) {
+func (ns *namespace) ResolveToMountTable(ctx context.T, name string, opts ...naming.ResolveOpt) ([]string, error) {
 	defer vlog.LogCall()()
 	// TODO(mattr): Implement this method for tests that might need it.
 	panic("ResolveToMountTable not implemented")
diff --git a/runtimes/google/testing/mocks/runtime/panic_runtime.go b/runtimes/google/testing/mocks/runtime/panic_runtime.go
index d70852b..292beef 100644
--- a/runtimes/google/testing/mocks/runtime/panic_runtime.go
+++ b/runtimes/google/testing/mocks/runtime/panic_runtime.go
@@ -8,6 +8,7 @@
 	"veyron.io/veyron/veyron2/ipc/stream"
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/security"
+	"veyron.io/veyron/veyron2/uniqueid"
 	"veyron.io/veyron/veyron2/vlog"
 	"veyron.io/veyron/veyron2/vtrace"
 )
@@ -17,20 +18,23 @@
 // implementation but you don't want it to be used.
 type PanicRuntime struct {
 	unique int // Make non-empty to ensure pointer instances are unique.
+
 }
 
 const badRuntime = "The runtime implmentation should not call methods on runtime intances."
 
-func (*PanicRuntime) Profile() veyron2.Profile                               { panic(badRuntime) }
-func (*PanicRuntime) AppCycle() veyron2.AppCycle                             { panic(badRuntime) }
-func (*PanicRuntime) Publisher() *config.Publisher                           { panic(badRuntime) }
-func (*PanicRuntime) Principal() security.Principal                          { panic(badRuntime) }
-func (*PanicRuntime) NewClient(opts ...ipc.ClientOpt) (ipc.Client, error)    { panic(badRuntime) }
-func (*PanicRuntime) NewServer(opts ...ipc.ServerOpt) (ipc.Server, error)    { panic(badRuntime) }
-func (*PanicRuntime) Client() ipc.Client                                     { panic(badRuntime) }
-func (*PanicRuntime) NewContext() context.T                                  { panic(badRuntime) }
-func (*PanicRuntime) WithNewSpan(context.T, string) (context.T, vtrace.Span) { panic(badRuntime) }
-func (*PanicRuntime) SpanFromContext(context.T) vtrace.Span                  { panic(badRuntime) }
+func (*PanicRuntime) Profile() veyron2.Profile                            { panic(badRuntime) }
+func (*PanicRuntime) AppCycle() veyron2.AppCycle                          { panic(badRuntime) }
+func (*PanicRuntime) Publisher() *config.Publisher                        { panic(badRuntime) }
+func (*PanicRuntime) Principal() security.Principal                       { panic(badRuntime) }
+func (*PanicRuntime) NewClient(opts ...ipc.ClientOpt) (ipc.Client, error) { panic(badRuntime) }
+func (*PanicRuntime) NewServer(opts ...ipc.ServerOpt) (ipc.Server, error) { panic(badRuntime) }
+func (*PanicRuntime) Client() ipc.Client                                  { panic(badRuntime) }
+func (*PanicRuntime) NewContext() context.T                               { panic(badRuntime) }
+
+func (PanicRuntime) WithNewSpan(c context.T, m string) (context.T, vtrace.Span) { return c, &span{m} }
+
+func (*PanicRuntime) SpanFromContext(context.T) vtrace.Span { return &span{} }
 func (*PanicRuntime) NewStreamManager(opts ...stream.ManagerOpt) (stream.Manager, error) {
 	panic(badRuntime)
 }
@@ -45,3 +49,13 @@
 }
 func (*PanicRuntime) VtraceStore() vtrace.Store { panic(badRuntime) }
 func (*PanicRuntime) Cleanup()                  { panic(badRuntime) }
+
+type span struct{ m string }
+
+func (s *span) Name() string                   { return s.m + ".panic" }
+func (*span) ID() uniqueid.ID                  { return uniqueid.ID{} }
+func (s *span) Parent() uniqueid.ID            { return s.ID() }
+func (*span) Annotate(string)                  {}
+func (*span) Annotatef(string, ...interface{}) {}
+func (*span) Finish()                          {}
+func (*span) Trace() vtrace.Trace              { return nil }
diff --git a/runtimes/google/vtrace/store.go b/runtimes/google/vtrace/store.go
index f70dc2a..7ab0a0a 100644
--- a/runtimes/google/vtrace/store.go
+++ b/runtimes/google/vtrace/store.go
@@ -62,7 +62,7 @@
 	s.mu.Lock()
 	defer s.mu.Unlock()
 
-	out := make([]vtrace.TraceRecord, s.size)
+	out := make([]vtrace.TraceRecord, len(s.traces))
 	i := 0
 	for _, ts := range s.traces {
 		ts.traceRecord(&out[i])
diff --git a/runtimes/google/vtrace/vtrace.go b/runtimes/google/vtrace/vtrace.go
index 04da3e3..7f7a2a9 100644
--- a/runtimes/google/vtrace/vtrace.go
+++ b/runtimes/google/vtrace/vtrace.go
@@ -4,6 +4,7 @@
 package vtrace
 
 import (
+	"fmt"
 	"time"
 
 	"veyron.io/veyron/veyron2/context"
@@ -41,8 +42,13 @@
 func (c *span) Parent() uniqueid.ID { return c.parent }
 func (c *span) Name() string        { return c.name }
 func (c *span) Trace() vtrace.Trace { return c.collector }
-func (c *span) Annotate(msg string) { c.collector.annotate(c, msg) }
-func (c *span) Finish()             { c.collector.finish(c) }
+func (c *span) Annotate(s string) {
+	c.collector.annotate(c, s)
+}
+func (c *span) Annotatef(format string, a ...interface{}) {
+	c.collector.annotate(c, fmt.Sprintf(format, a...))
+}
+func (c *span) Finish() { c.collector.finish(c) }
 
 // Request generates a vtrace.Request from the active Span.
 func Request(ctx context.T) vtrace.Request {
diff --git a/runtimes/google/vtrace/vtrace_test.go b/runtimes/google/vtrace/vtrace_test.go
index 07ebd2e..bc9cb87 100644
--- a/runtimes/google/vtrace/vtrace_test.go
+++ b/runtimes/google/vtrace/vtrace_test.go
@@ -134,7 +134,9 @@
 }
 
 func expectSequence(t *testing.T, trace vtrace.TraceRecord, expectedSpans []string) {
-	if got, want := len(trace.Spans), len(expectedSpans); got != want {
+	// It's okay to have additional spans - someone may have inserted
+	// additional spans for more debugging.
+	if got, want := len(trace.Spans), len(expectedSpans); got < want {
 		t.Errorf("Found %d spans, want %d", got, want)
 	}
 
diff --git a/security/acl/acl.go b/security/acl/acl.go
deleted file mode 100644
index 3971530..0000000
--- a/security/acl/acl.go
+++ /dev/null
@@ -1,44 +0,0 @@
-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
deleted file mode 100644
index 51bc01c..0000000
--- a/security/acl/acl.vdl
+++ /dev/null
@@ -1,38 +0,0 @@
-// 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
deleted file mode 100644
index 4a658de..0000000
--- a/security/acl/acl.vdl.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// 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
deleted file mode 100644
index 4187b18..0000000
--- a/security/acl/acl_test.go
+++ /dev/null
@@ -1,86 +0,0 @@
-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
deleted file mode 100644
index f4d60c9..0000000
--- a/security/acl/authorizer.go
+++ /dev/null
@@ -1,150 +0,0 @@
-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
deleted file mode 100644
index 27803f0..0000000
--- a/security/acl/authorizer_test.go
+++ /dev/null
@@ -1,224 +0,0 @@
-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(name string) []interface{} {
-	server := test.MyObjectServer(nil)
-	for _, iface := range server.Describe__() {
-		for _, method := range iface.Methods {
-			if method.Name == name {
-				tags := make([]interface{}, len(method.Tags))
-				for index, tag := range method.Tags {
-					tags[index] = tag
-				}
-				return tags
-			}
-		}
-	}
-	return nil
-}
diff --git a/security/acl/test/vdl.vdl b/security/acl/test/vdl.vdl
deleted file mode 100644
index fd3a73f..0000000
--- a/security/acl/test/vdl.vdl
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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
deleted file mode 100644
index 284a509..0000000
--- a/security/acl/test/vdl.vdl.go
+++ /dev/null
@@ -1,301 +0,0 @@
-// 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 "__" to prevent collisions.
-	__veyron2 "veyron.io/veyron/veyron2"
-	__context "veyron.io/veyron/veyron2/context"
-	__ipc "veyron.io/veyron/veyron2/ipc"
-	__vdlutil "veyron.io/veyron/veyron2/vdl/vdlutil"
-	__wiretype "veyron.io/veyron/veyron2/wiretype"
-)
-
-// TODO(toddw): Remove this line once the new signature support is done.
-// It corrects a bug where __wiretype is unused in VDL pacakges where only
-// bootstrap types are used on interfaces.
-const _ = __wiretype.TypeIDInvalid
-
-// 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")
-
-// MyObjectClientMethods is the client interface
-// containing MyObject methods.
-//
-// MyObject demonstrates how tags are attached to methods.
-type MyObjectClientMethods interface {
-	Get(__context.T, ...__ipc.CallOpt) error
-	Put(__context.T, ...__ipc.CallOpt) error
-	Resolve(__context.T, ...__ipc.CallOpt) error
-	NoTags(__context.T, ...__ipc.CallOpt) error // No tags attached to this.
-	AllTags(__context.T, ...__ipc.CallOpt) error
-}
-
-// MyObjectClientStub adds universal methods to MyObjectClientMethods.
-type MyObjectClientStub interface {
-	MyObjectClientMethods
-	__ipc.UniversalServiceMethods
-}
-
-// MyObjectClient returns a client stub for MyObject.
-func MyObjectClient(name string, opts ...__ipc.BindOpt) MyObjectClientStub {
-	var client __ipc.Client
-	for _, opt := range opts {
-		if clientOpt, ok := opt.(__ipc.Client); ok {
-			client = clientOpt
-		}
-	}
-	return implMyObjectClientStub{name, client}
-}
-
-type implMyObjectClientStub struct {
-	name   string
-	client __ipc.Client
-}
-
-func (c implMyObjectClientStub) c(ctx __context.T) __ipc.Client {
-	if c.client != nil {
-		return c.client
-	}
-	return __veyron2.RuntimeFromContext(ctx).Client()
-}
-
-func (c implMyObjectClientStub) Get(ctx __context.T, opts ...__ipc.CallOpt) (err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "Get", nil, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
-func (c implMyObjectClientStub) Put(ctx __context.T, opts ...__ipc.CallOpt) (err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "Put", nil, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
-func (c implMyObjectClientStub) Resolve(ctx __context.T, opts ...__ipc.CallOpt) (err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "Resolve", nil, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
-func (c implMyObjectClientStub) NoTags(ctx __context.T, opts ...__ipc.CallOpt) (err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "NoTags", nil, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
-func (c implMyObjectClientStub) AllTags(ctx __context.T, opts ...__ipc.CallOpt) (err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "AllTags", nil, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
-func (c implMyObjectClientStub) Signature(ctx __context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&o0, &err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
-// MyObjectServerMethods is the interface a server writer
-// implements for MyObject.
-//
-// MyObject demonstrates how tags are attached to methods.
-type MyObjectServerMethods interface {
-	Get(__ipc.ServerContext) error
-	Put(__ipc.ServerContext) error
-	Resolve(__ipc.ServerContext) error
-	NoTags(__ipc.ServerContext) error // No tags attached to this.
-	AllTags(__ipc.ServerContext) error
-}
-
-// MyObjectServerStubMethods is the server interface containing
-// MyObject methods, as expected by ipc.Server.
-// There is no difference between this interface and MyObjectServerMethods
-// since there are no streaming methods.
-type MyObjectServerStubMethods MyObjectServerMethods
-
-// MyObjectServerStub adds universal methods to MyObjectServerStubMethods.
-type MyObjectServerStub interface {
-	MyObjectServerStubMethods
-	// Describe the MyObject interfaces.
-	Describe__() []__ipc.InterfaceDesc
-	// Signature will be replaced with Describe__.
-	Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
-}
-
-// MyObjectServer returns a server stub for MyObject.
-// It converts an implementation of MyObjectServerMethods into
-// an object that may be used by ipc.Server.
-func MyObjectServer(impl MyObjectServerMethods) MyObjectServerStub {
-	stub := implMyObjectServerStub{
-		impl: impl,
-	}
-	// Initialize GlobState; always check the stub itself first, to handle the
-	// case where the user has the Glob method defined in their VDL source.
-	if gs := __ipc.NewGlobState(stub); gs != nil {
-		stub.gs = gs
-	} else if gs := __ipc.NewGlobState(impl); gs != nil {
-		stub.gs = gs
-	}
-	return stub
-}
-
-type implMyObjectServerStub struct {
-	impl MyObjectServerMethods
-	gs   *__ipc.GlobState
-}
-
-func (s implMyObjectServerStub) Get(ctx __ipc.ServerContext) error {
-	return s.impl.Get(ctx)
-}
-
-func (s implMyObjectServerStub) Put(ctx __ipc.ServerContext) error {
-	return s.impl.Put(ctx)
-}
-
-func (s implMyObjectServerStub) Resolve(ctx __ipc.ServerContext) error {
-	return s.impl.Resolve(ctx)
-}
-
-func (s implMyObjectServerStub) NoTags(ctx __ipc.ServerContext) error {
-	return s.impl.NoTags(ctx)
-}
-
-func (s implMyObjectServerStub) AllTags(ctx __ipc.ServerContext) error {
-	return s.impl.AllTags(ctx)
-}
-
-func (s implMyObjectServerStub) VGlob() *__ipc.GlobState {
-	return s.gs
-}
-
-func (s implMyObjectServerStub) Describe__() []__ipc.InterfaceDesc {
-	return []__ipc.InterfaceDesc{MyObjectDesc}
-}
-
-// MyObjectDesc describes the MyObject interface.
-var MyObjectDesc __ipc.InterfaceDesc = descMyObject
-
-// descMyObject hides the desc to keep godoc clean.
-var descMyObject = __ipc.InterfaceDesc{
-	Name:    "MyObject",
-	PkgPath: "veyron.io/veyron/veyron/security/acl/test",
-	Doc:     "// MyObject demonstrates how tags are attached to methods.",
-	Methods: []__ipc.MethodDesc{
-		{
-			Name: "Get",
-			OutArgs: []__ipc.ArgDesc{
-				{"", ``}, // error
-			},
-			Tags: []__vdlutil.Any{MyTag("R")},
-		},
-		{
-			Name: "Put",
-			OutArgs: []__ipc.ArgDesc{
-				{"", ``}, // error
-			},
-			Tags: []__vdlutil.Any{MyTag("W")},
-		},
-		{
-			Name: "Resolve",
-			OutArgs: []__ipc.ArgDesc{
-				{"", ``}, // error
-			},
-			Tags: []__vdlutil.Any{MyTag("X")},
-		},
-		{
-			Name: "NoTags",
-			OutArgs: []__ipc.ArgDesc{
-				{"", ``}, // error
-			},
-		},
-		{
-			Name: "AllTags",
-			OutArgs: []__ipc.ArgDesc{
-				{"", ``}, // error
-			},
-			Tags: []__vdlutil.Any{MyTag("R"), MyTag("W"), MyTag("X")},
-		},
-	},
-}
-
-func (s implMyObjectServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
-	// TODO(toddw): Replace with new Describe__ implementation.
-	result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
-	result.Methods["AllTags"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 65},
-		},
-	}
-	result.Methods["Get"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 65},
-		},
-	}
-	result.Methods["NoTags"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 65},
-		},
-	}
-	result.Methods["Put"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 65},
-		},
-	}
-	result.Methods["Resolve"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 65},
-		},
-	}
-
-	result.TypeDefs = []__vdlutil.Any{
-		__wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
-
-	return result, nil
-}
diff --git a/security/acl_authorizer.go b/security/acl_authorizer.go
deleted file mode 100644
index 2adfa80..0000000
--- a/security/acl_authorizer.go
+++ /dev/null
@@ -1,104 +0,0 @@
-package security
-
-// This file provides an implementation of security.Authorizer.
-//
-// Definitions
-// * Self-RPC: An RPC request is said to be a "self-RPC" if the identities
-// at the local and remote ends are identical.
-
-import (
-	"errors"
-	"os"
-	"reflect"
-
-	"veyron.io/veyron/veyron2/security"
-)
-
-var (
-	errACL          = errors.New("no matching ACL entry found")
-	errInvalidLabel = errors.New("label is invalid")
-)
-
-// aclAuthorizer implements Authorizer.
-type aclAuthorizer security.ACL
-
-// Authorize verifies a request iff the identity at the remote end has a name authorized by
-// the aclAuthorizer's ACL for the request's label, or the request corresponds to a self-RPC.
-func (a aclAuthorizer) Authorize(ctx security.Context) error {
-	// Test if the request corresponds to a self-RPC.
-	if ctx.LocalBlessings() != nil && ctx.RemoteBlessings() != nil && reflect.DeepEqual(ctx.LocalBlessings().PublicKey(), ctx.RemoteBlessings().PublicKey()) {
-		return nil
-	}
-	var blessings []string
-	if ctx.RemoteBlessings() != nil {
-		blessings = ctx.RemoteBlessings().ForContext(ctx)
-	}
-	return matchesACL(blessings, ctx.Label(), security.ACL(a))
-}
-
-// NewACLAuthorizer creates an authorizer from the provided ACL. The
-// authorizer authorizes a request iff the identity at the remote end has a name
-// authorized by the provided ACL for the request's label, or the request
-// corresponds to a self-RPC.
-func NewACLAuthorizer(acl security.ACL) security.Authorizer { return aclAuthorizer(acl) }
-
-// fileACLAuthorizer implements Authorizer.
-type fileACLAuthorizer string
-
-// Authorize reads and decodes the fileACLAuthorizer's ACL file into a ACL and
-// then verifies the request according to an aclAuthorizer based on the ACL. If
-// reading or decoding the file fails then no requests are authorized.
-func (a fileACLAuthorizer) Authorize(ctx security.Context) error {
-	acl, err := loadACLFromFile(string(a))
-	if err != nil {
-		return err
-	}
-	return aclAuthorizer(acl).Authorize(ctx)
-}
-
-// NewFileACLAuthorizer creates an authorizer from the provided path to a file
-// containing a JSON-encoded ACL. Each call to "Authorize" involves reading and
-// decoding a ACL from the file and then authorizing the request according to the
-// ACL. The authorizer monitors the file so out of band changes to the contents of
-// the file are reflected in the ACL. If reading or decoding the file fails then
-// no requests are authorized.
-//
-// The JSON-encoding of a ACL is essentially a JSON object describing a map from
-// BlessingPatterns to encoded LabelSets (see LabelSet.MarshalJSON).
-// Examples:
-// * `{"In": {"..." : "RW"}}` encodes an ACL that allows all principals to access all methods with
-//   ReadLabel or WriteLabel.
-// * `{"In":{"veyron/alice": "RW", "veyron/bob/...": "R"}}` encodes an ACL that allows all principals
-//   matched by "veyron/alice" to access methods with ReadLabel or WriteLabel, and all
-//   principals matched by "veyron/bob/..." to access methods with ReadLabel.
-// * `{"In": {"...": "RW"}, "NotIn": {"veyron/alice": "W"}}` encodes an ACL that allows all principals
-//   access to all ReadLabel or WriteLabel methods, EXCEPT that methods with a WriteLabel are not
-//   accessible to veyron/alice and her delegates.
-// (Also see BlessingPattern.MatchedBy)
-//
-// TODO(ataly, ashankar): Instead of reading the file on each call we should use the "inotify"
-// mechanism to watch the file. Eventually we should also support ACLs stored in the Veyron
-// store.
-func NewFileACLAuthorizer(filePath string) security.Authorizer { return fileACLAuthorizer(filePath) }
-
-func matchesACL(blessings []string, label security.Label, acl security.ACL) error {
-	if len(blessings) == 0 && acl.CanAccess("", label) {
-		// No blessings, check if that satisfies the ACL (it will be if AllPrincipals appears in the ACL).
-		return nil
-	}
-	for _, b := range blessings {
-		if acl.CanAccess(b, label) {
-			return nil
-		}
-	}
-	return errACL
-}
-
-func loadACLFromFile(filePath string) (security.ACL, error) {
-	f, err := os.Open(filePath)
-	if err != nil {
-		return nullACL, err
-	}
-	defer f.Close()
-	return LoadACL(f)
-}
diff --git a/security/acl_authorizer_test.go b/security/acl_authorizer_test.go
deleted file mode 100644
index 98b0e2a..0000000
--- a/security/acl_authorizer_test.go
+++ /dev/null
@@ -1,238 +0,0 @@
-package security
-
-import (
-	"io/ioutil"
-	"os"
-	"runtime"
-	"testing"
-
-	"veyron.io/veyron/veyron2/security"
-)
-
-func saveACLToTempFile(acl security.ACL) string {
-	f, err := ioutil.TempFile("", "saved_acl")
-	if err != nil {
-		panic(err)
-	}
-	defer f.Close()
-	if err := SaveACL(f, acl); err != nil {
-		defer os.Remove(f.Name())
-		panic(err)
-	}
-	return f.Name()
-}
-
-func updateACLInFile(fileName string, acl security.ACL) {
-	f, err := os.OpenFile(fileName, os.O_WRONLY, 0600)
-	if err != nil {
-		panic(err)
-	}
-	defer f.Close()
-	if err := SaveACL(f, acl); err != nil {
-		panic(err)
-	}
-}
-
-func testSelfRPCs(t *testing.T, authorizer security.Authorizer) {
-	_, file, line, _ := runtime.Caller(1)
-	var (
-		pserver, server = newPrincipal("server")
-		_, imposter     = newPrincipal("server")
-		palice, alice   = newPrincipal("alice")
-		aliceServer     = bless(palice, pserver, alice, "server")
-
-		ctxp  = &security.ContextParams{LocalPrincipal: pserver, LocalBlessings: server}
-		tests = []struct {
-			remote       security.Blessings
-			isAuthorized bool
-		}{
-			{server, true},
-			{imposter, false},
-			// A principal talking to itself (even if with a different blessing) is authorized.
-			// TODO(ashankar,ataly): Is this a desired property?
-			{aliceServer, true},
-		}
-	)
-	for _, test := range tests {
-		ctxp.RemoteBlessings = test.remote
-		ctx := security.NewContext(ctxp)
-		if got, want := authorizer.Authorize(ctx), test.isAuthorized; (got == nil) != want {
-			t.Errorf("%s:%d: %+v.Authorize(%v) returned error: %v, want error: %v", file, line, authorizer, ctx, got, !want)
-		}
-	}
-}
-
-func testNothingPermitted(t *testing.T, authorizer security.Authorizer) {
-	_, file, line, _ := runtime.Caller(1)
-	var (
-		pserver, server = newPrincipal("server")
-		palice, alice   = newPrincipal("alice")
-		pbob, bob       = newPrincipal("random")
-
-		serverAlice       = bless(pserver, palice, server, "alice")
-		serverAliceFriend = bless(palice, pbob, serverAlice, "friend")
-		serverBob         = bless(pserver, pbob, server, "bob")
-
-		users = []security.Blessings{
-			// blessings not recognized by "server" (since they are rooted at public
-			// keys not recognized as roots by pserver)
-			alice,
-			bob,
-			// blessings recognized by "server" (since they are its delegates)
-			serverAlice,
-			serverAliceFriend,
-			serverBob,
-		}
-
-		invalidLabel = security.Label(3)
-	)
-	// No principal (other than the server itself - self-RPCs are allowed) should have access to any
-	// valid or invalid label.
-	for _, u := range users {
-		for _, l := range security.ValidLabels {
-			ctx := security.NewContext(&security.ContextParams{
-				LocalPrincipal:  pserver,
-				LocalBlessings:  server,
-				RemoteBlessings: u,
-				MethodTags:      []interface{}{l},
-			})
-			if got := authorizer.Authorize(ctx); got == nil {
-				t.Errorf("%s:%d: %+v.Authorize(%v) returns nil, want error", file, line, authorizer, ctx)
-			}
-		}
-
-		ctx := security.NewContext(&security.ContextParams{
-			LocalPrincipal:  pserver,
-			LocalBlessings:  server,
-			RemoteBlessings: u,
-			MethodTags:      []interface{}{invalidLabel},
-		})
-		if got := authorizer.Authorize(ctx); got == nil {
-			t.Errorf("%s:%d: %+v.Authorize(%v) returns nil, want error", file, line, authorizer, ctx)
-		}
-	}
-}
-
-func TestACLAuthorizer(t *testing.T) {
-	const (
-		// Shorthands
-		R = security.ReadLabel
-		W = security.WriteLabel
-		A = security.AdminLabel
-		D = security.DebugLabel
-		M = security.MonitoringLabel
-		X = security.ResolveLabel
-	)
-	type Expectations map[security.Blessings]security.LabelSet
-	// Principals to test
-	var (
-		// Principals
-		pserver, server = newPrincipal("server")
-		palice, alice   = newPrincipal("alice")
-		pbob, bob       = newPrincipal("bob")
-		pche, che       = newPrincipal("che")
-
-		// Blessings from the server
-		serverAlice       = bless(pserver, palice, server, "alice")
-		serverBob         = bless(pserver, pbob, server, "bob")
-		serverChe         = bless(pserver, pche, server, "che")
-		serverAliceFriend = bless(palice, pbob, serverAlice, "friend")
-		serverCheFriend   = bless(pche, pbob, serverChe, "friend")
-
-		authorizer security.Authorizer // the authorizer to test.
-
-		runTests = func(expectations Expectations) {
-			_, file, line, _ := runtime.Caller(1)
-			for user, labels := range expectations {
-				for _, l := range security.ValidLabels {
-					ctx := security.NewContext(&security.ContextParams{
-						LocalPrincipal:  pserver,
-						LocalBlessings:  server,
-						RemoteBlessings: user,
-						MethodTags:      []interface{}{l},
-					})
-					if got, want := authorizer.Authorize(ctx), labels.HasLabel(l); (got == nil) != want {
-						t.Errorf("%s:%d: %+v.Authorize(%v) returned error: %v, want error: %v", file, line, authorizer, ctx, got, !want)
-					}
-				}
-			}
-		}
-	)
-	// Convenience function for combining Labels into a LabelSet.
-	LS := func(labels ...security.Label) security.LabelSet {
-		var ret security.LabelSet
-		for _, l := range labels {
-			ret = ret | security.LabelSet(l)
-		}
-		return ret
-	}
-
-	// ACL for testing
-	acl := security.ACL{
-		In: map[security.BlessingPattern]security.LabelSet{
-			"...":              LS(R),
-			"server/alice/...": LS(W, R),
-			"server/alice":     LS(A, D, M),
-			"server/bob":       LS(D, M),
-			"server/che/...":   LS(W, R),
-			"server/che":       LS(W, R),
-		},
-		NotIn: map[string]security.LabelSet{
-			"server/che/friend": LS(W),
-		},
-	}
-
-	// Authorizations for the above ACL.
-	expectations := Expectations{
-		alice:             LS(R),              // "..." ACL entry.
-		bob:               LS(R),              // "..." ACL entry.
-		che:               LS(R),              // "..." ACL entry.
-		server:            security.AllLabels, // self RPC
-		serverAlice:       LS(R, W, A, D, M),  // "server/alice/..." ACL entry
-		serverBob:         LS(R, D, M),        // "..." and "server/bob" ACL entries
-		serverAliceFriend: LS(W, R),           // "server/alice/..." ACL entry.
-		serverChe:         LS(W, R),           // "server/che" ACL entry.
-		serverCheFriend:   LS(R),              // "server/che/..." ACL entry, with the "server/che/friend" NotIn exception.
-		nil:               LS(R),              // No blessings presented, same authorizations as "..." ACL entry.
-	}
-	// Create an aclAuthorizer based on the ACL and verify the authorizations.
-	authorizer = NewACLAuthorizer(acl)
-	runTests(expectations)
-	testSelfRPCs(t, authorizer)
-
-	// Create a fileACLAuthorizer by saving the ACL in a file, and verify the
-	// authorizations.
-	fileName := saveACLToTempFile(acl)
-	defer os.Remove(fileName)
-	authorizer = NewFileACLAuthorizer(fileName)
-	runTests(expectations)
-	testSelfRPCs(t, authorizer)
-
-	// Modify the ACL stored in the file and verify that the authorizations appropriately
-	// change for the fileACLAuthorizer.
-	acl.In["server/bob"] = LS(R, W, A, D, M)
-	expectations[serverBob] = LS(R, W, A, D, M)
-	updateACLInFile(fileName, acl)
-	runTests(expectations)
-	testSelfRPCs(t, authorizer)
-
-	// Update the ACL file with invalid contents and verify that no requests are
-	// authorized.
-	f, err := os.OpenFile(fileName, os.O_WRONLY, 0600)
-	if err != nil {
-		panic(err)
-	}
-	f.Write([]byte("invalid ACL"))
-	f.Close()
-	testNothingPermitted(t, authorizer)
-}
-
-func TestFileACLAuthorizerOnNonExistentFile(t *testing.T) {
-	testNothingPermitted(t, NewFileACLAuthorizer("fileDoesNotExist"))
-}
-
-func TestNilACLAuthorizer(t *testing.T) {
-	authorizer := NewACLAuthorizer(nullACL)
-	testNothingPermitted(t, authorizer)
-	testSelfRPCs(t, authorizer)
-}
diff --git a/security/agent/agent_test.go b/security/agent/agent_test.go
index d3a0b39..3d9fd8c 100644
--- a/security/agent/agent_test.go
+++ b/security/agent/agent_test.go
@@ -4,7 +4,6 @@
 	"crypto/ecdsa"
 	"crypto/elliptic"
 	"crypto/rand"
-	"errors"
 	"reflect"
 	"testing"
 
@@ -15,6 +14,7 @@
 	"veyron.io/veyron/veyron2/options"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/security"
+	"veyron.io/veyron/veyron2/verror2"
 )
 
 func setupAgent(t *testing.T, p security.Principal) security.Principal {
@@ -39,13 +39,17 @@
 	Method string
 	Args   V
 	Result interface{} // Result returned by the Method call.
-	Error  error       // If Error is not nil will be compared to the last result.
+	Error  verror2.E   // If Error is not nil will be compared to the last result.
 }
 
-var addToRootsErr = errors.New("AddToRoots")
-var storeSetDefaultErr = errors.New("StoreSetDefault")
-var rootsAddErr = errors.New("RootsAdd")
-var rootsRecognizedErr = errors.New("RootsRecognized")
+const pkgPath = "veyron.io/veyron/veyron/security/agent/"
+
+var (
+	addToRootsErr      = verror2.Register(pkgPath+".addToRoots", verror2.NoRetry, "")
+	storeSetDefaultErr = verror2.Register(pkgPath+".storeSetDefault", verror2.NoRetry, "")
+	rootsAddErr        = verror2.Register(pkgPath+".rootsAdd", verror2.NoRetry, "")
+	rootsRecognizedErr = verror2.Register(pkgPath+".rootsRecognized", verror2.NoRetry, "")
+)
 
 func TestAgent(t *testing.T) {
 	var (
@@ -56,10 +60,12 @@
 	tests := []testInfo{
 		{"BlessSelf", V{"self"}, newBlessing(t, "blessing"), nil},
 		{"Bless", V{newPrincipal(t).PublicKey(), newBlessing(t, "root"), "extension", security.UnconstrainedUse()}, newBlessing(t, "root/extension"), nil},
+		// TODO(toddw): This change is necessary for vom2:
+		//{"Sign", V{make([]byte, 10)}, security.Signature{Purpose: []byte{}, R: []byte{1}, S: []byte{1}}, nil},
 		{"Sign", V{make([]byte, 10)}, security.Signature{R: []byte{1}, S: []byte{1}}, nil},
 		{"MintDischarge", V{thirdPartyCaveat, security.UnconstrainedUse()}, discharge, nil},
 		{"PublicKey", V{}, mockP.PublicKey(), nil},
-		{"AddToRoots", V{newBlessing(t, "blessing")}, nil, addToRootsErr},
+		{"AddToRoots", V{newBlessing(t, "blessing")}, nil, verror2.Make(addToRootsErr, nil)},
 	}
 	for _, test := range tests {
 		mockP.NextResult = test.Result
@@ -71,7 +77,7 @@
 	storeTests := []testInfo{
 		{"Set", V{newBlessing(t, "blessing"), security.BlessingPattern("test")}, newBlessing(t, "root/extension"), nil},
 		{"ForPeer", V{"test", "oink"}, newBlessing(t, "for/peer"), nil},
-		{"SetDefault", V{newBlessing(t, "blessing")}, nil, storeSetDefaultErr},
+		{"SetDefault", V{newBlessing(t, "blessing")}, nil, verror2.Make(storeSetDefaultErr, nil)},
 		{"Default", V{}, newBlessing(t, "root/extension"), nil},
 		{"PublicKey", V{}, mockP.PublicKey(), nil},
 		{"DebugString", V{}, "StoreString", nil},
@@ -84,8 +90,8 @@
 
 	roots := agent.Roots()
 	rootTests := []testInfo{
-		{"Add", V{newPrincipal(t).PublicKey(), security.BlessingPattern("test")}, nil, rootsAddErr},
-		{"Recognized", V{newPrincipal(t).PublicKey(), "blessing"}, nil, rootsRecognizedErr},
+		{"Add", V{newPrincipal(t).PublicKey(), security.BlessingPattern("test")}, nil, verror2.Make(rootsAddErr, nil)},
+		{"Recognized", V{newPrincipal(t).PublicKey(), "blessing"}, nil, verror2.Make(rootsRecognizedErr, nil)},
 		{"DebugString", V{}, "RootsString", nil},
 	}
 	for _, test := range rootTests {
@@ -103,7 +109,7 @@
 	}
 	// We only set the error value when error is the only output to ensure the real function gets called.
 	if test.Error != nil {
-		if got := results[len(results)-1]; got == nil || got.(error).Error() != test.Error.Error() {
+		if got := results[len(results)-1]; got == nil || !verror2.Is(got.(error), test.Error.ErrorID()) {
 			t.Errorf("p.%v(%#v) returned an incorrect error: %v, expected %v", test.Method, test.Args, got, test.Error)
 		}
 		if len(results) == 1 {
@@ -111,7 +117,7 @@
 		}
 	}
 	if got := results[0]; !reflect.DeepEqual(got, test.Result) {
-		t.Errorf("p.%v(%#v) returned %v(%T) want %v(%T)", test.Method, test.Args, got, got, test.Result, test.Result)
+		t.Errorf("p.%v(%#v) returned %#v want %#v", test.Method, test.Args, got, test.Result)
 	}
 }
 
diff --git a/security/agent/pingpong/main.go b/security/agent/pingpong/main.go
index e09ef7b..31fcd8a 100644
--- a/security/agent/pingpong/main.go
+++ b/security/agent/pingpong/main.go
@@ -6,7 +6,6 @@
 
 	"veyron.io/veyron/veyron/lib/signals"
 	_ "veyron.io/veyron/veyron/profiles"
-	vsecurity "veyron.io/veyron/veyron/security"
 
 	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/rt"
@@ -23,6 +22,8 @@
 
 func clientMain() {
 	runtime := rt.Init()
+	defer runtime.Cleanup()
+
 	log := runtime.Logger()
 	log.Info("Pinging...")
 
@@ -51,17 +52,18 @@
 		log.Fatal("error listening to service: ", err)
 	}
 
-	auth := vsecurity.NewACLAuthorizer(security.ACL{In: map[security.BlessingPattern]security.LabelSet{
-		security.AllPrincipals: security.AllLabels,
-	}})
-	if err := s.Serve("pingpong", serverPong, auth); err != nil {
+	if err := s.Serve("pingpong", serverPong, allowEveryone{}); err != nil {
 		log.Fatal("error serving service: ", err)
 	}
 
 	// Wait forever.
-	<-signals.ShutdownOnSignals()
+	<-signals.ShutdownOnSignals(r)
 }
 
+type allowEveryone struct{}
+
+func (allowEveryone) Authorize(security.Context) error { return nil }
+
 func main() {
 	flag.Parse()
 	if *runServer {
diff --git a/security/flag/flag.go b/security/flag/flag.go
index 91b54c2..cd1086e 100644
--- a/security/flag/flag.go
+++ b/security/flag/flag.go
@@ -7,14 +7,13 @@
 	"errors"
 	"flag"
 
-	vsecurity "veyron.io/veyron/veyron/security"
-
 	"veyron.io/veyron/veyron2/security"
+	"veyron.io/veyron/veyron2/services/security/access"
 )
 
 var (
-	acl     = flag.String("acl", "", `acl is an optional JSON-encoded security.ACL that is used to construct a security.Authorizer. Example: {"In":{"veyron/alice/...":"RW"}} is a JSON-encoded ACL that allows all delegates of "veyron/alice" to access all methods with ReadLabel or WriteLabel. If this flag is provided then the \"--acl_file\" must be absent.`)
-	aclFile = flag.String("acl_file", "", "acl_file is an optional path to a file containing a JSON-encoded security.ACL that is used to construct a security.Authorizer. If this flag is provided then the \"--acl_file\" flag must be absent.")
+	acl     = flag.String("acl", "", `acl is an optional JSON-encoded access.TaggedACLMap that is used to construct a security.Authorizer using the tags defined in the access package. Example: {"Read": {"In": ["veyron/alice/..."]}} allows all delegates of "veyron/alice" to access all methods with the "Read" access tag on them. If this flag is set then the --acl_file flag must not be set.`)
+	aclFile = flag.String("acl_file", "", "acl_file is an optional path to a file containing a JSON-encoded access.TaggedACLMap that is used to construct a security.Authorizer (with the set of tags defined in the access package). If this flag is set then --acl must not be set")
 )
 
 // NewAuthorizerOrDie constructs an Authorizer based on the provided "--acl" or
@@ -28,12 +27,18 @@
 	if len(*acl) != 0 && len(*aclFile) != 0 {
 		panic(errors.New("only one of the flags \"--acl\" or \"--acl_file\" must be provided"))
 	}
+	var a security.Authorizer
+	var err error
 	if len(*aclFile) != 0 {
-		return vsecurity.NewFileACLAuthorizer(*aclFile)
+		a, err = access.TaggedACLAuthorizerFromFile(*aclFile, access.TypicalTagType())
+	} else {
+		var tam access.TaggedACLMap
+		if tam, err = access.ReadTaggedACLMap(bytes.NewBufferString(*acl)); err == nil {
+			a, err = access.TaggedACLAuthorizer(tam, access.TypicalTagType())
+		}
 	}
-	a, err := vsecurity.LoadACL(bytes.NewBufferString(*acl))
 	if err != nil {
 		panic(err)
 	}
-	return vsecurity.NewACLAuthorizer(a)
+	return a
 }
diff --git a/security/flag/flag_test.go b/security/flag/flag_test.go
index de56a92..0da0bde 100644
--- a/security/flag/flag_test.go
+++ b/security/flag/flag_test.go
@@ -7,9 +7,9 @@
 	"testing"
 
 	tsecurity "veyron.io/veyron/veyron/lib/testutil/security"
-	vsecurity "veyron.io/veyron/veyron/security"
 
 	"veyron.io/veyron/veyron2/security"
+	"veyron.io/veyron/veyron2/services/security/access"
 )
 
 func TestNewAuthorizerOrDie(t *testing.T) {
@@ -29,11 +29,22 @@
 		flag.Set("acl_file", "")
 	}
 	var (
-		acl1 = security.ACL{}
-		acl2 = security.ACL{In: map[security.BlessingPattern]security.LabelSet{
-			"veyron/alice": security.LabelSet(security.ReadLabel | security.WriteLabel),
-			"veyron/bob":   security.LabelSet(security.ReadLabel),
-		}}
+		acl1 = access.TaggedACLMap{}
+		acl2 = access.TaggedACLMap{
+			string(access.Read): access.ACL{
+				In: []security.BlessingPattern{"veyron/alice", "veyron/bob"},
+			},
+			string(access.Write): access.ACL{
+				In: []security.BlessingPattern{"veyron/alice"},
+			},
+		}
+
+		auth = func(a security.Authorizer, err error) security.Authorizer {
+			if err != nil {
+				panic(err)
+			}
+			return a
+		}
 	)
 	acl2File := tsecurity.SaveACLToFile(acl2)
 	defer os.Remove(acl2File)
@@ -49,19 +60,19 @@
 		},
 		{
 			flags:    flagValue{"acl": "{}"},
-			wantAuth: vsecurity.NewACLAuthorizer(acl1),
+			wantAuth: auth(access.TaggedACLAuthorizer(acl1, access.TypicalTagType())),
 		},
 		{
 			flags:    flagValue{"acl": `{"In":{"veyron/alice":"RW", "veyron/bob": "R"}}`},
-			wantAuth: vsecurity.NewACLAuthorizer(acl2),
+			wantAuth: auth(access.TaggedACLAuthorizer(acl2, access.TypicalTagType())),
 		},
 		{
 			flags:    flagValue{"acl": `{"In":{"veyron/bob":"R", "veyron/alice": "WR"}}`},
-			wantAuth: vsecurity.NewACLAuthorizer(acl2),
+			wantAuth: auth(access.TaggedACLAuthorizer(acl2, access.TypicalTagType())),
 		},
 		{
 			flags:    flagValue{"acl_file": acl2File},
-			wantAuth: vsecurity.NewFileACLAuthorizer(acl2File),
+			wantAuth: auth(access.TaggedACLAuthorizerFromFile(acl2File, access.TypicalTagType())),
 		},
 		{
 			flags:     flagValue{"acl_file": acl2File, "acl": `{"In":{"veyron/alice":"RW", "veyron/bob": "R"}}`},
diff --git a/security/serialization/verifying_reader.go b/security/serialization/verifying_reader.go
index 2a240b6..e8f1f44 100644
--- a/security/serialization/verifying_reader.go
+++ b/security/serialization/verifying_reader.go
@@ -9,6 +9,7 @@
 	"io"
 
 	"veyron.io/veyron/veyron2/security"
+	"veyron.io/veyron/veyron2/vdl/vdlutil"
 	"veyron.io/veyron/veyron2/vom"
 )
 
@@ -119,5 +120,5 @@
 }
 
 func init() {
-	vom.Register([sha256.Size]byte{})
+	vdlutil.Register([sha256.Size]byte{})
 }
diff --git a/security/testdata/blessingstore.sig b/security/testdata/blessingstore.sig
index 1040fb8..b06ba85 100644
--- a/security/testdata/blessingstore.sig
+++ b/security/testdata/blessingstore.sig
Binary files differ
diff --git a/security/util.go b/security/util.go
index ea9df1c..1ce53ef 100644
--- a/security/util.go
+++ b/security/util.go
@@ -6,7 +6,6 @@
 	"crypto/elliptic"
 	"crypto/rand"
 	"crypto/x509"
-	"encoding/json"
 	"encoding/pem"
 	"errors"
 	"fmt"
@@ -19,15 +18,6 @@
 
 const ecPrivateKeyPEMType = "EC PRIVATE KEY"
 
-var nullACL security.ACL
-
-// OpenACL creates an ACL that grants access to all principals.
-func OpenACL() security.ACL {
-	acl := security.ACL{}
-	acl.In = map[security.BlessingPattern]security.LabelSet{security.AllPrincipals: security.AllLabels}
-	return acl
-}
-
 var PassphraseErr = errors.New("passphrase incorrect for decrypting private key")
 
 // NewPrincipalKey generates an ECDSA (public, private) key pair.
@@ -104,20 +94,6 @@
 	return pem.Encode(w, pemKey)
 }
 
-// LoadACL reads an ACL from the provided Reader containing a JSON encoded ACL.
-func LoadACL(r io.Reader) (security.ACL, error) {
-	var acl security.ACL
-	if err := json.NewDecoder(r).Decode(&acl); err != nil {
-		return nullACL, err
-	}
-	return acl, nil
-}
-
-// SaveACL encodes an ACL in JSON format and writes it to the provided Writer.
-func SaveACL(w io.Writer, acl security.ACL) error {
-	return json.NewEncoder(w).Encode(acl)
-}
-
 // ThirdPartyCaveats returns the set of security.ThirdPartyCaveats
 // that could be successfully decoded from the provided caveat bytes.
 func ThirdPartyCaveats(caveats ...security.Caveat) []security.ThirdPartyCaveat {
diff --git a/security/util_test.go b/security/util_test.go
index 2274a70..194443f 100644
--- a/security/util_test.go
+++ b/security/util_test.go
@@ -9,7 +9,7 @@
 	"testing"
 
 	"veyron.io/veyron/veyron2/security"
-	"veyron.io/veyron/veyron2/vom"
+	"veyron.io/veyron/veyron2/vdl/vdlutil"
 )
 
 func TestLoadSavePEMKey(t *testing.T) {
@@ -65,31 +65,6 @@
 	}
 }
 
-func TestLoadSaveACL(t *testing.T) {
-	acl := security.ACL{}
-	acl.In = map[security.BlessingPattern]security.LabelSet{
-		"veyron/...":   security.LabelSet(security.ReadLabel),
-		"veyron/alice": security.LabelSet(security.ReadLabel | security.WriteLabel),
-		"veyron/bob":   security.LabelSet(security.AdminLabel),
-	}
-	acl.NotIn = map[string]security.LabelSet{
-		"veyron/che": security.LabelSet(security.ReadLabel),
-	}
-
-	var buf bytes.Buffer
-	if err := SaveACL(&buf, acl); err != nil {
-		t.Fatalf("Failed to save ACL %q: %v", acl, err)
-	}
-
-	loadedACL, err := LoadACL(&buf)
-	if err != nil {
-		t.Fatalf("Failed to load ACL: %v", err)
-	}
-	if !reflect.DeepEqual(loadedACL, acl) {
-		t.Fatalf("Got ACL %v, but want %v", loadedACL, acl)
-	}
-}
-
 // fpCaveat implements security.CaveatValidator.
 type fpCaveat struct{}
 
@@ -146,6 +121,6 @@
 }
 
 func init() {
-	vom.Register(&fpCaveat{})
-	vom.Register(&tpCaveat{})
+	vdlutil.Register(&fpCaveat{})
+	vdlutil.Register(&tpCaveat{})
 }
diff --git a/services/identity/identityd/main.go b/services/identity/identityd/main.go
index 55e0b87..5e9f3dc 100644
--- a/services/identity/identityd/main.go
+++ b/services/identity/identityd/main.go
@@ -142,7 +142,7 @@
 	})
 	vlog.Infof("Running HTTP server at: %v", httpaddress())
 	go runHTTPSServer(*httpaddr)
-	<-signals.ShutdownOnSignals()
+	<-signals.ShutdownOnSignals(r)
 }
 
 func appendSuffixTo(objectname []string, suffix string) []string {
diff --git a/services/identity/revocation/revocation_manager.go b/services/identity/revocation/revocation_manager.go
index b4b2178..4a45a9a 100644
--- a/services/identity/revocation/revocation_manager.go
+++ b/services/identity/revocation/revocation_manager.go
@@ -9,7 +9,7 @@
 	"time"
 
 	"veyron.io/veyron/veyron2/security"
-	"veyron.io/veyron/veyron2/vom"
+	"veyron.io/veyron/veyron2/vdl/vdlutil"
 )
 
 // RevocationManager persists information for revocation caveats to provided discharges and allow for future revocations.
@@ -89,5 +89,5 @@
 }
 
 func init() {
-	vom.Register(revocationCaveat{})
+	vdlutil.Register(revocationCaveat{})
 }
diff --git a/services/mgmt/application/applicationd/main.go b/services/mgmt/application/applicationd/main.go
index ab42449..af11153 100644
--- a/services/mgmt/application/applicationd/main.go
+++ b/services/mgmt/application/applicationd/main.go
@@ -50,5 +50,5 @@
 		vlog.Infof("Application repository serving at %q", epName)
 	}
 	// Wait until shutdown.
-	<-signals.ShutdownOnSignals()
+	<-signals.ShutdownOnSignals(runtime)
 }
diff --git a/services/mgmt/application/impl/impl_test.go b/services/mgmt/application/impl/impl_test.go
index 50e9ce2..d8c158c 100644
--- a/services/mgmt/application/impl/impl_test.go
+++ b/services/mgmt/application/impl/impl_test.go
@@ -9,6 +9,7 @@
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/services/mgmt/application"
+	"veyron.io/veyron/veyron2/verror2"
 
 	"veyron.io/veyron/veyron/lib/testutil"
 	"veyron.io/veyron/veyron/profiles"
@@ -69,7 +70,7 @@
 	if err := stubV2.Put(ctx, []string{"base"}, envelopeV2); err != nil {
 		t.Fatalf("Put() failed: %v", err)
 	}
-	if err := stub.Put(ctx, []string{"base", "media"}, envelopeV1); err == nil || err.Error() != errInvalidSuffix.Error() {
+	if err := stub.Put(ctx, []string{"base", "media"}, envelopeV1); err == nil || !verror2.Is(err, errInvalidSuffix.ID) {
 		t.Fatalf("Unexpected error: expected %v, got %v", errInvalidSuffix, err)
 	}
 
@@ -88,18 +89,18 @@
 	if !reflect.DeepEqual(envelopeV1, output) {
 		t.Fatalf("Unexpected output: expected %v, got %v", envelopeV1, output)
 	}
-	if _, err := stubV2.Match(ctx, []string{"media"}); err == nil || err.Error() != errNotFound.Error() {
+	if _, err := stubV2.Match(ctx, []string{"media"}); err == nil || !verror2.Is(err, errNotFound.ID) {
 		t.Fatalf("Unexpected error: expected %v, got %v", errNotFound, err)
 	}
-	if _, err := stubV2.Match(ctx, []string{}); err == nil || err.Error() != errNotFound.Error() {
+	if _, err := stubV2.Match(ctx, []string{}); err == nil || !verror2.Is(err, errNotFound.ID) {
 		t.Fatalf("Unexpected error: expected %v, got %v", errNotFound, err)
 	}
-	if _, err := stub.Match(ctx, []string{"media"}); err == nil || err.Error() != errInvalidSuffix.Error() {
+	if _, err := stub.Match(ctx, []string{"media"}); err == nil || !verror2.Is(err, errInvalidSuffix.ID) {
 		t.Fatalf("Unexpected error: expected %v, got %v", errInvalidSuffix, err)
 	}
 
 	// Test Glob
-	matches, err := testutil.GlobName(naming.JoinAddressName(endpoint.String(), ""), "...")
+	matches, err := testutil.GlobName(ctx, naming.JoinAddressName(endpoint.String(), ""), "...")
 	if err != nil {
 		t.Errorf("Unexpected Glob error: %v", err)
 	}
@@ -121,13 +122,13 @@
 	if output, err = stubV1.Match(ctx, []string{"media"}); err != nil {
 		t.Fatalf("Match() failed: %v", err)
 	}
-	if err := stubV1.Remove(ctx, "base"); err == nil || err.Error() != errNotFound.Error() {
+	if err := stubV1.Remove(ctx, "base"); err == nil || !verror2.Is(err, errNotFound.ID) {
 		t.Fatalf("Unexpected error: expected %v, got %v", errNotFound, err)
 	}
 	if err := stub.Remove(ctx, "base"); err != nil {
 		t.Fatalf("Remove() failed: %v", err)
 	}
-	if err := stubV2.Remove(ctx, "media"); err == nil || err.Error() != errNotFound.Error() {
+	if err := stubV2.Remove(ctx, "media"); err == nil || !verror2.Is(err, errNotFound.ID) {
 		t.Fatalf("Unexpected error: expected %v, got %v", errNotFound, err)
 	}
 	if err := stubV1.Remove(ctx, "media"); err != nil {
@@ -136,13 +137,13 @@
 
 	// Finally, use Match() to test that Remove really removed the
 	// application envelopes.
-	if _, err := stubV1.Match(ctx, []string{"base"}); err == nil || err.Error() != errNotFound.Error() {
+	if _, err := stubV1.Match(ctx, []string{"base"}); err == nil || !verror2.Is(err, errNotFound.ID) {
 		t.Fatalf("Unexpected error: expected %v, got %v", errNotFound, err)
 	}
-	if _, err := stubV1.Match(ctx, []string{"media"}); err == nil || err.Error() != errNotFound.Error() {
+	if _, err := stubV1.Match(ctx, []string{"media"}); err == nil || !verror2.Is(err, errNotFound.ID) {
 		t.Fatalf("Unexpected error: expected %v, got %v", errNotFound, err)
 	}
-	if _, err := stubV2.Match(ctx, []string{"base"}); err == nil || err.Error() != errNotFound.Error() {
+	if _, err := stubV2.Match(ctx, []string{"base"}); err == nil || !verror2.Is(err, errNotFound.ID) {
 		t.Fatalf("Unexpected error: expected %v, got %v", errNotFound, err)
 	}
 
diff --git a/services/mgmt/application/impl/service.go b/services/mgmt/application/impl/service.go
index b5cdf01..a42dcab 100644
--- a/services/mgmt/application/impl/service.go
+++ b/services/mgmt/application/impl/service.go
@@ -1,13 +1,13 @@
 package impl
 
 import (
-	"errors"
 	"strings"
 
 	"veyron.io/veyron/veyron/services/mgmt/lib/fs"
 	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/services/mgmt/application"
+	"veyron.io/veyron/veyron2/verror2"
 	"veyron.io/veyron/veyron2/vlog"
 )
 
@@ -24,10 +24,12 @@
 	suffix string
 }
 
+const pkgPath = "veyron.io/veyron/veyron/services/mgmt/application/impl/"
+
 var (
-	errInvalidSuffix   = errors.New("invalid suffix")
-	errOperationFailed = errors.New("operation failed")
-	errNotFound        = errors.New("not found")
+	errInvalidSuffix   = verror2.Register(pkgPath+".invalidSuffix", verror2.NoRetry, "")
+	errOperationFailed = verror2.Register(pkgPath+".operationFailed", verror2.NoRetry, "")
+	errNotFound        = verror2.Register(pkgPath+".notFound", verror2.NoRetry, "")
 )
 
 // NewApplicationService returns a new Application service implementation.
@@ -35,7 +37,7 @@
 	return &appRepoService{store: store, storeRoot: storeRoot, suffix: suffix}
 }
 
-func parse(suffix string) (string, string, error) {
+func parse(context ipc.ServerContext, suffix string) (string, string, error) {
 	tokens := strings.Split(suffix, "/")
 	switch len(tokens) {
 	case 2:
@@ -43,19 +45,19 @@
 	case 1:
 		return tokens[0], "", nil
 	default:
-		return "", "", errInvalidSuffix
+		return "", "", verror2.Make(errInvalidSuffix, context)
 	}
 }
 
 func (i *appRepoService) Match(context ipc.ServerContext, profiles []string) (application.Envelope, error) {
 	vlog.VI(0).Infof("%v.Match(%v)", i.suffix, profiles)
 	empty := application.Envelope{}
-	name, version, err := parse(i.suffix)
+	name, version, err := parse(context, i.suffix)
 	if err != nil {
 		return empty, err
 	}
 	if version == "" {
-		return empty, errInvalidSuffix
+		return empty, verror2.Make(errInvalidSuffix, context)
 	}
 
 	i.store.Lock()
@@ -73,17 +75,17 @@
 		}
 		return envelope, nil
 	}
-	return empty, errNotFound
+	return empty, verror2.Make(errNotFound, context)
 }
 
 func (i *appRepoService) Put(context ipc.ServerContext, profiles []string, envelope application.Envelope) error {
 	vlog.VI(0).Infof("%v.Put(%v, %v)", i.suffix, profiles, envelope)
-	name, version, err := parse(i.suffix)
+	name, version, err := parse(context, i.suffix)
 	if err != nil {
 		return err
 	}
 	if version == "" {
-		return errInvalidSuffix
+		return verror2.Make(errInvalidSuffix, context)
 	}
 	i.store.Lock()
 	defer i.store.Unlock()
@@ -99,18 +101,18 @@
 		object := i.store.BindObject(path)
 		_, err := object.Put(context, envelope)
 		if err != nil {
-			return errOperationFailed
+			return verror2.Make(errOperationFailed, context)
 		}
 	}
 	if err := i.store.BindTransaction(tname).Commit(context); err != nil {
-		return errOperationFailed
+		return verror2.Make(errOperationFailed, context)
 	}
 	return nil
 }
 
 func (i *appRepoService) Remove(context ipc.ServerContext, profile string) error {
 	vlog.VI(0).Infof("%v.Remove(%v)", i.suffix, profile)
-	name, version, err := parse(i.suffix)
+	name, version, err := parse(context, i.suffix)
 	if err != nil {
 		return err
 	}
@@ -128,16 +130,16 @@
 	object := i.store.BindObject(path)
 	found, err := object.Exists(context)
 	if err != nil {
-		return errOperationFailed
+		return verror2.Make(errOperationFailed, context)
 	}
 	if !found {
-		return errNotFound
+		return verror2.Make(errNotFound, context)
 	}
 	if err := object.Remove(context); err != nil {
-		return errOperationFailed
+		return verror2.Make(errOperationFailed, context)
 	}
 	if err := i.store.BindTransaction(tname).Commit(context); err != nil {
-		return errOperationFailed
+		return verror2.Make(errOperationFailed, context)
 	}
 	return nil
 }
@@ -174,8 +176,8 @@
 	return versions, nil
 }
 
-func (i *appRepoService) VGlobChildren() ([]string, error) {
-	vlog.VI(0).Infof("%v.VGlobChildren()", i.suffix)
+func (i *appRepoService) GlobChildren__() (<-chan string, error) {
+	vlog.VI(0).Infof("%v.GlobChildren__()", i.suffix)
 	i.store.Lock()
 	defer i.store.Unlock()
 
@@ -184,11 +186,19 @@
 		elems = strings.Split(i.suffix, "/")
 	}
 
+	var results []string
+	var err error
 	switch len(elems) {
 	case 0:
-		return i.allApplications()
+		results, err = i.allApplications()
+		if err != nil {
+			return nil, err
+		}
 	case 1:
-		return i.allAppVersions(elems[0])
+		results, err = i.allAppVersions(elems[0])
+		if err != nil {
+			return nil, err
+		}
 	case 2:
 		versions, err := i.allAppVersions(elems[0])
 		if err != nil {
@@ -199,8 +209,15 @@
 				return nil, nil
 			}
 		}
-		return nil, errNotFound
+		return nil, verror2.Make(errNotFound, nil)
 	default:
-		return nil, errNotFound
+		return nil, verror2.Make(errNotFound, nil)
 	}
+
+	ch := make(chan string, len(results))
+	for _, r := range results {
+		ch <- r
+	}
+	close(ch)
+	return ch, nil
 }
diff --git a/services/mgmt/binary/binaryd/main.go b/services/mgmt/binary/binaryd/main.go
index 9b87655..d65984f 100644
--- a/services/mgmt/binary/binaryd/main.go
+++ b/services/mgmt/binary/binaryd/main.go
@@ -129,5 +129,5 @@
 		vlog.Infof("Binary repository serving at %q", epName)
 	}
 	// Wait until shutdown.
-	<-signals.ShutdownOnSignals()
+	<-signals.ShutdownOnSignals(runtime)
 }
diff --git a/services/mgmt/binary/binaryd/test.sh b/services/mgmt/binary/binaryd/test.sh
index 51b7201..17347fa 100755
--- a/services/mgmt/binary/binaryd/test.sh
+++ b/services/mgmt/binary/binaryd/test.sh
@@ -30,29 +30,49 @@
   # Create a binary file.
   local -r BINARY_SUFFIX="test-binary"
   local -r BINARY="${REPO}/${BINARY_SUFFIX}"
-  local -r BINARY_FILE=$(shell::tmp_file)
+  local -r BINARY_FILE="${WORKDIR}/bin1"
   dd if=/dev/urandom of="${BINARY_FILE}" bs=1000000 count=16 \
     || shell_test::fail "line ${LINENO}: faile to create a random binary file"
   "${BINARY_BIN}" upload "${BINARY}" "${BINARY_FILE}" || shell_test::fail "line ${LINENO}: 'upload' failed"
 
+  # Create TAR file.
+  local -r TAR="${REPO}/tarobj"
+  local -r TAR_FILE="${WORKDIR}/bin1.tar.gz"
+  tar zcvf "${TAR_FILE}" "${BINARY_FILE}"
+  "${BINARY_BIN}" upload "${TAR}" "${TAR_FILE}" || shell_test::fail "line ${LINENO}: 'upload' failed"
+
   # Download the binary file.
-  local -r BINARY_FILE2=$(shell::tmp_file)
+  local -r BINARY_FILE2="${WORKDIR}/bin2"
   "${BINARY_BIN}" download "${BINARY}" "${BINARY_FILE2}" || shell_test::fail "line ${LINENO}: 'RPC download' failed"
   if [[ $(cmp "${BINARY_FILE}" "${BINARY_FILE2}" &> /dev/null) ]]; then
     shell_test::fail "mismatching binary file downloaded via RPC"
   fi
+  local -r BINARY_FILE2_INFO=$(cat "${BINARY_FILE2}.__info")
+  shell_test::assert_eq "${BINARY_FILE2_INFO}" '{"Type":"application/octet-stream","Encoding":""}' "${LINENO}"
 
-  local -r BINARY_FILE3=$(shell::tmp_file)
+  # Download the tar file.
+  local -r TAR_FILE2="${WORKDIR}/downloadedtar"
+  "${BINARY_BIN}" download "${TAR}" "${TAR_FILE2}" || shell_test::fail "line ${LINENO}: 'RPC download' failed"
+  if [[ $(cmp "${TAR_FILE}" "${TAR_FILE2}" &> /dev/null) ]]; then
+    shell_test::fail "mismatching tar file downloaded via RPC"
+  fi
+  local -r TAR_FILE2_INFO=$(cat "${TAR_FILE2}.__info")
+  shell_test::assert_eq "${TAR_FILE2_INFO}" '{"Type":"application/x-tar","Encoding":"gzip"}' "${LINENO}"
+
+  local -r BINARY_FILE3="${WORKDIR}/bin3"
   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
 
-  # Remove the binary file.
+  # Remove the files.
   "${BINARY_BIN}" delete "${BINARY}" || shell_test::fail "line ${LINENO}: 'delete' failed"
+  "${BINARY_BIN}" delete "${TAR}" || shell_test::fail "line ${LINENO}: 'delete' failed"
 
-  # Check the binary no longer exists.
-  local -r RESULT=$(shell::check_result "${BINARY_BIN}" download "${BINARY}" "${BINARY_FILE2}")
+  # Check the files no longer exist.
+  local RESULT=$(shell::check_result "${BINARY_BIN}" download "${BINARY}" "${BINARY_FILE2}")
+  shell_test::assert_ne "${RESULT}" "0" "${LINENO}"
+  RESULT=$(shell::check_result "${BINARY_BIN}" download "${TAR}" "${TAR_FILE2}")
   shell_test::assert_ne "${RESULT}" "0" "${LINENO}"
 
   shell_test::pass
diff --git a/services/mgmt/binary/impl/fs_utils.go b/services/mgmt/binary/impl/fs_utils.go
index 431f434..62eaab8 100644
--- a/services/mgmt/binary/impl/fs_utils.go
+++ b/services/mgmt/binary/impl/fs_utils.go
@@ -79,7 +79,7 @@
 			}
 			result[idx] = filepath.Join(path, partName)
 		} else {
-			if info.Name() == "name" {
+			if info.Name() == "name" || info.Name() == "mediainfo" {
 				continue
 			}
 			// The only entries should correspond to the part dirs.
diff --git a/services/mgmt/binary/impl/http_test.go b/services/mgmt/binary/impl/http_test.go
index 123540e..bde93b3 100644
--- a/services/mgmt/binary/impl/http_test.go
+++ b/services/mgmt/binary/impl/http_test.go
@@ -9,6 +9,7 @@
 	"testing"
 
 	"veyron.io/veyron/veyron2/rt"
+	"veyron.io/veyron/veyron2/services/mgmt/repository"
 
 	"veyron.io/veyron/veyron/lib/testutil"
 )
@@ -27,7 +28,8 @@
 			size := testutil.Rand.Intn(1000*bufferLength) + 1
 			data[i] = testutil.RandomBytes(size)
 		}
-		if err := binary.Create(rt.R().NewContext(), int32(length)); err != nil {
+		mediaInfo := repository.MediaInfo{Type: "application/octet-stream"}
+		if err := binary.Create(rt.R().NewContext(), int32(length), mediaInfo); err != nil {
 			t.Fatalf("Create() failed: %v", err)
 		}
 		for i := 0; i < length; i++ {
@@ -35,7 +37,7 @@
 				t.FailNow()
 			}
 		}
-		parts, err := binary.Stat(rt.R().NewContext())
+		parts, _, err := binary.Stat(rt.R().NewContext())
 		if err != nil {
 			t.Fatalf("Stat() failed: %v", err)
 		}
diff --git a/services/mgmt/binary/impl/impl_test.go b/services/mgmt/binary/impl/impl_test.go
index 75bb0e0..35aa2e3 100644
--- a/services/mgmt/binary/impl/impl_test.go
+++ b/services/mgmt/binary/impl/impl_test.go
@@ -162,13 +162,13 @@
 		size := testutil.Rand.Intn(1000 * bufferLength)
 		data := testutil.RandomBytes(size)
 		// Test the binary repository interface.
-		if err := binary.Create(rt.R().NewContext(), 1); err != nil {
+		if err := binary.Create(rt.R().NewContext(), 1, repository.MediaInfo{Type: "application/octet-stream"}); err != nil {
 			t.Fatalf("Create() failed: %v", err)
 		}
 		if streamErr, err := invokeUpload(t, binary, data, 0); streamErr != nil || err != nil {
 			t.FailNow()
 		}
-		parts, err := binary.Stat(rt.R().NewContext())
+		parts, _, err := binary.Stat(rt.R().NewContext())
 		if err != nil {
 			t.Fatalf("Stat() failed: %v", err)
 		}
@@ -188,7 +188,7 @@
 		if bytes.Compare(output, data) != 0 {
 			t.Fatalf("Unexpected output: expected %v, got %v", data, output)
 		}
-		results, err := testutil.GlobName(naming.JoinAddressName(ep, ""), "...")
+		results, err := testutil.GlobName(rt.R().NewContext(), naming.JoinAddressName(ep, ""), "...")
 		if err != nil {
 			t.Fatalf("GlobName failed: %v", err)
 		}
@@ -215,7 +215,7 @@
 			data[i] = testutil.RandomBytes(size)
 		}
 		// Test the binary repository interface.
-		if err := binary.Create(rt.R().NewContext(), int32(length)); err != nil {
+		if err := binary.Create(rt.R().NewContext(), int32(length), repository.MediaInfo{Type: "application/octet-stream"}); err != nil {
 			t.Fatalf("Create() failed: %v", err)
 		}
 		for i := 0; i < length; i++ {
@@ -223,7 +223,7 @@
 				t.FailNow()
 			}
 		}
-		parts, err := binary.Stat(rt.R().NewContext())
+		parts, _, err := binary.Stat(rt.R().NewContext())
 		if err != nil {
 			t.Fatalf("Stat() failed: %v", err)
 		}
@@ -264,13 +264,13 @@
 			size := testutil.Rand.Intn(1000 * bufferLength)
 			data[i] = testutil.RandomBytes(size)
 		}
-		if err := binary.Create(rt.R().NewContext(), int32(length)); err != nil {
+		if err := binary.Create(rt.R().NewContext(), int32(length), repository.MediaInfo{Type: "application/octet-stream"}); err != nil {
 			t.Fatalf("Create() failed: %v", err)
 		}
 		// Simulate a flaky upload client that keeps uploading parts until
 		// finished.
 		for {
-			parts, err := binary.Stat(rt.R().NewContext())
+			parts, _, err := binary.Stat(rt.R().NewContext())
 			if err != nil {
 				t.Fatalf("Stat() failed: %v", err)
 			}
@@ -309,10 +309,10 @@
 			data[i][j] = byte(testutil.Rand.Int())
 		}
 	}
-	if err := binary.Create(rt.R().NewContext(), int32(length)); err != nil {
+	if err := binary.Create(rt.R().NewContext(), int32(length), repository.MediaInfo{Type: "application/octet-stream"}); err != nil {
 		t.Fatalf("Create() failed: %v", err)
 	}
-	if err := binary.Create(rt.R().NewContext(), int32(length)); err == nil {
+	if err := binary.Create(rt.R().NewContext(), int32(length), repository.MediaInfo{Type: "application/octet-stream"}); err == nil {
 		t.Fatalf("Create() did not fail when it should have")
 	} else if want := verror.Exists; !verror.Is(err, want) {
 		t.Fatalf("Unexpected error: %v, expected error id %v", err, want)
@@ -372,14 +372,14 @@
 		name := naming.JoinAddressName(ep, obj)
 		binary := repository.BinaryClient(name)
 
-		if err := binary.Create(rt.R().NewContext(), 1); err != nil {
+		if err := binary.Create(rt.R().NewContext(), 1, repository.MediaInfo{Type: "application/octet-stream"}); err != nil {
 			t.Fatalf("Create() failed: %v", err)
 		}
 		if streamErr, err := invokeUpload(t, binary, data, 0); streamErr != nil || err != nil {
 			t.FailNow()
 		}
 	}
-	results, err := testutil.GlobName(naming.JoinAddressName(ep, ""), "...")
+	results, err := testutil.GlobName(rt.R().NewContext(), naming.JoinAddressName(ep, ""), "...")
 	if err != nil {
 		t.Fatalf("GlobName failed: %v", err)
 	}
diff --git a/services/mgmt/binary/impl/service.go b/services/mgmt/binary/impl/service.go
index 8a01122..a1999c6 100644
--- a/services/mgmt/binary/impl/service.go
+++ b/services/mgmt/binary/impl/service.go
@@ -22,6 +22,7 @@
 import (
 	"crypto/md5"
 	"encoding/hex"
+	"encoding/json"
 	"io"
 	"io/ioutil"
 	"os"
@@ -75,8 +76,8 @@
 
 const bufferLength = 4096
 
-func (i *binaryService) Create(_ ipc.ServerContext, nparts int32) error {
-	vlog.Infof("%v.Create(%v)", i.suffix, nparts)
+func (i *binaryService) Create(_ ipc.ServerContext, nparts int32, mediaInfo repository.MediaInfo) error {
+	vlog.Infof("%v.Create(%v, %v)", i.suffix, nparts, mediaInfo)
 	if nparts < 1 {
 		return errInvalidParts
 	}
@@ -96,6 +97,16 @@
 		vlog.Errorf("WriteFile(%q) failed: %v", nameFile)
 		return errOperationFailed
 	}
+	infoFile := filepath.Join(tmpDir, "mediainfo")
+	jInfo, err := json.Marshal(mediaInfo)
+	if err != nil {
+		vlog.Errorf("json.Marshal(%v) failed: %v", mediaInfo, err)
+		return errOperationFailed
+	}
+	if err := ioutil.WriteFile(infoFile, jInfo, os.FileMode(0600)); err != nil {
+		vlog.Errorf("WriteFile(%q) failed: %v", infoFile, err)
+		return errOperationFailed
+	}
 	for j := 0; j < int(nparts); j++ {
 		partPath, partPerm := generatePartPath(tmpDir, j), os.FileMode(0700)
 		if err := os.MkdirAll(partPath, partPerm); err != nil {
@@ -199,12 +210,12 @@
 	return "", 0, nil
 }
 
-func (i *binaryService) Stat(ipc.ServerContext) ([]binary.PartInfo, error) {
+func (i *binaryService) Stat(ipc.ServerContext) ([]binary.PartInfo, repository.MediaInfo, error) {
 	vlog.Infof("%v.Stat()", i.suffix)
 	result := make([]binary.PartInfo, 0)
 	parts, err := getParts(i.path)
 	if err != nil {
-		return []binary.PartInfo{}, err
+		return []binary.PartInfo{}, repository.MediaInfo{}, err
 	}
 	for _, part := range parts {
 		checksumFile := filepath.Join(part, checksum)
@@ -215,7 +226,7 @@
 				continue
 			}
 			vlog.Errorf("ReadFile(%v) failed: %v", checksumFile, err)
-			return []binary.PartInfo{}, errOperationFailed
+			return []binary.PartInfo{}, repository.MediaInfo{}, errOperationFailed
 		}
 		dataFile := filepath.Join(part, data)
 		fi, err := os.Stat(dataFile)
@@ -225,11 +236,22 @@
 				continue
 			}
 			vlog.Errorf("Stat(%v) failed: %v", dataFile, err)
-			return []binary.PartInfo{}, errOperationFailed
+			return []binary.PartInfo{}, repository.MediaInfo{}, errOperationFailed
 		}
 		result = append(result, binary.PartInfo{Checksum: string(bytes), Size: fi.Size()})
 	}
-	return result, nil
+	infoFile := filepath.Join(i.path, "mediainfo")
+	jInfo, err := ioutil.ReadFile(infoFile)
+	if err != nil {
+		vlog.Errorf("ReadFile(%q) failed: %v", infoFile)
+		return []binary.PartInfo{}, repository.MediaInfo{}, errOperationFailed
+	}
+	var mediaInfo repository.MediaInfo
+	if err := json.Unmarshal(jInfo, &mediaInfo); err != nil {
+		vlog.Errorf("json.Unmarshal(%v) failed: %v", jInfo, err)
+		return []binary.PartInfo{}, repository.MediaInfo{}, errOperationFailed
+	}
+	return result, mediaInfo, nil
 }
 
 func (i *binaryService) Upload(context repository.BinaryUploadContext, part int32) error {
@@ -303,7 +325,7 @@
 	return nil
 }
 
-func (i *binaryService) VGlobChildren() ([]string, error) {
+func (i *binaryService) GlobChildren__() (<-chan string, error) {
 	elems := strings.Split(i.suffix, "/")
 	if len(elems) == 1 && elems[0] == "" {
 		elems = nil
@@ -312,11 +334,12 @@
 	if n == nil {
 		return nil, errOperationFailed
 	}
-	results := make([]string, len(n.children))
-	index := 0
-	for k, _ := range n.children {
-		results[index] = k
-		index++
-	}
-	return results, nil
+	ch := make(chan string, 100)
+	go func() {
+		for k, _ := range n.children {
+			ch <- k
+		}
+		close(ch)
+	}()
+	return ch, nil
 }
diff --git a/services/mgmt/build/buildd/main.go b/services/mgmt/build/buildd/main.go
index bba50c4..deb5f37 100644
--- a/services/mgmt/build/buildd/main.go
+++ b/services/mgmt/build/buildd/main.go
@@ -42,5 +42,5 @@
 	vlog.Infof("Build server running at endpoint=%q", endpoint)
 
 	// Wait until shutdown.
-	<-signals.ShutdownOnSignals()
+	<-signals.ShutdownOnSignals(runtime)
 }
diff --git a/services/mgmt/debug/dispatcher.go b/services/mgmt/debug/dispatcher.go
index e11cf1e..6f0f3b6 100644
--- a/services/mgmt/debug/dispatcher.go
+++ b/services/mgmt/debug/dispatcher.go
@@ -32,7 +32,7 @@
 
 func (d *dispatcher) Lookup(suffix string) (interface{}, security.Authorizer, error) {
 	if suffix == "" {
-		return ipc.VChildrenGlobberInvoker(rootName), d.auth, nil
+		return ipc.ChildrenGlobberInvoker(rootName), d.auth, nil
 	}
 	if !strings.HasPrefix(suffix, rootName) {
 		return nil, nil, nil
@@ -41,7 +41,7 @@
 	suffix = strings.TrimLeft(suffix, "/")
 
 	if suffix == "" {
-		return ipc.VChildrenGlobberInvoker("logs", "pprof", "stats", "vtrace"), d.auth, nil
+		return ipc.ChildrenGlobberInvoker("logs", "pprof", "stats", "vtrace"), d.auth, nil
 	}
 	parts := strings.SplitN(suffix, "/", 2)
 	if len(parts) == 2 {
diff --git a/services/mgmt/debug/dispatcher_test.go b/services/mgmt/debug/dispatcher_test.go
index 2d9236b..46fd799 100644
--- a/services/mgmt/debug/dispatcher_test.go
+++ b/services/mgmt/debug/dispatcher_test.go
@@ -13,13 +13,15 @@
 	"time"
 
 	"veyron.io/veyron/veyron2"
+	"veyron.io/veyron/veyron2/context"
 	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/services/mgmt/logreader"
 	"veyron.io/veyron/veyron2/services/mgmt/stats"
-	"veyron.io/veyron/veyron2/services/mgmt/vtrace"
+	vtracesvc "veyron.io/veyron/veyron2/services/mgmt/vtrace"
 	"veyron.io/veyron/veyron2/verror"
+	"veyron.io/veyron/veyron2/vtrace"
 
 	libstats "veyron.io/veyron/veyron/lib/stats"
 	"veyron.io/veyron/veyron/lib/testutil"
@@ -49,6 +51,11 @@
 
 func TestDebugServer(t *testing.T) {
 	runtime := rt.Init()
+	tracedContext := func() context.T {
+		ctx := runtime.NewContext()
+		vtrace.FromContext(ctx).Trace().ForceCollect()
+		return ctx
+	}
 	rootName = "debug"
 
 	workdir, err := ioutil.TempDir("", "logreadertest")
@@ -68,7 +75,7 @@
 
 	// Access a logs directory that exists.
 	{
-		results, err := testutil.GlobName(naming.JoinAddressName(endpoint, "debug/logs"), "*")
+		results, err := testutil.GlobName(runtime.NewContext(), naming.JoinAddressName(endpoint, "debug/logs"), "*")
 		if err != nil {
 			t.Errorf("Glob failed: %v", err)
 		}
@@ -79,7 +86,7 @@
 
 	// Access a logs directory that doesn't exist.
 	{
-		results, err := testutil.GlobName(naming.JoinAddressName(endpoint, "debug/logs/nowheretobefound"), "*")
+		results, err := testutil.GlobName(runtime.NewContext(), naming.JoinAddressName(endpoint, "debug/logs/nowheretobefound"), "*")
 		if len(results) != 0 {
 			t.Errorf("unexpected result. Got %v, want ''", results)
 		}
@@ -91,7 +98,7 @@
 	// Access a log file that exists.
 	{
 		lf := logreader.LogFileClient(naming.JoinAddressName(endpoint, "debug/logs/test.INFO"))
-		size, err := lf.Size(runtime.NewContext())
+		size, err := lf.Size(tracedContext())
 		if err != nil {
 			t.Errorf("Size failed: %v", err)
 		}
@@ -103,7 +110,7 @@
 	// Access a log file that doesn't exist.
 	{
 		lf := logreader.LogFileClient(naming.JoinAddressName(endpoint, "debug/logs/nosuchfile.INFO"))
-		_, err = lf.Size(runtime.NewContext())
+		_, err = lf.Size(tracedContext())
 		if expected := verror.NoExist; !verror.Is(err, expected) {
 			t.Errorf("unexpected error value, got %v, want: %v", err, expected)
 		}
@@ -115,7 +122,7 @@
 		foo.Set(123)
 
 		st := stats.StatsClient(naming.JoinAddressName(endpoint, "debug/stats/testing/foo"))
-		v, err := st.Value(runtime.NewContext())
+		v, err := st.Value(tracedContext())
 		if err != nil {
 			t.Errorf("Value failed: %v", err)
 		}
@@ -127,7 +134,7 @@
 	// Access a stats object that doesn't exists.
 	{
 		st := stats.StatsClient(naming.JoinAddressName(endpoint, "debug/stats/testing/nobodyhome"))
-		_, err = st.Value(runtime.NewContext())
+		_, err = st.Value(tracedContext())
 		if expected := verror.NoExist; !verror.Is(err, expected) {
 			t.Errorf("unexpected error value, got %v, want: %v", err, expected)
 		}
@@ -135,7 +142,7 @@
 
 	// Access vtrace.
 	{
-		vt := vtrace.StoreClient(naming.JoinAddressName(endpoint, "debug/vtrace"))
+		vt := vtracesvc.StoreClient(naming.JoinAddressName(endpoint, "debug/vtrace"))
 		call, err := vt.AllTraces(runtime.NewContext())
 		if err != nil {
 			t.Errorf("AllTraces failed: %v", err)
@@ -149,8 +156,8 @@
 		if err = stream.Err(); err != nil && err != io.EOF {
 			t.Fatalf("Unexpected error reading trace stream: %s", err)
 		}
-		if ntraces < 1 {
-			t.Errorf("We expected at least one trace, got: %d", ntraces)
+		if ntraces != 4 {
+			t.Errorf("We expected 4 traces, got: %d", ntraces)
 		}
 	}
 
diff --git a/services/mgmt/lib/binary/impl.go b/services/mgmt/lib/binary/impl.go
index 41af160..07bedd9 100644
--- a/services/mgmt/lib/binary/impl.go
+++ b/services/mgmt/lib/binary/impl.go
@@ -14,11 +14,12 @@
 	"time"
 
 	"veyron.io/veyron/veyron2/context"
-	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/services/mgmt/binary"
 	"veyron.io/veyron/veyron2/services/mgmt/repository"
 	"veyron.io/veyron/veyron2/verror"
 	"veyron.io/veyron/veyron2/vlog"
+
+	"veyron.io/veyron/veyron/services/mgmt/lib/packages"
 )
 
 var (
@@ -32,8 +33,8 @@
 	subpartSize = 1 << 12
 )
 
-func Delete(name string) error {
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+func Delete(ctx context.T, name string) error {
+	ctx, cancel := ctx.WithTimeout(time.Minute)
 	defer cancel()
 	if err := repository.BinaryClient(name).Delete(ctx); err != nil {
 		vlog.Errorf("Delete() failed: %v", err)
@@ -42,16 +43,16 @@
 	return nil
 }
 
-func download(ctx context.T, w io.WriteSeeker, von string) error {
+func download(ctx context.T, w io.WriteSeeker, von string) (repository.MediaInfo, error) {
 	client := repository.BinaryClient(von)
-	parts, err := client.Stat(ctx)
+	parts, mediaInfo, err := client.Stat(ctx)
 	if err != nil {
 		vlog.Errorf("Stat() failed: %v", err)
-		return err
+		return repository.MediaInfo{}, err
 	}
 	for _, part := range parts {
 		if part.Checksum == binary.MissingChecksum {
-			return errNotExist
+			return repository.MediaInfo{}, errNotExist
 		}
 	}
 	offset, whence := int64(0), 0
@@ -102,36 +103,37 @@
 			success = true
 		}
 		if !success {
-			return errOperationFailed
+			return repository.MediaInfo{}, errOperationFailed
 		}
 		offset += part.Size
 	}
-	return nil
+	return mediaInfo, nil
 }
 
-func Download(von string) ([]byte, error) {
+func Download(ctx context.T, von string) ([]byte, repository.MediaInfo, error) {
 	dir, prefix := "", ""
 	file, err := ioutil.TempFile(dir, prefix)
 	if err != nil {
 		vlog.Errorf("TempFile(%v, %v) failed: %v", dir, prefix, err)
-		return nil, errOperationFailed
+		return nil, repository.MediaInfo{}, errOperationFailed
 	}
 	defer os.Remove(file.Name())
 	defer file.Close()
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ctx, cancel := ctx.WithTimeout(time.Minute)
 	defer cancel()
-	if err := download(ctx, file, von); err != nil {
-		return nil, errOperationFailed
+	mediaInfo, err := download(ctx, file, von)
+	if err != nil {
+		return nil, repository.MediaInfo{}, errOperationFailed
 	}
 	bytes, err := ioutil.ReadFile(file.Name())
 	if err != nil {
 		vlog.Errorf("ReadFile(%v) failed: %v", file.Name(), err)
-		return nil, errOperationFailed
+		return nil, repository.MediaInfo{}, errOperationFailed
 	}
-	return bytes, nil
+	return bytes, mediaInfo, nil
 }
 
-func DownloadToFile(von, path string) error {
+func DownloadToFile(ctx context.T, von, path string) error {
 	dir, prefix := "", ""
 	file, err := ioutil.TempFile(dir, prefix)
 	if err != nil {
@@ -139,15 +141,16 @@
 		return errOperationFailed
 	}
 	defer file.Close()
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ctx, cancel := ctx.WithTimeout(time.Minute)
 	defer cancel()
-	if err := download(ctx, file, von); err != nil {
+	mediaInfo, err := download(ctx, file, von)
+	if err != nil {
 		if err := os.Remove(file.Name()); err != nil {
 			vlog.Errorf("Remove(%v) failed: %v", file.Name(), err)
 		}
 		return errOperationFailed
 	}
-	perm := os.FileMode(0700)
+	perm := os.FileMode(0600)
 	if err := file.Chmod(perm); err != nil {
 		vlog.Errorf("Chmod(%v) failed: %v", perm, err)
 		if err := os.Remove(file.Name()); err != nil {
@@ -162,10 +165,17 @@
 		}
 		return errOperationFailed
 	}
+	if err := packages.SaveMediaInfo(path, mediaInfo); err != nil {
+		vlog.Errorf("packages.SaveMediaInfo(%v, %v) failed: %v", path, mediaInfo, err)
+		if err := os.Remove(path); err != nil {
+			vlog.Errorf("Remove(%v) failed: %v", path, err)
+		}
+		return errOperationFailed
+	}
 	return nil
 }
 
-func upload(ctx context.T, r io.ReadSeeker, von string) error {
+func upload(ctx context.T, r io.ReadSeeker, mediaInfo repository.MediaInfo, von string) error {
 	client := repository.BinaryClient(von)
 	offset, whence := int64(0), 2
 	size, err := r.Seek(offset, whence)
@@ -174,7 +184,7 @@
 		return errOperationFailed
 	}
 	nparts := (size-1)/partSize + 1
-	if err := client.Create(ctx, int32(nparts)); err != nil {
+	if err := client.Create(ctx, int32(nparts), mediaInfo); err != nil {
 		vlog.Errorf("Create() failed: %v", err)
 		return err
 	}
@@ -220,7 +230,7 @@
 			}
 			if err := sender.Close(); err != nil {
 				vlog.Errorf("Close() failed: %v", err)
-				parts, statErr := client.Stat(ctx)
+				parts, _, statErr := client.Stat(ctx)
 				if statErr != nil {
 					vlog.Errorf("Stat() failed: %v", statErr)
 					if deleteErr := client.Delete(ctx); err != nil {
@@ -235,7 +245,7 @@
 			}
 			if err := stream.Finish(); err != nil {
 				vlog.Errorf("Finish() failed: %v", err)
-				parts, statErr := client.Stat(ctx)
+				parts, _, statErr := client.Stat(ctx)
 				if statErr != nil {
 					vlog.Errorf("Stat() failed: %v", statErr)
 					if deleteErr := client.Delete(ctx); err != nil {
@@ -256,21 +266,22 @@
 	return nil
 }
 
-func Upload(von string, data []byte) error {
+func Upload(ctx context.T, von string, data []byte, mediaInfo repository.MediaInfo) error {
 	buffer := bytes.NewReader(data)
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ctx, cancel := ctx.WithTimeout(time.Minute)
 	defer cancel()
-	return upload(ctx, buffer, von)
+	return upload(ctx, buffer, mediaInfo, von)
 }
 
-func UploadFromFile(von, path string) error {
+func UploadFromFile(ctx context.T, von, path string) error {
 	file, err := os.Open(path)
 	defer file.Close()
 	if err != nil {
 		vlog.Errorf("Open(%v) failed: %v", err)
 		return errOperationFailed
 	}
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ctx, cancel := ctx.WithTimeout(time.Minute)
 	defer cancel()
-	return upload(ctx, file, von)
+	mediaInfo := packages.MediaInfoForFileName(path)
+	return upload(ctx, file, mediaInfo, von)
 }
diff --git a/services/mgmt/lib/binary/impl_test.go b/services/mgmt/lib/binary/impl_test.go
index 3f79d89..ca0a76f 100644
--- a/services/mgmt/lib/binary/impl_test.go
+++ b/services/mgmt/lib/binary/impl_test.go
@@ -5,10 +5,13 @@
 	"io/ioutil"
 	"os"
 	"path/filepath"
+	"reflect"
 	"testing"
 
+	"veyron.io/veyron/veyron2"
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/rt"
+	"veyron.io/veyron/veyron2/services/mgmt/repository"
 	"veyron.io/veyron/veyron2/vlog"
 
 	"veyron.io/veyron/veyron/lib/testutil"
@@ -20,9 +23,16 @@
 	veyronPrefix = "veyron_binary_repository"
 )
 
+var runtime veyron2.Runtime
+
 func init() {
 	testutil.Init()
-	rt.Init()
+
+	var err error
+	runtime, err = rt.New()
+	if err != nil {
+		panic(err)
+	}
 }
 
 func setupRepository(t *testing.T) (string, func()) {
@@ -36,7 +46,7 @@
 		vlog.Fatalf("WriteFile(%v, %v, %v) failed: %v", path, impl.Version, perm, err)
 	}
 	// Setup and start the binary repository server.
-	server, err := rt.R().NewServer()
+	server, err := runtime.NewServer()
 	if err != nil {
 		t.Fatalf("NewServer() failed: %v", err)
 	}
@@ -77,21 +87,25 @@
 	von, cleanup := setupRepository(t)
 	defer cleanup()
 	data := testutil.RandomBytes(testutil.Rand.Intn(10 << 20))
-	if err := Upload(von, data); err != nil {
+	mediaInfo := repository.MediaInfo{Type: "application/octet-stream"}
+	if err := Upload(runtime.NewContext(), von, data, mediaInfo); err != nil {
 		t.Fatalf("Upload(%v) failed: %v", von, err)
 	}
-	output, err := Download(von)
+	output, outInfo, err := Download(runtime.NewContext(), von)
 	if err != nil {
 		t.Fatalf("Download(%v) failed: %v", von, err)
 	}
 	if bytes.Compare(data, output) != 0 {
-		t.Fatalf("Data mismatch:\nexpected %v %v\ngot %v %v", len(data), data[:100], len(output), output[:100])
+		t.Errorf("Data mismatch:\nexpected %v %v\ngot %v %v", len(data), data[:100], len(output), output[:100])
 	}
-	if err := Delete(von); err != nil {
-		t.Fatalf("Delete(%v) failed: %v", von, err)
+	if err := Delete(runtime.NewContext(), von); err != nil {
+		t.Errorf("Delete(%v) failed: %v", von, err)
 	}
-	if _, err := Download(von); err == nil {
-		t.Fatalf("Download(%v) did not fail", von)
+	if _, _, err := Download(runtime.NewContext(), von); err == nil {
+		t.Errorf("Download(%v) did not fail", von)
+	}
+	if !reflect.DeepEqual(mediaInfo, outInfo) {
+		t.Errorf("unexpected media info: expected %v, got %v", mediaInfo, outInfo)
 	}
 }
 
@@ -109,29 +123,40 @@
 	}
 	defer os.Remove(src.Name())
 	defer src.Close()
-	dst, err := ioutil.TempFile(dir, prefix)
+	dstdir, err := ioutil.TempDir(dir, prefix)
 	if err != nil {
-		t.Fatalf("TempFile(%v, %v) failed: %v", dir, prefix, err)
+		t.Fatalf("TempDir(%v, %v) failed: %v", dir, prefix, err)
 	}
-	defer os.Remove(dst.Name())
+	defer os.RemoveAll(dstdir)
+	dst, err := ioutil.TempFile(dstdir, prefix)
+	if err != nil {
+		t.Fatalf("TempFile(%v, %v) failed: %v", dstdir, prefix, err)
+	}
 	defer dst.Close()
 	if _, err := src.Write(data); err != nil {
 		t.Fatalf("Write() failed: %v", err)
 	}
-	if err := UploadFromFile(von, src.Name()); err != nil {
+	if err := UploadFromFile(runtime.NewContext(), von, src.Name()); err != nil {
 		t.Fatalf("UploadFromFile(%v, %v) failed: %v", von, src.Name(), err)
 	}
-	if err := DownloadToFile(von, dst.Name()); err != nil {
+	if err := DownloadToFile(runtime.NewContext(), von, dst.Name()); err != nil {
 		t.Fatalf("DownloadToFile(%v, %v) failed: %v", von, dst.Name(), err)
 	}
 	output, err := ioutil.ReadFile(dst.Name())
 	if err != nil {
-		t.Fatalf("ReadFile(%v) failed: %v", dst.Name(), err)
+		t.Errorf("ReadFile(%v) failed: %v", dst.Name(), err)
 	}
 	if bytes.Compare(data, output) != 0 {
-		t.Fatalf("Data mismatch:\nexpected %v %v\ngot %v %v", len(data), data[:100], len(output), output[:100])
+		t.Errorf("Data mismatch:\nexpected %v %v\ngot %v %v", len(data), data[:100], len(output), output[:100])
 	}
-	if err := Delete(von); err != nil {
-		t.Fatalf("Delete(%v) failed: %v", von, err)
+	jMediaInfo, err := ioutil.ReadFile(dst.Name() + ".__info")
+	if err != nil {
+		t.Errorf("ReadFile(%v) failed: %v", dst.Name()+".__info", err)
+	}
+	if expected := `{"Type":"application/octet-stream","Encoding":""}`; string(jMediaInfo) != expected {
+		t.Errorf("unexpected media info: expected %q, got %q", expected, string(jMediaInfo))
+	}
+	if err := Delete(runtime.NewContext(), von); err != nil {
+		t.Errorf("Delete(%v) failed: %v", von, err)
 	}
 }
diff --git a/services/mgmt/lib/packages/packages.go b/services/mgmt/lib/packages/packages.go
new file mode 100644
index 0000000..57f9dde
--- /dev/null
+++ b/services/mgmt/lib/packages/packages.go
@@ -0,0 +1,192 @@
+// Package packages provides functionality to install ZIP and TAR packages.
+package packages
+
+import (
+	"archive/tar"
+	"archive/zip"
+	"compress/bzip2"
+	"compress/gzip"
+	"encoding/json"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"veyron.io/veyron/veyron2/services/mgmt/repository"
+)
+
+const defaultType = "application/octet-stream"
+
+var typemap = map[string]repository.MediaInfo{
+	".zip":     repository.MediaInfo{Type: "application/zip"},
+	".tar":     repository.MediaInfo{Type: "application/x-tar"},
+	".tgz":     repository.MediaInfo{Type: "application/x-tar", Encoding: "gzip"},
+	".tar.gz":  repository.MediaInfo{Type: "application/x-tar", Encoding: "gzip"},
+	".tbz2":    repository.MediaInfo{Type: "application/x-tar", Encoding: "bzip2"},
+	".tb2":     repository.MediaInfo{Type: "application/x-tar", Encoding: "bzip2"},
+	".tbz":     repository.MediaInfo{Type: "application/x-tar", Encoding: "bzip2"},
+	".tar.bz2": repository.MediaInfo{Type: "application/x-tar", Encoding: "bzip2"},
+}
+
+// MediaInfoForFileName returns the MediaInfo based on the file's extension.
+func MediaInfoForFileName(fileName string) repository.MediaInfo {
+	fileName = strings.ToLower(fileName)
+	for k, v := range typemap {
+		if strings.HasSuffix(fileName, k) {
+			return v
+		}
+	}
+	return repository.MediaInfo{Type: defaultType}
+}
+
+// Install installs a package in the given directory. If the package is a TAR or
+// ZIP archive, its content is extracted in the destination directory.
+// Otherwise, the package file itself is copied to the destination directory.
+func Install(pkgFile, dir string) error {
+	mediaInfo, err := LoadMediaInfo(pkgFile)
+	if err != nil {
+		return err
+	}
+	switch mediaInfo.Type {
+	case "application/x-tar":
+		return extractTar(pkgFile, mediaInfo, dir)
+	case "application/zip":
+		return extractZip(pkgFile, dir)
+	default:
+		return fmt.Errorf("unsupported media type: %v", mediaInfo.Type)
+	}
+}
+
+// LoadMediaInfo returns the MediaInfo for the given package file.
+func LoadMediaInfo(pkgFile string) (repository.MediaInfo, error) {
+	jInfo, err := ioutil.ReadFile(pkgFile + ".__info")
+	if err != nil {
+		return repository.MediaInfo{}, err
+	}
+	var info repository.MediaInfo
+	if err := json.Unmarshal(jInfo, &info); err != nil {
+		return repository.MediaInfo{}, err
+	}
+	return info, nil
+}
+
+// SaveMediaInfo saves the media info for a package.
+func SaveMediaInfo(pkgFile string, mediaInfo repository.MediaInfo) error {
+	jInfo, err := json.Marshal(mediaInfo)
+	if err != nil {
+		return err
+	}
+	infoFile := pkgFile + ".__info"
+	if err := ioutil.WriteFile(infoFile, jInfo, os.FileMode(0600)); err != nil {
+		return err
+	}
+	return nil
+}
+
+func extractZip(zipFile, installDir string) error {
+	zr, err := zip.OpenReader(zipFile)
+	if err != nil {
+		return err
+	}
+	for _, file := range zr.File {
+		fi := file.FileInfo()
+		name := filepath.Join(installDir, file.Name)
+		if !strings.HasPrefix(name, installDir) {
+			return fmt.Errorf("failed to extract file %q outside of install directory", file.Name)
+		}
+		if fi.IsDir() {
+			if err := os.MkdirAll(name, os.FileMode(fi.Mode()&0700)); err != nil && !os.IsExist(err) {
+				return err
+			}
+			continue
+		}
+		in, err := file.Open()
+		if err != nil {
+			return err
+		}
+		parentName := filepath.Dir(name)
+		if err := os.MkdirAll(parentName, os.FileMode(0700)); err != nil {
+			return err
+		}
+		out, err := os.OpenFile(name, os.O_CREATE|os.O_WRONLY, os.FileMode(fi.Mode()&0700))
+		if err != nil {
+			in.Close()
+			return err
+		}
+		nbytes, err := io.Copy(out, in)
+		in.Close()
+		out.Close()
+		if err != nil {
+			return err
+		}
+		if nbytes != fi.Size() {
+			return fmt.Errorf("file size doesn't match for %q: %d != %d", fi.Name(), nbytes, fi.Size())
+		}
+	}
+	return nil
+}
+
+func extractTar(pkgFile string, mediaInfo repository.MediaInfo, installDir string) error {
+	f, err := os.Open(pkgFile)
+	if err != nil {
+		return err
+	}
+	defer f.Close()
+
+	var reader io.Reader
+	switch enc := mediaInfo.Encoding; enc {
+	case "":
+		reader = f
+	case "gzip":
+		var err error
+		if reader, err = gzip.NewReader(f); err != nil {
+			return err
+		}
+	case "bzip2":
+		reader = bzip2.NewReader(f)
+	default:
+		return fmt.Errorf("unsupported encoding: %q", enc)
+	}
+
+	tr := tar.NewReader(reader)
+	for {
+		hdr, err := tr.Next()
+		if err == io.EOF {
+			return nil
+		}
+		if err != nil {
+			return err
+		}
+		name := filepath.Join(installDir, hdr.Name)
+		if !strings.HasPrefix(name, installDir) {
+			return fmt.Errorf("failed to extract file %q outside of install directory", hdr.Name)
+		}
+		// Regular file
+		if hdr.Typeflag == tar.TypeReg {
+			out, err := os.OpenFile(name, os.O_CREATE|os.O_WRONLY, os.FileMode(hdr.Mode&0700))
+			if err != nil {
+				return err
+			}
+			nbytes, err := io.Copy(out, tr)
+			out.Close()
+			if err != nil {
+				return err
+			}
+			if nbytes != hdr.Size {
+				return fmt.Errorf("file size doesn't match for %q: %d != %d", hdr.Name, nbytes, hdr.Size)
+			}
+			continue
+		}
+		// Directory
+		if hdr.Typeflag == tar.TypeDir {
+			if err := os.Mkdir(name, os.FileMode(hdr.Mode&0700)); err != nil && !os.IsExist(err) {
+				return err
+			}
+			continue
+		}
+		// Skip unsupported types
+		// TODO(rthellend): Consider adding support for Symlink.
+	}
+}
diff --git a/services/mgmt/lib/packages/packages_test.go b/services/mgmt/lib/packages/packages_test.go
new file mode 100644
index 0000000..8182b44
--- /dev/null
+++ b/services/mgmt/lib/packages/packages_test.go
@@ -0,0 +1,242 @@
+package packages_test
+
+import (
+	"archive/tar"
+	"archive/zip"
+	"compress/gzip"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"reflect"
+	"sort"
+	"testing"
+
+	"veyron.io/veyron/veyron2/services/mgmt/repository"
+
+	"veyron.io/veyron/veyron/services/mgmt/lib/packages"
+)
+
+func TestInstall(t *testing.T) {
+	workdir, err := ioutil.TempDir("", "packages-test-")
+	if err != nil {
+		t.Fatalf("ioutil.TempDir failed: %v", err)
+	}
+	defer os.RemoveAll(workdir)
+	srcdir := filepath.Join(workdir, "src")
+	dstdir := filepath.Join(workdir, "dst")
+	createFiles(t, srcdir)
+
+	zipfile := filepath.Join(workdir, "archivezip")
+	tarfile := filepath.Join(workdir, "archivetar")
+	tgzfile := filepath.Join(workdir, "archivetgz")
+
+	makeZip(t, zipfile, srcdir)
+	makeTar(t, tarfile, srcdir)
+	doGzip(t, tarfile, tgzfile)
+
+	binfile := filepath.Join(workdir, "binfile")
+	ioutil.WriteFile(binfile, []byte("This is a binary file"), os.FileMode(0644))
+	ioutil.WriteFile(binfile+".__info", []byte(`{"type":"application/octet-stream"}`), os.FileMode(0644))
+
+	expected := []string{
+		"a perm:700",
+		"a/b perm:700",
+		"a/b/xyzzy.txt perm:600",
+		"a/bar.txt perm:600",
+		"a/foo.txt perm:600",
+	}
+	for _, file := range []string{zipfile, tarfile, tgzfile} {
+		setupDstDir(t, dstdir)
+		if err := packages.Install(file, dstdir); err != nil {
+			t.Errorf("packages.Install failed for %q: %v", file, err)
+		}
+		files := scanDir(dstdir)
+		if !reflect.DeepEqual(files, expected) {
+			t.Errorf("unexpected result for %q: Got %q, want %q", file, files, expected)
+		}
+	}
+
+	setupDstDir(t, dstdir)
+	if err := packages.Install(binfile, dstdir); err == nil {
+		t.Errorf("expected packages.Install to fail %q", binfile)
+	}
+}
+
+func TestMediaInfo(t *testing.T) {
+	testcases := []struct {
+		filename string
+		expected repository.MediaInfo
+	}{
+		{"foo.zip", repository.MediaInfo{Type: "application/zip"}},
+		{"foo.ZIP", repository.MediaInfo{Type: "application/zip"}},
+		{"foo.tar", repository.MediaInfo{Type: "application/x-tar"}},
+		{"foo.TAR", repository.MediaInfo{Type: "application/x-tar"}},
+		{"foo.tgz", repository.MediaInfo{Type: "application/x-tar", Encoding: "gzip"}},
+		{"FOO.TAR.GZ", repository.MediaInfo{Type: "application/x-tar", Encoding: "gzip"}},
+		{"foo.tbz2", repository.MediaInfo{Type: "application/x-tar", Encoding: "bzip2"}},
+		{"foo.tar.bz2", repository.MediaInfo{Type: "application/x-tar", Encoding: "bzip2"}},
+		{"foo", repository.MediaInfo{Type: "application/octet-stream"}},
+	}
+	for _, tc := range testcases {
+		if got := packages.MediaInfoForFileName(tc.filename); !reflect.DeepEqual(got, tc.expected) {
+			t.Errorf("unexpected result for %q: Got %v, want %v", tc.filename, got, tc.expected)
+		}
+	}
+}
+
+func createFiles(t *testing.T, dir string) {
+	if err := os.Mkdir(dir, os.FileMode(0755)); err != nil {
+		t.Fatalf("os.Mkdir(%q) failed: %v", dir, err)
+	}
+	dirs := []string{"a", "a/b"}
+	for _, d := range dirs {
+		fullname := filepath.Join(dir, d)
+		if err := os.Mkdir(fullname, os.FileMode(0755)); err != nil {
+			t.Fatalf("os.Mkdir(%q) failed: %v", fullname, err)
+		}
+	}
+	files := []string{"a/foo.txt", "a/bar.txt", "a/b/xyzzy.txt"}
+	for _, f := range files {
+		fullname := filepath.Join(dir, f)
+		if err := ioutil.WriteFile(fullname, []byte(f), os.FileMode(0644)); err != nil {
+			t.Fatalf("ioutil.WriteFile(%q) failed: %v", fullname, err)
+		}
+	}
+}
+
+func makeZip(t *testing.T, zipfile, dir string) {
+	z, err := os.OpenFile(zipfile, os.O_CREATE|os.O_WRONLY, os.FileMode(0644))
+	if err != nil {
+		t.Fatalf("os.OpenFile(%q) failed: %v", zipfile, err)
+	}
+	defer z.Close()
+	w := zip.NewWriter(z)
+	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
+		if err != nil {
+			t.Fatalf("Walk(%q) error: %v", dir, err)
+		}
+		if dir == path {
+			return nil
+		}
+		fh, err := zip.FileInfoHeader(info)
+		if err != nil {
+			t.Fatalf("FileInfoHeader failed: %v", err)
+		}
+		fh.Name, _ = filepath.Rel(dir, path)
+		hdr, err := w.CreateHeader(fh)
+		if err != nil {
+			t.Fatalf("w.CreateHeader failed: %v", err)
+		}
+		if !info.IsDir() {
+			content, err := ioutil.ReadFile(path)
+			if err != nil {
+				t.Fatalf("ioutil.ReadFile(%q) failed: %v", path, err)
+			}
+			if _, err = hdr.Write(content); err != nil {
+				t.Fatalf("hdr.Write(%q) failed: %v", content, err)
+			}
+		}
+		return nil
+	})
+	if err := w.Close(); err != nil {
+		t.Fatalf("w.Close() failed: %v", err)
+	}
+	if err := ioutil.WriteFile(zipfile+".__info", []byte(`{"type":"application/zip"}`), os.FileMode(0644)); err != nil {
+		t.Fatalf("ioutil.WriteFile() failed: %v", err)
+	}
+}
+
+func makeTar(t *testing.T, tarfile, dir string) {
+	tf, err := os.OpenFile(tarfile, os.O_CREATE|os.O_WRONLY, os.FileMode(0644))
+	if err != nil {
+		t.Fatalf("os.OpenFile(%q) failed: %v", tarfile, err)
+	}
+	defer tf.Close()
+
+	tw := tar.NewWriter(tf)
+	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
+		if err != nil {
+			t.Fatalf("Walk(%q) error: %v", dir, err)
+		}
+		if dir == path {
+			return nil
+		}
+		hdr, err := tar.FileInfoHeader(info, "")
+		if err != nil {
+			t.Fatalf("tar.FileInfoHeader failed: %v", err)
+		}
+		hdr.Name, _ = filepath.Rel(dir, path)
+		if err := tw.WriteHeader(hdr); err != nil {
+			t.Fatalf("tw.WriteHeader failed: %v", err)
+		}
+		if !info.IsDir() {
+			content, err := ioutil.ReadFile(path)
+			if err != nil {
+				t.Fatalf("ioutil.ReadFile(%q) failed: %v", path, err)
+			}
+			if _, err := tw.Write(content); err != nil {
+				t.Fatalf("tw.Write failed: %v", err)
+			}
+		}
+		return nil
+	})
+	if err := tw.Close(); err != nil {
+		t.Fatalf("tw.Close failed: %v", err)
+	}
+	if err := ioutil.WriteFile(tarfile+".__info", []byte(`{"type":"application/x-tar"}`), os.FileMode(0644)); err != nil {
+		t.Fatalf("ioutil.WriteFile() failed: %v", err)
+	}
+}
+
+func doGzip(t *testing.T, infile, outfile string) {
+	in, err := os.Open(infile)
+	if err != nil {
+		t.Fatalf("os.Open(%q) failed: %v", infile, err)
+	}
+	defer in.Close()
+	out, err := os.OpenFile(outfile, os.O_CREATE|os.O_WRONLY, os.FileMode(0644))
+	if err != nil {
+		t.Fatalf("os.OpenFile(%q) failed: %v", outfile, err)
+	}
+	defer out.Close()
+	writer := gzip.NewWriter(out)
+	defer writer.Close()
+	if _, err := io.Copy(writer, in); err != nil {
+		t.Fatalf("io.Copy() failed: %v", err)
+	}
+
+	info, err := packages.LoadMediaInfo(infile)
+	if err != nil {
+		t.Fatalf("LoadMediaInfo(%q) failed: %v", infile, err)
+	}
+	info.Encoding = "gzip"
+	if err := packages.SaveMediaInfo(outfile, info); err != nil {
+		t.Fatalf("SaveMediaInfo(%v) failed: %v", outfile, err)
+	}
+}
+
+func scanDir(root string) []string {
+	files := []string{}
+	filepath.Walk(root, func(path string, info os.FileInfo, _ error) error {
+		if root == path {
+			return nil
+		}
+		rel, _ := filepath.Rel(root, path)
+		perm := info.Mode() & 0700
+		files = append(files, fmt.Sprintf("%s perm:%o", rel, perm))
+		return nil
+	})
+	sort.Strings(files)
+	return files
+}
+
+func setupDstDir(t *testing.T, dst string) {
+	if err := os.RemoveAll(dst); err != nil {
+		t.Fatalf("os.RemoveAll(%q) failed: %v", dst, err)
+	}
+	if err := os.Mkdir(dst, os.FileMode(0755)); err != nil {
+		t.Fatalf("os.Mkdir(%q) failed: %v", dst, err)
+	}
+}
diff --git a/services/mgmt/logreader/impl/logfile.go b/services/mgmt/logreader/impl/logfile.go
index fd6f354..0011fa8 100644
--- a/services/mgmt/logreader/impl/logfile.go
+++ b/services/mgmt/logreader/impl/logfile.go
@@ -110,10 +110,10 @@
 	return reader.tell(), nil
 }
 
-// VGlobChildren returns the list of files in a directory, or an empty list if
-// the object is a file.
-func (i *logfileService) VGlobChildren() ([]string, error) {
-	vlog.VI(1).Infof("%v.VGlobChildren()", i.suffix)
+// GlobChildren__ returns the list of files in a directory streamed on a
+// channel. The list is empty if the object is a file.
+func (i *logfileService) GlobChildren__() (<-chan string, error) {
+	vlog.VI(1).Infof("%v.GlobChildren__()", i.suffix)
 	dirName, err := translateNameToFilename(i.root, i.suffix)
 	if err != nil {
 		return nil, err
@@ -129,22 +129,24 @@
 		return nil, nil
 	}
 
-	f, err := os.Open(dirName)
-	if err != nil {
-		return nil, errOperationFailed
-	}
-	fi, err := f.Readdir(0)
-	if err != nil {
-		return nil, errOperationFailed
-	}
-	f.Close()
-	children := []string{}
-	for _, file := range fi {
-		fileName := file.Name()
-		if fileName == "." || fileName == ".." {
-			continue
+	const batchSize = 100
+	ch := make(chan string, batchSize)
+	go func() {
+		defer close(ch)
+		f, err := os.Open(dirName)
+		if err != nil {
+			return
 		}
-		children = append(children, file.Name())
-	}
-	return children, nil
+		defer f.Close()
+		for {
+			fi, err := f.Readdir(batchSize)
+			if err != nil {
+				return
+			}
+			for _, file := range fi {
+				ch <- file.Name()
+			}
+		}
+	}()
+	return ch, nil
 }
diff --git a/services/mgmt/node/impl/app_service.go b/services/mgmt/node/impl/app_service.go
index 3473a37..b5ab1ab 100644
--- a/services/mgmt/node/impl/app_service.go
+++ b/services/mgmt/node/impl/app_service.go
@@ -21,6 +21,10 @@
 //         bin                      - application binary
 //         previous                 - symbolic link to previous version directory
 //         envelope                 - application envelope (JSON-encoded)
+//         pkg/                     - the application packages
+//           <pkg name>
+//           <pkg name>.__info
+//           ...
 //       <version 2 timestamp>
 //       ...
 //       current                    - symbolic link to the current version
@@ -29,6 +33,9 @@
 //           credentials/           - holds veyron credentials (unless running
 //                                    through security agent)
 //           root/                  - workspace that the instance is run from
+//             packages/            - the installed packages
+//               <pkg name>/
+//               ...
 //           logs/                  - stderr/stdout and log files generated by instance
 //           info                   - metadata for the instance (such as app
 //                                    cycle manager name and process id)
@@ -128,7 +135,8 @@
 	"veyron.io/veyron/veyron2/security"
 	"veyron.io/veyron/veyron2/services/mgmt/appcycle"
 	"veyron.io/veyron/veyron2/services/mgmt/application"
-	"veyron.io/veyron/veyron2/verror"
+	"veyron.io/veyron/veyron2/services/security/access"
+	"veyron.io/veyron/veyron2/verror2"
 	"veyron.io/veyron/veyron2/vlog"
 
 	vexec "veyron.io/veyron/veyron/lib/exec"
@@ -136,6 +144,8 @@
 	vsecurity "veyron.io/veyron/veyron/security"
 	"veyron.io/veyron/veyron/security/agent"
 	"veyron.io/veyron/veyron/security/agent/keymgr"
+	libbinary "veyron.io/veyron/veyron/services/mgmt/lib/binary"
+	libpackages "veyron.io/veyron/veyron/services/mgmt/lib/packages"
 	iconfig "veyron.io/veyron/veyron/services/mgmt/node/config"
 )
 
@@ -151,12 +161,12 @@
 	jsonInfo, err := json.Marshal(info)
 	if err != nil {
 		vlog.Errorf("Marshal(%v) failed: %v", info, err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	infoPath := filepath.Join(dir, "info")
 	if err := ioutil.WriteFile(infoPath, jsonInfo, 0600); err != nil {
 		vlog.Errorf("WriteFile(%v) failed: %v", infoPath, err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	return nil
 }
@@ -166,10 +176,10 @@
 	info := new(instanceInfo)
 	if infoBytes, err := ioutil.ReadFile(infoPath); err != nil {
 		vlog.Errorf("ReadFile(%v) failed: %v", infoPath, err)
-		return nil, errOperationFailed
+		return nil, verror2.Make(ErrOperationFailed, nil)
 	} else if err := json.Unmarshal(infoBytes, info); err != nil {
 		vlog.Errorf("Unmarshal(%v) failed: %v", infoBytes, err)
-		return nil, errOperationFailed
+		return nil, verror2.Make(ErrOperationFailed, nil)
 	}
 	return info, nil
 }
@@ -196,7 +206,7 @@
 	uat    BlessingSystemAssociationStore
 	locks  aclLocks
 	// Reference to the nodemanager top-level ACL list.
-	nodeACL security.ACL
+	nodeACL access.TaggedACLMap
 	// securityAgent holds state related to the security agent (nil if not
 	// using the agent).
 	securityAgent *securityAgentState
@@ -206,12 +216,12 @@
 	jsonEnvelope, err := json.Marshal(envelope)
 	if err != nil {
 		vlog.Errorf("Marshal(%v) failed: %v", envelope, err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	path := filepath.Join(dir, "envelope")
 	if err := ioutil.WriteFile(path, jsonEnvelope, 0600); err != nil {
 		vlog.Errorf("WriteFile(%v) failed: %v", path, err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	return nil
 }
@@ -221,10 +231,10 @@
 	envelope := new(application.Envelope)
 	if envelopeBytes, err := ioutil.ReadFile(path); err != nil {
 		vlog.Errorf("ReadFile(%v) failed: %v", path, err)
-		return nil, errOperationFailed
+		return nil, verror2.Make(ErrOperationFailed, nil)
 	} else if err := json.Unmarshal(envelopeBytes, envelope); err != nil {
 		vlog.Errorf("Unmarshal(%v) failed: %v", envelopeBytes, err)
-		return nil, errOperationFailed
+		return nil, verror2.Make(ErrOperationFailed, nil)
 	}
 	return envelope, nil
 }
@@ -233,7 +243,7 @@
 	path := filepath.Join(dir, "origin")
 	if err := ioutil.WriteFile(path, []byte(originVON), 0600); err != nil {
 		vlog.Errorf("WriteFile(%v) failed: %v", path, err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	return nil
 }
@@ -242,7 +252,7 @@
 	path := filepath.Join(dir, "origin")
 	if originBytes, err := ioutil.ReadFile(path); err != nil {
 		vlog.Errorf("ReadFile(%v) failed: %v", path, err)
-		return "", errOperationFailed
+		return "", verror2.Make(ErrOperationFailed, nil)
 	} else {
 		return string(originBytes), nil
 	}
@@ -308,7 +318,7 @@
 	if envelope.Title == application.NodeManagerTitle {
 		// Disallow node manager apps from being installed like a
 		// regular app.
-		return nil, errInvalidOperation
+		return nil, verror2.Make(ErrInvalidOperation, ctx)
 	}
 	return envelope, nil
 }
@@ -317,12 +327,27 @@
 func newVersion(installationDir string, envelope *application.Envelope, oldVersionDir string) (string, error) {
 	versionDir := filepath.Join(installationDir, generateVersionDirName())
 	if err := mkdir(versionDir); err != nil {
-		return "", errOperationFailed
+		return "", verror2.Make(ErrOperationFailed, nil)
+	}
+	pkgDir := filepath.Join(versionDir, "pkg")
+	if err := mkdir(pkgDir); err != nil {
+		return "", verror2.Make(ErrOperationFailed, nil)
 	}
 	// TODO(caprita): Share binaries if already existing locally.
 	if err := downloadBinary(versionDir, "bin", envelope.Binary); err != nil {
 		return versionDir, err
 	}
+	for localPkg, pkgName := range envelope.Packages {
+		if localPkg == "" || localPkg[0] == '.' || strings.Contains(localPkg, string(filepath.Separator)) {
+			vlog.Infof("invalid local package name: %q", localPkg)
+			return versionDir, verror2.Make(ErrOperationFailed, nil)
+		}
+		path := filepath.Join(pkgDir, localPkg)
+		if err := libbinary.DownloadToFile(rt.R().NewContext(), pkgName, path); err != nil {
+			vlog.Infof("DownloadToFile(%q, %q) failed: %v", pkgName, path, err)
+			return versionDir, verror2.Make(ErrOperationFailed, nil)
+		}
+	}
 	if err := saveEnvelope(versionDir, envelope); err != nil {
 		return versionDir, err
 	}
@@ -330,7 +355,7 @@
 		previousLink := filepath.Join(versionDir, "previous")
 		if err := os.Symlink(oldVersionDir, previousLink); err != nil {
 			vlog.Errorf("Symlink(%v, %v) failed: %v", oldVersionDir, previousLink, err)
-			return versionDir, errOperationFailed
+			return versionDir, verror2.Make(ErrOperationFailed, nil)
 		}
 	}
 	// updateLink should be the last thing we do, after we've ensured the
@@ -339,23 +364,14 @@
 	return versionDir, updateLink(versionDir, filepath.Join(installationDir, "current"))
 }
 
-// TODO(rjkroege): Refactor this code with the intance creation code.
-func initializeInstallationACLs(dir string, blessings []string, acl security.ACL) error {
-	// Start out with the claimant's ACLs and add the invoker's blessings.
-
-	var labels security.LabelSet
-	if acl.In == nil {
-		// The acl.In will be empty for an unclaimed node manager. In this case,
-		// create it.
-		acl.In = make(map[security.BlessingPattern]security.LabelSet)
+// TODO(rjkroege): Refactor this code with the instance creation code.
+func initializeInstallationACLs(dir string, blessings []string, acl access.TaggedACLMap) error {
+	// Add the invoker's blessings.
+	for _, b := range blessings {
+		for _, tag := range access.AllTypicalTags() {
+			acl.Add(security.BlessingPattern(b), string(tag))
+		}
 	}
-	labels = security.AllLabels
-
-	for _, name := range blessings {
-		// TODO(rjkroege): Use custom labels.
-		acl.In[security.BlessingPattern(name)] = labels
-	}
-
 	aclDir := path.Join(dir, "acls")
 	aclData := path.Join(aclDir, "data")
 	aclSig := path.Join(aclDir, "signature")
@@ -364,9 +380,9 @@
 
 func (i *appService) Install(call ipc.ServerContext, applicationVON string) (string, error) {
 	if len(i.suffix) > 0 {
-		return "", errInvalidSuffix
+		return "", verror2.Make(ErrInvalidSuffix, call)
 	}
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ctx, cancel := rt.R().NewContext().WithTimeout(ipcContextTimeout)
 	defer cancel()
 	envelope, err := fetchAppEnvelope(ctx, applicationVON)
 	if err != nil {
@@ -392,7 +408,10 @@
 		return "", err
 	}
 
-	if err := initializeInstallationACLs(installationDir, call.RemoteBlessings().ForContext(call), i.nodeACL); err != nil {
+	// TODO(caprita,rjkroege): Should the installation ACLs really be
+	// seeded with the node ACL? Instead, might want to hide the nodeACL
+	// from the app?
+	if err := initializeInstallationACLs(installationDir, call.RemoteBlessings().ForContext(call), i.nodeACL.Copy()); err != nil {
 		return "", err
 	}
 	deferrer = nil
@@ -414,23 +433,23 @@
 	file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, perm)
 	if err != nil {
 		vlog.Errorf("OpenFile(%v) failed: %v", path, err)
-		return nil, errOperationFailed
+		return nil, verror2.Make(ErrOperationFailed, nil)
 	}
 	return file, nil
 }
 
 func installationDirCore(components []string, root string) (string, error) {
 	if nComponents := len(components); nComponents != 2 {
-		return "", errInvalidSuffix
+		return "", verror2.Make(ErrInvalidSuffix, nil)
 	}
 	app, installation := components[0], components[1]
 	installationDir := filepath.Join(root, applicationDirName(app), installationDirName(installation))
 	if _, err := os.Stat(installationDir); err != nil {
 		if os.IsNotExist(err) {
-			return "", errNotExist
+			return "", verror2.Make(ErrObjectNoExist, nil)
 		}
 		vlog.Errorf("Stat(%v) failed: %v", installationDir, err)
-		return "", errOperationFailed
+		return "", verror2.Make(ErrOperationFailed, nil)
 	}
 	return installationDir, nil
 }
@@ -446,13 +465,13 @@
 		client, err := rt.R().NewClient(options.VCSecurityNone)
 		if err != nil {
 			vlog.Errorf("NewClient() failed: %v", err)
-			return errOperationFailed
+			return verror2.Make(ErrOperationFailed, nil)
 		}
 		defer client.Close()
 		// TODO(caprita): release the socket created by NewAgentPrincipal.
 		if p, err = agent.NewAgentPrincipal(client, int(conn.Fd()), rt.R().NewContext()); err != nil {
 			vlog.Errorf("NewAgentPrincipal() failed: %v", err)
-			return errOperationFailed
+			return verror2.Make(ErrOperationFailed, nil)
 		}
 		info.SecurityAgentHandle = handle
 	} else {
@@ -462,7 +481,7 @@
 		var err error
 		if p, err = vsecurity.CreatePersistentPrincipal(credentialsDir, nil); err != nil {
 			vlog.Errorf("CreatePersistentPrincipal(%v, nil) failed: %v", credentialsDir, err)
-			return errOperationFailed
+			return verror2.Make(ErrOperationFailed, nil)
 		}
 	}
 	// Read the app installation version's envelope to obtain the app title.
@@ -479,27 +498,27 @@
 	// with the app title.
 	grantedBlessings := call.Blessings()
 	if grantedBlessings == nil {
-		return errInvalidBlessing
+		return verror2.Make(ErrInvalidBlessing, nil)
 	}
 	// TODO(caprita): Revisit UnconstrainedUse.
 	appBlessings, err := nmPrincipal.Bless(p.PublicKey(), grantedBlessings, envelope.Title, security.UnconstrainedUse())
 	if err != nil {
 		vlog.Errorf("Bless() failed: %v", err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	// The blessings we extended from the blessings that the Start-er
 	// granted are the default blessings for the app.
 	if err := p.BlessingStore().SetDefault(appBlessings); err != nil {
 		vlog.Errorf("BlessingStore.SetDefault() failed: %v", err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	if _, err := p.BlessingStore().Set(appBlessings, security.AllPrincipals); err != nil {
 		vlog.Errorf("BlessingStore.Set() failed: %v", err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	if err := p.AddToRoots(appBlessings); err != nil {
 		vlog.Errorf("AddToRoots() failed: %v", err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	// In addition, we give the app separate blessings for the purpose of
 	// communicating with the node manager.
@@ -522,7 +541,7 @@
 	for _, n := range names {
 		if _, err := p.BlessingStore().Set(nmBlessings, security.BlessingPattern(n)); err != nil {
 			vlog.Errorf("BlessingStore.Set() failed: %v", err)
-			return errOperationFailed
+			return verror2.Make(ErrOperationFailed, nil)
 		}
 	}
 	// We also want to override the app cycle manager's server blessing in
@@ -532,16 +551,16 @@
 	randomPattern, err := generateRandomString()
 	if err != nil {
 		vlog.Errorf("generateRandomString() failed: %v", err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	if _, err := p.BlessingStore().Set(nmBlessings, security.BlessingPattern(randomPattern)); err != nil {
 		vlog.Errorf("BlessingStore.Set() failed: %v", err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	info.NodeManagerPeerPattern = randomPattern
 	if err := p.AddToRoots(nmBlessings); err != nil {
 		vlog.Errorf("AddToRoots() failed: %v", err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	return nil
 }
@@ -554,23 +573,40 @@
 	return installationDirCore(i.suffix, i.config.Root)
 }
 
-func initializeInstanceACLs(instanceDir string, blessings []string, acl security.ACL) error {
-	if acl.In == nil {
-		// The acl.In will be empty for an unclaimed node manager. In this case,
-		// create it
-		acl.In = make(map[security.BlessingPattern]security.LabelSet)
+// installPackages installs all the packages for a new instance.
+func installPackages(versionDir, instanceDir string) error {
+	envelope, err := loadEnvelope(versionDir)
+	if err != nil {
+		return err
 	}
-
-	labels := security.AllLabels
-	for _, name := range blessings {
-		// TODO(rjkroege): Use custom labels.
-		acl.In[security.BlessingPattern(name)] = labels
+	packagesDir := filepath.Join(instanceDir, "root", "packages")
+	if err := os.MkdirAll(packagesDir, os.FileMode(0700)); err != nil {
+		return err
 	}
+	// TODO(rthellend): Consider making the packages read-only and sharing
+	// them between apps or instances.
+	for pkg, _ := range envelope.Packages {
+		pkgFile := filepath.Join(versionDir, "pkg", pkg)
+		dstDir := filepath.Join(packagesDir, pkg)
+		if err := os.MkdirAll(dstDir, os.FileMode(0700)); err != nil {
+			return err
+		}
+		if err := libpackages.Install(pkgFile, dstDir); err != nil {
+			return err
+		}
+	}
+	return nil
+}
 
+func initializeInstanceACLs(instanceDir string, blessings []string, acl access.TaggedACLMap) error {
+	for _, b := range blessings {
+		for _, tag := range access.AllTypicalTags() {
+			acl.Add(security.BlessingPattern(b), string(tag))
+		}
+	}
 	aclDir := path.Join(instanceDir, "acls")
 	aclData := path.Join(aclDir, "data")
 	aclSig := path.Join(aclDir, "signature")
-
 	return writeACLs(aclData, aclSig, aclDir, acl)
 }
 
@@ -581,23 +617,27 @@
 		return "", "", err
 	}
 	if !installationStateIs(installationDir, active) {
-		return "", "", errInvalidOperation
+		return "", "", verror2.Make(ErrInvalidOperation, call)
 	}
 	instanceID := generateID()
 	instanceDir := filepath.Join(installationDir, "instances", instanceDirName(instanceID))
 	if mkdir(instanceDir) != nil {
-		return "", instanceID, errOperationFailed
+		return "", instanceID, verror2.Make(ErrOperationFailed, call)
 	}
 	currLink := filepath.Join(installationDir, "current")
 	versionDir, err := filepath.EvalSymlinks(currLink)
 	if err != nil {
 		vlog.Errorf("EvalSymlinks(%v) failed: %v", currLink, err)
-		return instanceDir, instanceID, errOperationFailed
+		return instanceDir, instanceID, verror2.Make(ErrOperationFailed, call)
 	}
 	versionLink := filepath.Join(instanceDir, "version")
 	if err := os.Symlink(versionDir, versionLink); err != nil {
 		vlog.Errorf("Symlink(%v, %v) failed: %v", versionDir, versionLink, err)
-		return instanceDir, instanceID, errOperationFailed
+		return instanceDir, instanceID, verror2.Make(ErrOperationFailed, call)
+	}
+	if err := installPackages(versionDir, instanceDir); err != nil {
+		vlog.Errorf("installPackages(%v, %v) failed: %v", versionDir, instanceDir, err)
+		return instanceDir, instanceID, verror2.Make(ErrOperationFailed, call)
 	}
 	instanceInfo := new(instanceInfo)
 	if err := setupPrincipal(instanceDir, versionDir, call, i.securityAgent, instanceInfo); err != nil {
@@ -610,7 +650,7 @@
 		return instanceDir, instanceID, err
 	}
 
-	if err := initializeInstanceACLs(instanceDir, call.RemoteBlessings().ForContext(call), i.nodeACL); err != nil {
+	if err := initializeInstanceACLs(instanceDir, call.RemoteBlessings().ForContext(call), i.nodeACL.Copy()); err != nil {
 		return instanceDir, instanceID, err
 	}
 	return instanceDir, instanceID, nil
@@ -631,11 +671,12 @@
 // and is probably not a good fit in other contexts. Revisit the design
 // as appropriate. This function also internalizes a decision as to when
 // it is possible to start an application that needs to be made explicit.
-func systemAccountForHelper(helperPath string, identityNames []string, uat BlessingSystemAssociationStore) (systemName string, err error) {
+func systemAccountForHelper(ctx ipc.ServerContext, helperPath string, uat BlessingSystemAssociationStore) (systemName string, err error) {
+	identityNames := ctx.RemoteBlessings().ForContext(ctx)
 	helperStat, err := os.Stat(helperPath)
 	if err != nil {
 		vlog.Errorf("Stat(%v) failed: %v. helper is required.", helperPath, err)
-		return "", errOperationFailed
+		return "", verror2.Make(ErrOperationFailed, ctx)
 	}
 	haveHelper := isSetuid(helperStat)
 	systemName, present := uat.SystemAccountForBlessings(identityNames)
@@ -648,7 +689,7 @@
 		// Therefore, the node manager must never run an app as itself to
 		// prevent an app trivially granting itself root permissions.
 		// There must be an associated uname for the account in this case.
-		return "", verror.NoAccessf("use of setuid helper requires an associated uname.")
+		return "", verror2.Make(verror2.NoAccess, ctx, "use of setuid helper requires an associated uname.")
 	case !haveHelper:
 		// When the helper is not setuid, the helper can't change the
 		// app's uid so just run the app as the node manager's uname
@@ -657,11 +698,11 @@
 		user, err := user.Current()
 		if err != nil {
 			vlog.Errorf("user.Current() failed: %v", err)
-			return "", errOperationFailed
+			return "", verror2.Make(ErrOperationFailed, ctx)
 		}
 		return user.Username, nil
 	}
-	return "", errOperationFailed
+	return "", verror2.Make(ErrOperationFailed, ctx)
 }
 
 func genCmd(instanceDir, helperPath, systemName string) (*exec.Cmd, error) {
@@ -669,7 +710,7 @@
 	versionDir, err := filepath.EvalSymlinks(versionLink)
 	if err != nil {
 		vlog.Errorf("EvalSymlinks(%v) failed: %v", versionLink, err)
-		return nil, errOperationFailed
+		return nil, verror2.Make(ErrOperationFailed, nil)
 	}
 	envelope, err := loadEnvelope(versionDir)
 	if err != nil {
@@ -678,7 +719,7 @@
 	binPath := filepath.Join(versionDir, "bin")
 	if _, err := os.Stat(binPath); err != nil {
 		vlog.Errorf("Stat(%v) failed: %v", binPath, err)
-		return nil, errOperationFailed
+		return nil, verror2.Make(ErrOperationFailed, nil)
 	}
 
 	cmd := exec.Command(helperPath)
@@ -778,21 +819,20 @@
 			agentCleaner()
 		}
 		vlog.Errorf("Start() failed: %v", err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	if agentCleaner != nil {
 		agentCleaner()
 	}
 
 	// Wait for the child process to start.
-	timeout := 10 * time.Second
-	if err := handle.WaitForReady(timeout); err != nil {
-		vlog.Errorf("WaitForReady(%v) failed: %v", timeout, err)
-		return errOperationFailed
+	if err := handle.WaitForReady(childReadyTimeout); err != nil {
+		vlog.Errorf("WaitForReady(%v) failed: %v", childReadyTimeout, err)
+		return verror2.Make(ErrOperationFailed, nil)
 	}
-	childName, err := listener.waitForValue(timeout)
+	childName, err := listener.waitForValue(childReadyTimeout)
 	if err != nil {
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	info.AppCycleMgrName, info.Pid = childName, handle.Pid()
 	if err := saveInstanceInfo(instanceDir, info); err != nil {
@@ -829,7 +869,7 @@
 		return nil, err
 	}
 
-	systemName, err := systemAccountForHelper(helper, call.RemoteBlessings().ForContext(call), i.uat)
+	systemName, err := systemAccountForHelper(call, helper, i.uat)
 	if err != nil {
 		cleanupDir(instanceDir, helper)
 		return nil, err
@@ -854,7 +894,7 @@
 // referred to by the given suffix relative to the given root directory.
 func instanceDir(root string, suffix []string) (string, error) {
 	if nComponents := len(suffix); nComponents != 3 {
-		return "", errInvalidSuffix
+		return "", verror2.Make(ErrInvalidSuffix, nil)
 	}
 	app, installation, instance := suffix[0], suffix[1], suffix[2]
 	instancesDir := filepath.Join(root, applicationDirName(app), installationDirName(installation), "instances")
@@ -875,7 +915,7 @@
 		return err
 	}
 
-	systemName, err := systemAccountForHelper(i.config.Helper, call.RemoteBlessings().ForContext(call), i.uat)
+	systemName, err := systemAccountForHelper(call, i.config.Helper, i.uat)
 	if err != nil {
 		return err
 	}
@@ -886,19 +926,19 @@
 	}
 
 	if startSystemName != systemName {
-		return verror.NoAccessf("Not allowed to resume an application under a different system name.")
+		return verror2.Make(verror2.NoAccess, call, "Not allowed to resume an application under a different system name.")
 	}
 	return i.run(instanceDir, systemName)
 }
 
 func stopAppRemotely(appVON string) error {
 	appStub := appcycle.AppCycleClient(appVON)
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ctx, cancel := rt.R().NewContext().WithTimeout(ipcContextTimeout)
 	defer cancel()
 	stream, err := appStub.Stop(ctx)
 	if err != nil {
 		vlog.Errorf("%v.Stop() failed: %v", appVON, err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	rstream := stream.RecvStream()
 	for rstream.Advance() {
@@ -906,11 +946,11 @@
 	}
 	if err := rstream.Err(); err != nil {
 		vlog.Errorf("Advance() failed: %v", err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	if err := stream.Finish(); err != nil {
 		vlog.Errorf("Finish() failed: %v", err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	return nil
 }
@@ -930,7 +970,7 @@
 	if err != nil {
 		return err
 	}
-	if err := transitionInstance(instanceDir, suspended, stopped); err == errOperationFailed || err == nil {
+	if err := transitionInstance(instanceDir, suspended, stopped); verror2.Is(err, ErrOperationFailed.ID) || err == nil {
 		return err
 	}
 	if err := transitionInstance(instanceDir, started, stopping); err != nil {
@@ -966,19 +1006,19 @@
 	return transitionInstallation(installationDir, active, uninstalled)
 }
 
-func (i *appService) Update(ipc.ServerContext) error {
+func (i *appService) Update(call ipc.ServerContext) error {
 	installationDir, err := i.installationDir()
 	if err != nil {
 		return err
 	}
 	if !installationStateIs(installationDir, active) {
-		return errInvalidOperation
+		return verror2.Make(ErrInvalidOperation, call)
 	}
 	originVON, err := loadOrigin(installationDir)
 	if err != nil {
 		return err
 	}
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ctx, cancel := rt.R().NewContext().WithTimeout(ipcContextTimeout)
 	defer cancel()
 	newEnvelope, err := fetchAppEnvelope(ctx, originVON)
 	if err != nil {
@@ -988,7 +1028,7 @@
 	oldVersionDir, err := filepath.EvalSymlinks(currLink)
 	if err != nil {
 		vlog.Errorf("EvalSymlinks(%v) failed: %v", currLink, err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, call)
 	}
 	// NOTE(caprita): A race can occur between two competing updates, where
 	// both use the old version as their baseline.  This can result in both
@@ -1003,10 +1043,10 @@
 		return err
 	}
 	if oldEnvelope.Title != newEnvelope.Title {
-		return errIncompatibleUpdate
+		return verror2.Make(ErrAppTitleMismatch, call)
 	}
 	if reflect.DeepEqual(oldEnvelope, newEnvelope) {
-		return errUpdateNoOp
+		return verror2.Make(ErrUpdateNoOp, call)
 	}
 	versionDir, err := newVersion(installationDir, newEnvelope, oldVersionDir)
 	if err != nil {
@@ -1021,13 +1061,13 @@
 	return nil
 }
 
-func (i *appService) Revert(ipc.ServerContext) error {
+func (i *appService) Revert(ctx ipc.ServerContext) error {
 	installationDir, err := i.installationDir()
 	if err != nil {
 		return err
 	}
 	if !installationStateIs(installationDir, active) {
-		return errInvalidOperation
+		return verror2.Make(ErrInvalidOperation, ctx)
 	}
 	// NOTE(caprita): A race can occur between an update and a revert, where
 	// both use the same current version as their starting point.  This will
@@ -1038,21 +1078,21 @@
 	currVersionDir, err := filepath.EvalSymlinks(currLink)
 	if err != nil {
 		vlog.Errorf("EvalSymlinks(%v) failed: %v", currLink, err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, ctx)
 	}
 	previousLink := filepath.Join(currVersionDir, "previous")
 	if _, err := os.Lstat(previousLink); err != nil {
 		if os.IsNotExist(err) {
 			// No 'previous' link -- must be the first version.
-			return errUpdateNoOp
+			return verror2.Make(ErrUpdateNoOp, ctx)
 		}
 		vlog.Errorf("Lstat(%v) failed: %v", previousLink, err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, ctx)
 	}
 	prevVersionDir, err := filepath.EvalSymlinks(previousLink)
 	if err != nil {
 		vlog.Errorf("EvalSymlinks(%v) failed: %v", previousLink, err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, ctx)
 	}
 	return updateLink(prevVersionDir, currLink)
 }
@@ -1154,7 +1194,7 @@
 	}
 }
 
-func (i *appService) VGlobChildren() ([]string, error) {
+func (i *appService) GlobChildren__() (<-chan string, error) {
 	tree := newTreeNode()
 	switch len(i.suffix) {
 	case 0:
@@ -1171,19 +1211,20 @@
 		}
 		i.scanInstance(tree, i.suffix[0], dir)
 	default:
-		return nil, errNotExist
+		return nil, verror2.Make(ErrObjectNoExist, nil)
 	}
 	n := tree.find(i.suffix, false)
 	if n == nil {
-		return nil, errInvalidSuffix
+		return nil, verror2.Make(ErrInvalidSuffix, nil)
 	}
-	children := make([]string, len(n.children))
-	index := 0
-	for child, _ := range n.children {
-		children[index] = child
-		index++
-	}
-	return children, nil
+	ch := make(chan string, 100)
+	go func() {
+		for child, _ := range n.children {
+			ch <- child
+		}
+		close(ch)
+	}()
+	return ch, nil
 }
 
 // TODO(rjkroege): Refactor to eliminate redundancy with newAppSpecificAuthorizer.
@@ -1203,11 +1244,11 @@
 		}
 		return p, nil
 	}
-	return "", errInvalidSuffix
+	return "", verror2.Make(ErrInvalidSuffix, nil)
 }
 
 // TODO(rjkroege): Consider maintaining an in-memory ACL cache.
-func (i *appService) SetACL(_ ipc.ServerContext, acl security.ACL, etag string) error {
+func (i *appService) SetACL(_ ipc.ServerContext, acl access.TaggedACLMap, etag string) error {
 	dir, err := dirFromSuffix(i.suffix, i.config.Root)
 	if err != nil {
 		return err
@@ -1215,10 +1256,10 @@
 	return setAppACL(i.locks, dir, acl, etag)
 }
 
-func (i *appService) GetACL(_ ipc.ServerContext) (acl security.ACL, etag string, err error) {
+func (i *appService) GetACL(_ ipc.ServerContext) (acl access.TaggedACLMap, etag string, err error) {
 	dir, err := dirFromSuffix(i.suffix, i.config.Root)
 	if err != nil {
-		return security.ACL{}, "", err
+		return nil, "", err
 	}
 	return getAppACL(i.locks, dir)
 }
diff --git a/services/mgmt/node/impl/app_state.go b/services/mgmt/node/impl/app_state.go
index 9fbc1c2..63071ca 100644
--- a/services/mgmt/node/impl/app_state.go
+++ b/services/mgmt/node/impl/app_state.go
@@ -6,6 +6,7 @@
 	"os"
 	"path/filepath"
 
+	"veyron.io/veyron/veyron2/verror2"
 	"veyron.io/veyron/veyron2/vlog"
 )
 
@@ -98,10 +99,10 @@
 	targetState := filepath.Join(dir, target.String())
 	if err := os.Rename(initialState, targetState); err != nil {
 		if os.IsNotExist(err) {
-			return errInvalidOperation
+			return verror2.Make(ErrInvalidOperation, nil)
 		}
 		vlog.Errorf("Rename(%v, %v) failed: %v", initialState, targetState, err) // Something went really wrong.
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	return nil
 }
@@ -110,7 +111,7 @@
 	initialStatus := filepath.Join(dir, initial.String())
 	if err := ioutil.WriteFile(initialStatus, []byte("status"), 0600); err != nil {
 		vlog.Errorf("WriteFile(%v) failed: %v", initialStatus, err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	return nil
 }
diff --git a/services/mgmt/node/impl/association_instance.go b/services/mgmt/node/impl/association_instance.go
index 02ae3a7..32dd993 100644
--- a/services/mgmt/node/impl/association_instance.go
+++ b/services/mgmt/node/impl/association_instance.go
@@ -7,6 +7,7 @@
 	"io/ioutil"
 	"path/filepath"
 
+	"veyron.io/veyron/veyron2/verror2"
 	"veyron.io/veyron/veyron2/vlog"
 )
 
@@ -14,7 +15,7 @@
 	snp := filepath.Join(dir, "systemname")
 	if err := ioutil.WriteFile(snp, []byte(systemName), 0600); err != nil {
 		vlog.Errorf("WriteFile(%v, %v) failed: %v", snp, systemName, err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	return nil
 }
@@ -24,7 +25,7 @@
 	name, err := ioutil.ReadFile(snp)
 	if err != nil {
 		vlog.Errorf("ReadFile(%v) failed: %v", snp, err)
-		return "", errOperationFailed
+		return "", verror2.Make(ErrOperationFailed, nil)
 	}
 	return string(name), nil
 }
diff --git a/services/mgmt/node/impl/association_state.go b/services/mgmt/node/impl/association_state.go
index 8fe738f..1e9a285 100644
--- a/services/mgmt/node/impl/association_state.go
+++ b/services/mgmt/node/impl/association_state.go
@@ -1,13 +1,13 @@
 package impl
 
 import (
+	"encoding/json"
 	"os"
 	"path/filepath"
-	"veyron.io/veyron/veyron2/services/mgmt/node"
-	"veyron.io/veyron/veyron2/verror"
-
-	"encoding/json"
 	"sync"
+
+	"veyron.io/veyron/veyron2/services/mgmt/node"
+	"veyron.io/veyron/veyron2/verror2"
 )
 
 // BlessingSystemAssociationStore manages a persisted association between
@@ -65,7 +65,7 @@
 func (u *association) serialize() (err error) {
 	f, err := os.OpenFile(u.filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
 	if err != nil {
-		return verror.NoExistf("Could not open association file for writing %s: %v", u.filename, err)
+		return verror2.Make(verror2.NoExist, nil, "Could not open association file for writing", u.filename, err)
 	}
 	defer func() {
 		if closerr := f.Close(); closerr != nil {
@@ -100,13 +100,13 @@
 func NewBlessingSystemAssociationStore(root string) (BlessingSystemAssociationStore, error) {
 	nddir := filepath.Join(root, "node-manager", "node-data")
 	if err := os.MkdirAll(nddir, os.FileMode(0700)); err != nil {
-		return nil, verror.NoExistf("Could not create node-data directory %s: %v\n", nddir, err)
+		return nil, verror2.Make(verror2.NoExist, nil, "Could not create node-data directory", nddir, err)
 	}
 	msf := filepath.Join(nddir, "associated.accounts")
 
 	f, err := os.Open(msf)
 	if err != nil && os.IsExist(err) {
-		return nil, verror.NoExistf("Could not open association file %s: %v\n", msf, err)
+		return nil, verror2.Make(verror2.NoExist, nil, "Could not open association file", msf, err)
 
 	}
 	defer f.Close()
@@ -117,7 +117,7 @@
 		dec := json.NewDecoder(f)
 		err := dec.Decode(&a.data)
 		if err != nil {
-			return nil, verror.NoExistf("Could not read association file %s: %v\n", msf, err)
+			return nil, verror2.Make(verror2.NoExist, nil, "Could not read association file", msf, err)
 		}
 	}
 	return BlessingSystemAssociationStore(a), nil
diff --git a/services/mgmt/node/impl/association_state_test.go b/services/mgmt/node/impl/association_state_test.go
index 4d313dc..39b8f28 100644
--- a/services/mgmt/node/impl/association_state_test.go
+++ b/services/mgmt/node/impl/association_state_test.go
@@ -128,13 +128,17 @@
 	}
 
 	// Create a NewBlessingSystemAssociationStore directory as a side-effect.
-	nbsa1, err = impl.NewBlessingSystemAssociationStore(os.TempDir())
-	defer os.RemoveAll(path.Join(os.TempDir(), "node-manager"))
+	dir, err = ioutil.TempDir("", "bad-starting-conditions")
+	if err != nil {
+		t.Fatalf("TempDir failed: %v", err)
+	}
+	nbsa1, err = impl.NewBlessingSystemAssociationStore(dir)
+	defer os.RemoveAll(dir)
 	if err != nil {
 		t.Fatalf("NewBlessingSystemAssociationStore failed: %v", err)
 	}
 
-	tpath := path.Join(os.TempDir(), "node-manager", "node-data", "associated.accounts")
+	tpath := path.Join(dir, "node-manager", "node-data", "associated.accounts")
 	f, err := os.Create(tpath)
 	if err != nil {
 		t.Fatalf("could not open backing file for setup: %v", err)
diff --git a/services/mgmt/node/impl/callback.go b/services/mgmt/node/impl/callback.go
index 02238c6..94241d9 100644
--- a/services/mgmt/node/impl/callback.go
+++ b/services/mgmt/node/impl/callback.go
@@ -1,8 +1,6 @@
 package impl
 
 import (
-	"time"
-
 	"veyron.io/veyron/veyron2/mgmt"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/vlog"
@@ -24,7 +22,7 @@
 			return
 		}
 		nmClient := node.ConfigClient(callbackName)
-		ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+		ctx, cancel := rt.R().NewContext().WithTimeout(ipcContextTimeout)
 		defer cancel()
 		if err := nmClient.Set(ctx, mgmt.ChildNameConfigKey, name); err != nil {
 			vlog.Fatalf("Set(%v, %v) failed: %v", mgmt.ChildNameConfigKey, name, err)
diff --git a/services/mgmt/node/impl/config_service.go b/services/mgmt/node/impl/config_service.go
index 609e1c6..b7c504d 100644
--- a/services/mgmt/node/impl/config_service.go
+++ b/services/mgmt/node/impl/config_service.go
@@ -12,6 +12,7 @@
 
 	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/naming"
+	"veyron.io/veyron/veyron2/verror2"
 	"veyron.io/veyron/veyron2/vlog"
 )
 
@@ -64,7 +65,7 @@
 		return value, nil
 	case <-time.After(timeout):
 		vlog.Errorf("Waiting for callback timed out")
-		return "", errOperationFailed
+		return "", verror2.Make(ErrOperationFailed, nil)
 	}
 }
 
@@ -127,7 +128,7 @@
 	i.callback.Lock()
 	if _, ok := i.callback.channels[id]; !ok {
 		i.callback.Unlock()
-		return errInvalidSuffix
+		return verror2.Make(ErrInvalidSuffix, nil)
 	}
 	channel, ok := i.callback.channels[id][key]
 	i.callback.Unlock()
diff --git a/services/mgmt/node/impl/dispatcher.go b/services/mgmt/node/impl/dispatcher.go
index dd4b647..45b2bd2 100644
--- a/services/mgmt/node/impl/dispatcher.go
+++ b/services/mgmt/node/impl/dispatcher.go
@@ -12,7 +12,6 @@
 	"strings"
 	"sync"
 
-	vsecurity "veyron.io/veyron/veyron/security"
 	"veyron.io/veyron/veyron/security/agent"
 	"veyron.io/veyron/veyron/security/agent/keymgr"
 	vflag "veyron.io/veyron/veyron/security/flag"
@@ -30,6 +29,7 @@
 	"veyron.io/veyron/veyron2/services/mgmt/stats"
 	"veyron.io/veyron/veyron2/services/security/access"
 	"veyron.io/veyron/veyron2/verror"
+	"veyron.io/veyron/veyron2/verror2"
 	"veyron.io/veyron/veyron2/vlog"
 )
 
@@ -48,7 +48,7 @@
 type dispatcher struct {
 	// acl/auth hold the acl and authorizer used to authorize access to the
 	// node manager methods.
-	acl  security.ACL
+	acl  access.TaggedACLMap
 	auth security.Authorizer
 	// etag holds the version string for the ACL. We use this for optimistic
 	// concurrency control when clients update the ACLs for the node manager.
@@ -72,18 +72,19 @@
 	appsSuffix   = "apps"
 	nodeSuffix   = "nm"
 	configSuffix = "cfg"
+
+	pkgPath = "veyron.io/veyron/veyron/services/mgmt/node/impl"
 )
 
 var (
-	errInvalidSuffix      = verror.BadArgf("invalid suffix")
-	errOperationFailed    = verror.Internalf("operation failed")
-	errInProgress         = verror.Existsf("operation in progress")
-	errIncompatibleUpdate = verror.BadArgf("update failed: mismatching app title")
-	// TODO(bprosnitz) Remove the TODO blocks in util_test when these are upgraded to verror2
-	errUpdateNoOp       = verror.NoExistf("no different version available")
-	errNotExist         = verror.NoExistf("object does not exist")
-	errInvalidOperation = verror.BadArgf("invalid operation")
-	errInvalidBlessing  = verror.BadArgf("invalid claim blessing")
+	ErrInvalidSuffix       = verror2.Register(pkgPath+".InvalidSuffix", verror2.NoRetry, "")
+	ErrOperationFailed     = verror2.Register(pkgPath+".OperationFailed", verror2.NoRetry, "")
+	ErrOperationInProgress = verror2.Register(pkgPath+".OperationInProgress", verror2.NoRetry, "")
+	ErrAppTitleMismatch    = verror2.Register(pkgPath+".AppTitleMismatch", verror2.NoRetry, "")
+	ErrUpdateNoOp          = verror2.Register(pkgPath+".UpdateNoOp", verror2.NoRetry, "")
+	ErrObjectNoExist       = verror2.Register(pkgPath+".ObjectNoExist", verror2.NoRetry, "")
+	ErrInvalidOperation    = verror2.Register(pkgPath+".InvalidOperation", verror2.NoRetry, "")
+	ErrInvalidBlessing     = verror2.Register(pkgPath+".InvalidBlessing", verror2.NoRetry, "")
 )
 
 // NewDispatcher is the node manager dispatcher factory.
@@ -124,7 +125,7 @@
 		if err != nil {
 			return nil, fmt.Errorf("failed to read nodemanager ACL file:%v", err)
 		}
-		acl, err := vsecurity.LoadACL(reader)
+		acl, err := access.ReadTaggedACLMap(reader)
 		if err != nil {
 			return nil, fmt.Errorf("failed to load nodemanager ACL:%v", err)
 		}
@@ -135,7 +136,7 @@
 		if d.auth = vflag.NewAuthorizerOrDie(); d.auth == nil {
 			// If there are no specified ACLs we grant nodemanager access to all
 			// principals until it is claimed.
-			d.auth = vsecurity.NewACLAuthorizer(vsecurity.OpenACL())
+			d.auth = allowEveryone{}
 		}
 	}
 	// If we're in 'security agent mode', set up the key manager agent.
@@ -162,29 +163,31 @@
 	// TODO(rjkroege): Scrub the state tree of installation and instance ACL files.
 	if len(names) == 0 {
 		vlog.Errorf("No names for claimer(%v) are trusted", proof)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	rt.R().Principal().BlessingStore().Set(proof, security.AllPrincipals)
 	rt.R().Principal().BlessingStore().SetDefault(proof)
 	// Create ACLs to transfer nodemanager permissions to the provided identity.
-	acl := security.ACL{In: make(map[security.BlessingPattern]security.LabelSet)}
-	for _, name := range names {
-		acl.In[security.BlessingPattern(name)] = security.AllLabels
+	acl := make(access.TaggedACLMap)
+	for _, n := range names {
+		for _, tag := range access.AllTypicalTags() {
+			acl.Add(security.BlessingPattern(n), string(tag))
+		}
 	}
 	_, etag, err := d.getACL()
 	if err != nil {
 		vlog.Errorf("Failed to getACL:%v", err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	if err := d.setACL(acl, etag, true /* store ACL on disk */); err != nil {
 		vlog.Errorf("Failed to setACL:%v", err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	return nil
 }
 
 // TODO(rjkroege): Further refactor ACL-setting code.
-func setAppACL(locks aclLocks, dir string, acl security.ACL, etag string) error {
+func setAppACL(locks aclLocks, dir string, acl access.TaggedACLMap, etag string) error {
 	aclpath := path.Join(dir, "acls", "data")
 	sigpath := path.Join(dir, "acls", "signature")
 
@@ -204,9 +207,9 @@
 	}
 	defer f.Close()
 
-	curACL, err := vsecurity.LoadACL(f)
+	curACL, err := access.ReadTaggedACLMap(f)
 	if err != nil {
-		vlog.Errorf("LoadACL(%s) failed: %v", aclpath, err)
+		vlog.Errorf("ReadTaggedACLMap(%s) failed: %v", aclpath, err)
 		return err
 	}
 	curEtag, err := computeEtag(curACL)
@@ -222,7 +225,7 @@
 	return writeACLs(aclpath, sigpath, dir, acl)
 }
 
-func getAppACL(locks aclLocks, dir string) (security.ACL, string, error) {
+func getAppACL(locks aclLocks, dir string) (access.TaggedACLMap, string, error) {
 	aclpath := path.Join(dir, "acls", "data")
 
 	// Acquire lock. Locks are per path to an acls file.
@@ -236,30 +239,26 @@
 
 	f, err := os.Open(aclpath)
 	if err != nil {
-		vlog.Errorf("LoadACL(%s) failed: %v", aclpath, err)
-		return security.ACL{}, "", err
+		vlog.Errorf("Open(%s) failed: %v", aclpath, err)
+		return nil, "", err
 	}
 	defer f.Close()
 
-	acl, err := vsecurity.LoadACL(f)
+	acl, err := access.ReadTaggedACLMap(f)
 	if err != nil {
-		vlog.Errorf("LoadACL(%s) failed: %v", aclpath, err)
-		return security.ACL{}, "", err
+		vlog.Errorf("ReadTaggedACLMap(%s) failed: %v", aclpath, err)
+		return nil, "", err
 	}
 	curEtag, err := computeEtag(acl)
 	if err != nil {
-		return security.ACL{}, "", err
-	}
-
-	if err != nil {
-		return security.ACL{}, "", err
+		return nil, "", err
 	}
 	return acl, curEtag, nil
 }
 
-func computeEtag(acl security.ACL) (string, error) {
+func computeEtag(acl access.TaggedACLMap) (string, error) {
 	b := new(bytes.Buffer)
-	if err := vsecurity.SaveACL(b, acl); err != nil {
+	if err := acl.WriteTo(b); err != nil {
 		vlog.Errorf("Failed to save ACL:%v", err)
 		return "", err
 	}
@@ -269,7 +268,7 @@
 	return etag, nil
 }
 
-func writeACLs(aclFile, sigFile, dir string, acl security.ACL) error {
+func writeACLs(aclFile, sigFile, dir string, acl access.TaggedACLMap) error {
 	// Create dir directory if it does not exist
 	os.MkdirAll(dir, os.FileMode(0700))
 	// Save the object to temporary data and signature files, and then move
@@ -277,27 +276,27 @@
 	data, err := ioutil.TempFile(dir, "data")
 	if err != nil {
 		vlog.Errorf("Failed to open tmpfile data:%v", err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	defer os.Remove(data.Name())
 	sig, err := ioutil.TempFile(dir, "sig")
 	if err != nil {
 		vlog.Errorf("Failed to open tmpfile sig:%v", err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	defer os.Remove(sig.Name())
 	writer, err := serialization.NewSigningWriteCloser(data, sig, rt.R().Principal(), nil)
 	if err != nil {
 		vlog.Errorf("Failed to create NewSigningWriteCloser:%v", err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
-	if err = vsecurity.SaveACL(writer, acl); err != nil {
+	if err = acl.WriteTo(writer); err != nil {
 		vlog.Errorf("Failed to SaveACL:%v", err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	if err = writer.Close(); err != nil {
 		vlog.Errorf("Failed to Close() SigningWriteCloser:%v", err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	if err := os.Rename(data.Name(), aclFile); err != nil {
 		return err
@@ -308,7 +307,7 @@
 	return nil
 }
 
-func (d *dispatcher) setACL(acl security.ACL, etag string, writeToFile bool) error {
+func (d *dispatcher) setACL(acl access.TaggedACLMap, etag string, writeToFile bool) error {
 	d.mu.Lock()
 	defer d.mu.Unlock()
 	aclFile, sigFile, nodedata := d.getACLFilePaths()
@@ -326,11 +325,15 @@
 	if err != nil {
 		return err
 	}
-	d.acl, d.etag, d.auth = acl, etag, vsecurity.NewACLAuthorizer(acl)
+	auth, err := access.TaggedACLAuthorizer(acl, access.TypicalTagType())
+	if err != nil {
+		return err
+	}
+	d.acl, d.etag, d.auth = acl, etag, auth
 	return nil
 }
 
-func (d *dispatcher) getACL() (acl security.ACL, etag string, err error) {
+func (d *dispatcher) getACL() (acl access.TaggedACLMap, etag string, err error) {
 	d.mu.RLock()
 	defer d.mu.RUnlock()
 	return d.acl, d.etag, nil
@@ -346,7 +349,7 @@
 		}
 	}
 	if len(components) == 0 {
-		return ipc.VChildrenGlobberInvoker(nodeSuffix, appsSuffix), d.auth, nil
+		return ipc.ChildrenGlobberInvoker(nodeSuffix, appsSuffix), d.auth, nil
 	}
 	// The implementation of the node manager is split up into several
 	// invokers, which are instantiated depending on the receiver name
@@ -382,20 +385,17 @@
 					return nil, nil, err
 				}
 				if !instanceStateIs(appInstanceDir, started) {
-					return nil, nil, errInvalidSuffix
+					return nil, nil, verror2.Make(ErrInvalidSuffix, nil)
 				}
-				var label security.Label
 				var sigStub signatureStub
 				if kind == "pprof" {
-					label = security.DebugLabel
 					sigStub = pprof.PProfServer(nil)
 				} else {
-					label = security.DebugLabel | security.MonitoringLabel
 					sigStub = stats.StatsServer(nil)
 				}
 				suffix := naming.Join("__debug", naming.Join(components[4:]...))
 				remote := naming.JoinAddressName(info.AppCycleMgrName, suffix)
-				return &proxyInvoker{remote, label, sigStub}, d.auth, nil
+				return &proxyInvoker{remote, access.Debug, sigStub}, d.auth, nil
 			}
 		}
 		nodeACLs, _, err := d.getACL()
@@ -418,7 +418,7 @@
 		return receiver, appSpecificAuthorizer, nil
 	case configSuffix:
 		if len(components) != 2 {
-			return nil, nil, errInvalidSuffix
+			return nil, nil, verror2.Make(ErrInvalidSuffix, nil)
 		}
 		receiver := inode.ConfigServer(&configService{
 			callback: d.internal.callback,
@@ -433,7 +433,7 @@
 		// (and not other apps).
 		return receiver, nil, nil
 	default:
-		return nil, nil, errInvalidSuffix
+		return nil, nil, verror2.Make(ErrInvalidSuffix, nil)
 	}
 }
 
@@ -445,23 +445,27 @@
 		return sec, nil
 	}
 	// Otherwise, we require a per-installation and per-instance ACL file.
-
 	if len(suffix) == 2 {
 		p, err := installationDirCore(suffix, config.Root)
 		if err != nil {
 			vlog.Errorf("newAppSpecificAuthorizer failed: %v", err)
 			return nil, err
 		}
-		p = path.Join(p, "acls", "data")
-		return vsecurity.NewFileACLAuthorizer(p), nil
-	} else if len(suffix) > 2 {
+		return access.TaggedACLAuthorizerFromFile(path.Join(p, "acls", "data"), access.TypicalTagType())
+	}
+	if len(suffix) > 2 {
 		p, err := instanceDir(config.Root, suffix[0:3])
 		if err != nil {
 			vlog.Errorf("newAppSpecificAuthorizer failed: %v", err)
 			return nil, err
 		}
-		p = path.Join(p, "acls", "data")
-		return vsecurity.NewFileACLAuthorizer(p), nil
+		return access.TaggedACLAuthorizerFromFile(path.Join(p, "acls", "data"), access.TypicalTagType())
 	}
-	return nil, errInvalidSuffix
+	return nil, verror2.Make(ErrInvalidSuffix, nil)
 }
+
+// allowEveryone implements the authorization policy that allows all principals
+// access.
+type allowEveryone struct{}
+
+func (allowEveryone) Authorize(security.Context) error { return nil }
diff --git a/services/mgmt/node/impl/impl_test.go b/services/mgmt/node/impl/impl_test.go
index 0baca5b..103b2d4 100644
--- a/services/mgmt/node/impl/impl_test.go
+++ b/services/mgmt/node/impl/impl_test.go
@@ -10,7 +10,6 @@
 	"encoding/base64"
 	"encoding/hex"
 	"encoding/json"
-	"flag"
 	"fmt"
 	"io"
 	"io/ioutil"
@@ -38,16 +37,16 @@
 	"veyron.io/veyron/veyron2/services/mgmt/node"
 	"veyron.io/veyron/veyron2/services/mgmt/pprof"
 	"veyron.io/veyron/veyron2/services/mgmt/stats"
+	"veyron.io/veyron/veyron2/services/security/access"
+	"veyron.io/veyron/veyron2/vdl/vdlutil"
 	"veyron.io/veyron/veyron2/verror"
 	"veyron.io/veyron/veyron2/vlog"
-	"veyron.io/veyron/veyron2/vom"
 
 	"veyron.io/veyron/veyron/lib/expect"
 	"veyron.io/veyron/veyron/lib/modules"
 	"veyron.io/veyron/veyron/lib/signals"
 	"veyron.io/veyron/veyron/lib/testutil"
 	tsecurity "veyron.io/veyron/veyron/lib/testutil/security"
-	vsecurity "veyron.io/veyron/veyron/security"
 	"veyron.io/veyron/veyron/services/mgmt/node/config"
 	"veyron.io/veyron/veyron/services/mgmt/node/impl"
 	suidhelper "veyron.io/veyron/veyron/services/mgmt/suidhelper/impl"
@@ -62,7 +61,7 @@
 
 func init() {
 	// TODO(rthellend): Remove when vom2 is ready.
-	vom.Register(&naming.VDLMountedServer{})
+	vdlutil.Register(&naming.VDLMountedServer{})
 
 	modules.RegisterChild(execScriptCmd, "", execScript)
 	modules.RegisterChild(nodeManagerCmd, "", nodeManager)
@@ -74,17 +73,6 @@
 		return
 	}
 	initRT()
-
-	// NOTE(caprita): The default 1m timeout that the modules package gives
-	// to subprocesses is insufficient, especially with --race.
-	// If not explicitly set to a non-default value by the user, we set the
-	// test-wide timeout to 2 minutes (which will get propagated by the
-	// modules framework to the subprocesses).
-	timeoutFlag := flag.Lookup("test.timeout")
-	if timeoutFlag.Value.String() == timeoutFlag.DefValue {
-		timeoutFlag.Value.Set("2m")
-		vlog.Infof("Setting test.timeout to 2m.")
-	}
 }
 
 func initRT() {
@@ -185,7 +173,7 @@
 
 	fmt.Fprintf(stdout, "ready:%d\n", os.Getpid())
 
-	<-signals.ShutdownOnSignals()
+	<-signals.ShutdownOnSignals(rt.R())
 
 	if val, present := env["PAUSE_BEFORE_STOP"]; present && val == "1" {
 		modules.WaitForEOF(stdin)
@@ -247,9 +235,12 @@
 	if err := server.Serve(publishName, new(appService), nil); err != nil {
 		vlog.Fatalf("Serve(%v) failed: %v", publishName, err)
 	}
+	// Some of our tests look for log files, so make sure they are flushed
+	// to ensure that at least the files exist.
+	vlog.FlushLog()
 	ping()
 
-	<-signals.ShutdownOnSignals()
+	<-signals.ShutdownOnSignals(rt.R())
 	if err := ioutil.WriteFile("testfile", []byte("goodbye world"), 0600); err != nil {
 		vlog.Fatalf("Failed to write testfile: %v", err)
 	}
@@ -350,8 +341,8 @@
 	// Simulate an invalid envelope in the application repository.
 	*envelope = envelopeFromShell(sh, nmPauseBeforeStopEnv, nodeManagerCmd, "bogus", nmArgs...)
 
-	updateNodeExpectError(t, "factoryNM", verror.BadArg)  // Incorrect title.
-	revertNodeExpectError(t, "factoryNM", verror.NoExist) // No previous version available.
+	updateNodeExpectError(t, "factoryNM", impl.ErrAppTitleMismatch.ID)
+	revertNodeExpectError(t, "factoryNM", impl.ErrUpdateNoOp.ID)
 
 	// Set up a second version of the node manager. The information in the
 	// envelope will be used by the node manager to stage the next version.
@@ -373,7 +364,7 @@
 		t.Fatalf("current link didn't change")
 	}
 
-	updateNodeExpectError(t, "factoryNM", verror.Exists) // Update already in progress.
+	updateNodeExpectError(t, "factoryNM", impl.ErrOperationInProgress.ID)
 
 	nmh.CloseStdin()
 
@@ -391,7 +382,7 @@
 
 	// Try issuing an update without changing the envelope in the application
 	// repository: this should fail, and current link should be unchanged.
-	updateNodeExpectError(t, "v2NM", naming.ErrNoSuchName.ID)
+	updateNodeExpectError(t, "v2NM", impl.ErrUpdateNoOp.ID)
 	if evalLink() != scriptPathV2 {
 		t.Fatalf("script changed")
 	}
@@ -424,7 +415,7 @@
 
 	// Revert the node manager to its previous version (v2).
 	revertNode(t, "v3NM")
-	revertNodeExpectError(t, "v3NM", verror.Exists) // Revert already in progress.
+	revertNodeExpectError(t, "v3NM", impl.ErrOperationInProgress.ID) // Revert already in progress.
 	nmh.CloseStdin()
 	nms.Expect("v3NM terminating")
 	if evalLink() != scriptPathV2 {
@@ -457,6 +448,9 @@
 
 type pingServer chan<- string
 
+// TODO(caprita): Set the timeout in a more principled manner.
+const pingTimeout = 20 * time.Second
+
 func (p pingServer) Ping(_ ipc.ServerContext, arg string) {
 	p <- arg
 }
@@ -508,7 +502,7 @@
 	var env string
 	select {
 	case env = <-pingCh:
-	case <-time.After(time.Minute):
+	case <-time.After(pingTimeout):
 		t.Fatalf("%s: failed to get ping", loc(1))
 	}
 	d := json.NewDecoder(strings.NewReader(env))
@@ -560,8 +554,8 @@
 	appID := installApp(t)
 
 	// Start requires the caller to grant a blessing for the app instance.
-	if _, err := startAppImpl(t, appID, ""); err == nil || !verror.Is(err, verror.BadArg) {
-		t.Fatalf("Start(%v) expected to fail with %v, got %v instead", appID, verror.BadArg, err)
+	if _, err := startAppImpl(t, appID, ""); err == nil || !verror.Is(err, impl.ErrInvalidBlessing.ID) {
+		t.Fatalf("Start(%v) expected to fail with %v, got %v instead", appID, impl.ErrInvalidBlessing.ID, err)
 	}
 
 	// Start an instance of the app.
@@ -612,12 +606,12 @@
 	}
 
 	// Updating the installation to itself is a no-op.
-	updateAppExpectError(t, appID, naming.ErrNoSuchName.ID)
+	updateAppExpectError(t, appID, impl.ErrUpdateNoOp.ID)
 
 	// Updating the installation should not work with a mismatched title.
 	*envelope = envelopeFromShell(sh, nil, appCmd, "bogus")
 
-	updateAppExpectError(t, appID, verror.BadArg)
+	updateAppExpectError(t, appID, impl.ErrAppTitleMismatch.ID)
 
 	// Create a second version of the app and update the app to it.
 	*envelope = envelopeFromShell(sh, nil, appCmd, "google naps", "appV2")
@@ -679,19 +673,19 @@
 	resolveExpectNotFound(t, "appV1")
 
 	// We are already on the first version, no further revert possible.
-	revertAppExpectError(t, appID, naming.ErrNoSuchName.ID)
+	revertAppExpectError(t, appID, impl.ErrUpdateNoOp.ID)
 
 	// Uninstall the app.
 	uninstallApp(t, appID)
 
 	// Updating the installation should no longer be allowed.
-	updateAppExpectError(t, appID, verror.BadArg)
+	updateAppExpectError(t, appID, impl.ErrInvalidOperation.ID)
 
 	// Reverting the installation should no longer be allowed.
-	revertAppExpectError(t, appID, verror.BadArg)
+	revertAppExpectError(t, appID, impl.ErrInvalidOperation.ID)
 
 	// Starting new instances should no longer be allowed.
-	startAppExpectError(t, appID, verror.BadArg)
+	startAppExpectError(t, appID, impl.ErrInvalidOperation.ID)
 
 	// Cleanly shut down the node manager.
 	syscall.Kill(nmh.Pid(), syscall.SIGINT)
@@ -776,7 +770,7 @@
 	// Wait until the app pings us that it's ready.
 	select {
 	case <-pingCh:
-	case <-time.After(5 * time.Second):
+	case <-time.After(pingTimeout):
 		t.Fatalf("failed to get ping")
 	}
 	resolve(t, "trapp", 1)
@@ -839,10 +833,13 @@
 	if err := nodeStub.Claim(selfRT.NewContext(), &granter{p: selfRT.Principal(), extension: "mydevice"}); err != nil {
 		t.Fatal(err)
 	}
-	expectedACL := security.ACL{In: map[security.BlessingPattern]security.LabelSet{"root/self/mydevice": security.AllLabels}}
+	expectedACL := make(access.TaggedACLMap)
+	for _, tag := range access.AllTypicalTags() {
+		expectedACL[string(tag)] = access.ACL{In: []security.BlessingPattern{"root/self/mydevice"}}
+	}
 	var b bytes.Buffer
-	if err := vsecurity.SaveACL(&b, expectedACL); err != nil {
-		t.Fatalf("Failed to saveACL:%v", err)
+	if err := expectedACL.WriteTo(&b); err != nil {
+		t.Fatalf("Failed to save ACL:%v", err)
 	}
 	md5hash := md5.Sum(b.Bytes())
 	expectedETAG := hex.EncodeToString(md5hash[:])
@@ -856,7 +853,10 @@
 	if err := tryInstall(otherRT); err == nil {
 		t.Fatalf("Install should have failed with random identity")
 	}
-	newACL := security.ACL{In: map[security.BlessingPattern]security.LabelSet{"root/other": security.AllLabels}}
+	newACL := make(access.TaggedACLMap)
+	for _, tag := range access.AllTypicalTags() {
+		newACL.Add("root/other", string(tag))
+	}
 	if err := nodeStub.SetACL(selfRT.NewContext(), newACL, "invalid"); err == nil {
 		t.Fatalf("SetACL should have failed with invalid etag")
 	}
@@ -921,7 +921,7 @@
 	// sent to their children and so on.
 	pid := readPID(t, nms)
 	resolve(t, "nm", 1)
-	revertNodeExpectError(t, "nm", naming.ErrNoSuchName.ID) // No previous version available.
+	revertNodeExpectError(t, "nm", impl.ErrUpdateNoOp.ID) // No previous version available.
 	syscall.Kill(pid, syscall.SIGINT)
 
 	nms.Expect("nm terminating")
@@ -969,7 +969,7 @@
 	// Wait until the app pings us that it's ready.
 	select {
 	case <-pingCh:
-	case <-time.After(5 * time.Second):
+	case <-time.After(pingTimeout):
 		t.Fatalf("failed to get ping")
 	}
 
@@ -1013,7 +1013,7 @@
 	logFileRemoveErrorFatalWarningRE := regexp.MustCompile("(ERROR|FATAL|WARNING)")
 	statsTrimRE := regexp.MustCompile("/stats/(ipc|system(/start-time.*)?)$")
 	for _, tc := range testcases {
-		results, err := testutil.GlobName(tc.name, tc.pattern)
+		results, err := testutil.GlobName(rt.R().NewContext(), tc.name, tc.pattern)
 		if err != nil {
 			t.Errorf("unexpected glob error for (%q, %q): %v", tc.name, tc.pattern, err)
 			continue
@@ -1041,7 +1041,7 @@
 	}
 
 	// Call Size() on the log file objects.
-	files, err := testutil.GlobName("nm", "apps/google naps/"+installID+"/"+instance1ID+"/logs/*")
+	files, err := testutil.GlobName(rt.R().NewContext(), "nm", "apps/google naps/"+installID+"/"+instance1ID+"/logs/*")
 	if err != nil {
 		t.Errorf("unexpected glob error: %v", err)
 	}
@@ -1057,7 +1057,7 @@
 	}
 
 	// Call Value() on some of the stats objects.
-	objects, err := testutil.GlobName("nm", "apps/google naps/"+installID+"/"+instance1ID+"/stats/system/start-time*")
+	objects, err := testutil.GlobName(rt.R().NewContext(), "nm", "apps/google naps/"+installID+"/"+instance1ID+"/stats/system/start-time*")
 	if err != nil {
 		t.Errorf("unexpected glob error: %v", err)
 	}
@@ -1288,7 +1288,7 @@
 	if err != nil {
 		t.Fatalf("GetACL failed %v", err)
 	}
-	newACL.In["root/other/..."] = security.LabelSet(security.WriteLabel)
+	newACL.Add("root/other", string(access.Write))
 	if err := nodeStub.SetACL(selfRT.NewContext(), newACL, ""); err != nil {
 		t.Fatalf("SetACL failed %v", err)
 	}
@@ -1305,7 +1305,7 @@
 	if err != nil {
 		t.Fatalf("GetACL on appID: %v failed %v", appID, err)
 	}
-	newACL.In["root/other/..."] = security.LabelSet(security.ReadLabel)
+	newACL.Add("root/other", string(access.Read))
 	if err = appStub(appID).SetACL(selfRT.NewContext(), newACL, ""); err != nil {
 		t.Fatalf("SetACL on appID: %v failed: %v", appID, err)
 	}
diff --git a/services/mgmt/node/impl/mock_repo_test.go b/services/mgmt/node/impl/mock_repo_test.go
index 3901275..d55e2c9 100644
--- a/services/mgmt/node/impl/mock_repo_test.go
+++ b/services/mgmt/node/impl/mock_repo_test.go
@@ -3,7 +3,6 @@
 import (
 	"crypto/md5"
 	"encoding/hex"
-	"errors"
 	"io"
 	"io/ioutil"
 	"os"
@@ -13,6 +12,7 @@
 	"veyron.io/veyron/veyron2/services/mgmt/application"
 	"veyron.io/veyron/veyron2/services/mgmt/binary"
 	"veyron.io/veyron/veyron2/services/mgmt/repository"
+	"veyron.io/veyron/veyron2/verror2"
 	"veyron.io/veyron/veyron2/vlog"
 )
 
@@ -80,7 +80,12 @@
 
 // BINARY REPOSITORY INTERFACE IMPLEMENTATION
 
-func (*brInvoker) Create(ipc.ServerContext, int32) error {
+// TODO(toddw): Move the errors from dispatcher.go into a common location.
+const pkgPath = "veyron.io/veyron/veyron/services/mgmt/node/impl"
+
+var ErrOperationFailed = verror2.Register(pkgPath+".OperationFailed", verror2.NoRetry, "")
+
+func (*brInvoker) Create(ipc.ServerContext, int32, repository.MediaInfo) error {
 	vlog.VI(1).Infof("Create()")
 	return nil
 }
@@ -90,14 +95,12 @@
 	return nil
 }
 
-var errOperationFailed = errors.New("operation failed")
-
 func (i *brInvoker) Download(ctx repository.BinaryDownloadContext, _ int32) error {
 	vlog.VI(1).Infof("Download()")
 	file, err := os.Open(os.Args[0])
 	if err != nil {
 		vlog.Errorf("Open() failed: %v", err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, ctx)
 	}
 	defer file.Close()
 	bufferLength := 4096
@@ -111,11 +114,11 @@
 		case nil:
 			if err := sender.Send(buffer[:n]); err != nil {
 				vlog.Errorf("Send() failed: %v", err)
-				return errOperationFailed
+				return verror2.Make(ErrOperationFailed, ctx)
 			}
 		default:
 			vlog.Errorf("Read() failed: %v", err)
-			return errOperationFailed
+			return verror2.Make(ErrOperationFailed, ctx)
 		}
 	}
 }
@@ -125,16 +128,16 @@
 	return "", 0, nil
 }
 
-func (*brInvoker) Stat(ipc.ServerContext) ([]binary.PartInfo, error) {
+func (*brInvoker) Stat(ctx ipc.ServerContext) ([]binary.PartInfo, repository.MediaInfo, error) {
 	vlog.VI(1).Infof("Stat()")
 	h := md5.New()
 	bytes, err := ioutil.ReadFile(os.Args[0])
 	if err != nil {
-		return []binary.PartInfo{}, errOperationFailed
+		return []binary.PartInfo{}, repository.MediaInfo{}, verror2.Make(ErrOperationFailed, ctx)
 	}
 	h.Write(bytes)
 	part := binary.PartInfo{Checksum: hex.EncodeToString(h.Sum(nil)), Size: int64(len(bytes))}
-	return []binary.PartInfo{part}, nil
+	return []binary.PartInfo{part}, repository.MediaInfo{Type: "application/octet-stream"}, nil
 }
 
 func (i *brInvoker) Upload(repository.BinaryUploadContext, int32) error {
diff --git a/services/mgmt/node/impl/node_service.go b/services/mgmt/node/impl/node_service.go
index 773d4d9..e99b5b3 100644
--- a/services/mgmt/node/impl/node_service.go
+++ b/services/mgmt/node/impl/node_service.go
@@ -43,10 +43,11 @@
 	"veyron.io/veyron/veyron2/mgmt"
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/rt"
-	"veyron.io/veyron/veyron2/security"
 	"veyron.io/veyron/veyron2/services/mgmt/application"
 	"veyron.io/veyron/veyron2/services/mgmt/binary"
 	"veyron.io/veyron/veyron2/services/mgmt/node"
+	"veyron.io/veyron/veyron2/services/security/access"
+	"veyron.io/veyron/veyron2/verror2"
 	"veyron.io/veyron/veyron2/vlog"
 
 	vexec "veyron.io/veyron/veyron/lib/exec"
@@ -97,7 +98,7 @@
 	// Get the blessing to be used by the claimant.
 	blessings := call.Blessings()
 	if blessings == nil {
-		return errInvalidBlessing
+		return verror2.Make(ErrInvalidBlessing, call)
 	}
 	return i.disp.claimNodeManager(blessings.ForContext(call), blessings)
 }
@@ -220,55 +221,50 @@
 	// Start the child process.
 	if err := handle.Start(); err != nil {
 		vlog.Errorf("Start() failed: %v", err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, ctx)
 	}
 	defer func() {
-		// Ensure that any stdout output gets flushed.
-		if err := handle.Wait(10 * time.Second); err != nil {
-			vlog.Errorf("Wait() failed: %v", err)
-			if err := handle.Clean(); err != nil {
-				vlog.Errorf("Clean() failed: %v", err)
-			}
+		if err := handle.Clean(); err != nil {
+			vlog.Errorf("Clean() failed: %v", err)
 		}
 	}()
 	// Wait for the child process to start.
-	testTimeout := 10 * time.Second
-	if err := handle.WaitForReady(testTimeout); err != nil {
-		vlog.Errorf("WaitForReady(%v) failed: %v", testTimeout, err)
-		return errOperationFailed
+	if err := handle.WaitForReady(childReadyTimeout); err != nil {
+		vlog.Errorf("WaitForReady(%v) failed: %v", childReadyTimeout, err)
+		return verror2.Make(ErrOperationFailed, ctx)
 	}
-	childName, err := listener.waitForValue(testTimeout)
+	childName, err := listener.waitForValue(childReadyTimeout)
 	if err != nil {
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, ctx)
 	}
 	// Check that invoking Update() succeeds.
 	childName = naming.Join(childName, "nm")
 	nmClient := node.NodeClient(childName)
 	linkOld, pathOld, err := i.getCurrentFileInfo()
 	if err != nil {
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, ctx)
 	}
 	// Since the resolution of mtime for files is seconds, the test sleeps
 	// for a second to make sure it can check whether the current symlink is
 	// updated.
 	time.Sleep(time.Second)
 	if err := nmClient.Revert(ctx); err != nil {
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, ctx)
 	}
 	linkNew, pathNew, err := i.getCurrentFileInfo()
 	if err != nil {
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, ctx)
 	}
 	// Check that the new node manager updated the current symbolic link.
 	if !linkOld.ModTime().Before(linkNew.ModTime()) {
 		vlog.Errorf("new node manager test failed")
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, ctx)
 	}
 	// Ensure that the current symbolic link points to the same script.
 	if pathNew != pathOld {
 		updateLink(pathOld, i.config.CurrentLink)
 		vlog.Errorf("new node manager test failed")
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, ctx)
 	}
 	return nil
 }
@@ -281,7 +277,7 @@
 	path, err := filepath.EvalSymlinks(os.Args[0])
 	if err != nil {
 		vlog.Errorf("EvalSymlinks(%v) failed: %v", os.Args[0], err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 
 	output := "#!/bin/bash\n"
@@ -297,31 +293,31 @@
 	path = filepath.Join(workspace, "noded.sh")
 	if err := ioutil.WriteFile(path, []byte(output), 0700); err != nil {
 		vlog.Errorf("WriteFile(%v) failed: %v", path, err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	return nil
 }
 
 func (i *nodeService) updateNodeManager(ctx context.T) error {
 	if len(i.config.Origin) == 0 {
-		return errUpdateNoOp
+		return verror2.Make(ErrUpdateNoOp, ctx)
 	}
 	envelope, err := fetchEnvelope(ctx, i.config.Origin)
 	if err != nil {
 		return err
 	}
 	if envelope.Title != application.NodeManagerTitle {
-		return errIncompatibleUpdate
+		return verror2.Make(ErrAppTitleMismatch, ctx)
 	}
 	if i.config.Envelope != nil && reflect.DeepEqual(envelope, i.config.Envelope) {
-		return errUpdateNoOp
+		return verror2.Make(ErrUpdateNoOp, ctx)
 	}
 	// Create new workspace.
 	workspace := filepath.Join(i.config.Root, "node-manager", generateVersionDirName())
 	perm := os.FileMode(0700)
 	if err := os.MkdirAll(workspace, perm); err != nil {
 		vlog.Errorf("MkdirAll(%v, %v) failed: %v", workspace, perm, err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, ctx)
 	}
 
 	deferrer := func() {
@@ -350,7 +346,7 @@
 	// Populate the new workspace with a node manager script.
 	configSettings, err := i.config.Save(envelope)
 	if err != nil {
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, ctx)
 	}
 
 	if err := generateScript(workspace, configSettings, envelope); err != nil {
@@ -370,8 +366,8 @@
 	return nil
 }
 
-func (*nodeService) Install(ipc.ServerContext, string) (string, error) {
-	return "", errInvalidSuffix
+func (*nodeService) Install(ctx ipc.ServerContext, _ string) (string, error) {
+	return "", verror2.Make(ErrInvalidSuffix, ctx)
 }
 
 func (*nodeService) Refresh(ipc.ServerContext) error {
@@ -384,17 +380,17 @@
 	return nil
 }
 
-func (*nodeService) Resume(ipc.ServerContext) error {
-	return errInvalidSuffix
+func (*nodeService) Resume(ctx ipc.ServerContext) error {
+	return verror2.Make(ErrInvalidSuffix, ctx)
 }
 
 func (i *nodeService) Revert(call ipc.ServerContext) error {
 	if i.config.Previous == "" {
-		return errUpdateNoOp
+		return verror2.Make(ErrUpdateNoOp, call)
 	}
 	updatingState := i.updating
 	if updatingState.testAndSetUpdating() {
-		return errInProgress
+		return verror2.Make(ErrOperationInProgress, call)
 	}
 	err := i.revertNodeManager()
 	if err != nil {
@@ -403,12 +399,12 @@
 	return err
 }
 
-func (*nodeService) Start(ipc.ServerContext) ([]string, error) {
-	return nil, errInvalidSuffix
+func (*nodeService) Start(ctx ipc.ServerContext) ([]string, error) {
+	return nil, verror2.Make(ErrInvalidSuffix, ctx)
 }
 
-func (*nodeService) Stop(ipc.ServerContext, uint32) error {
-	return errInvalidSuffix
+func (*nodeService) Stop(ctx ipc.ServerContext, _ uint32) error {
+	return verror2.Make(ErrInvalidSuffix, ctx)
 }
 
 func (*nodeService) Suspend(ipc.ServerContext) error {
@@ -416,17 +412,17 @@
 	return nil
 }
 
-func (*nodeService) Uninstall(ipc.ServerContext) error {
-	return errInvalidSuffix
+func (*nodeService) Uninstall(ctx ipc.ServerContext) error {
+	return verror2.Make(ErrInvalidSuffix, ctx)
 }
 
-func (i *nodeService) Update(ipc.ServerContext) error {
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+func (i *nodeService) Update(call ipc.ServerContext) error {
+	ctx, cancel := rt.R().NewContext().WithTimeout(ipcContextTimeout)
 	defer cancel()
 
 	updatingState := i.updating
 	if updatingState.testAndSetUpdating() {
-		return errInProgress
+		return verror2.Make(ErrOperationInProgress, call)
 	}
 
 	err := i.updateNodeManager(ctx)
@@ -441,21 +437,21 @@
 	return nil
 }
 
-func (i *nodeService) SetACL(_ ipc.ServerContext, acl security.ACL, etag string) error {
+func (i *nodeService) SetACL(_ ipc.ServerContext, acl access.TaggedACLMap, etag string) error {
 	return i.disp.setACL(acl, etag, true /* store ACL on disk */)
 }
 
-func (i *nodeService) GetACL(_ ipc.ServerContext) (acl security.ACL, etag string, err error) {
+func (i *nodeService) GetACL(_ ipc.ServerContext) (acl access.TaggedACLMap, etag string, err error) {
 	return i.disp.getACL()
 }
 
-func sameMachineCheck(call ipc.ServerContext) error {
-	switch local, err := netstate.SameMachine(call.RemoteEndpoint().Addr()); {
+func sameMachineCheck(ctx ipc.ServerContext) error {
+	switch local, err := netstate.SameMachine(ctx.RemoteEndpoint().Addr()); {
 	case err != nil:
 		return err
 	case local == false:
 		vlog.Errorf("SameMachine() indicates that endpoint is not on the same node")
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, ctx)
 	}
 	return nil
 }
diff --git a/services/mgmt/node/impl/proxy_invoker.go b/services/mgmt/node/impl/proxy_invoker.go
index 1617dac..1f8cf98 100644
--- a/services/mgmt/node/impl/proxy_invoker.go
+++ b/services/mgmt/node/impl/proxy_invoker.go
@@ -6,7 +6,7 @@
 
 	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/rt"
-	"veyron.io/veyron/veyron2/security"
+	"veyron.io/veyron/veyron2/services/security/access"
 )
 
 // proxyInvoker is an ipc.Invoker implementation that proxies all requests
@@ -14,11 +14,11 @@
 // <remote> transparently.
 //
 // remote is the name of the remote object.
-// label is the security label required to access this object.
+// access is the access tag require to access the object.
 // sigStub is used to get the signature of the remote object.
 type proxyInvoker struct {
 	remote  string
-	label   security.Label
+	access  access.Tag
 	sigStub signatureStub
 }
 
@@ -34,7 +34,7 @@
 		var x interface{}
 		argptrs[i] = &x
 	}
-	tags = []interface{}{p.label}
+	tags = []interface{}{p.access}
 	return
 }
 
@@ -185,7 +185,7 @@
 }
 
 func (p *proxyInvoker) VGlob() *ipc.GlobState {
-	return &ipc.GlobState{VAllGlobber: p}
+	return &ipc.GlobState{AllGlobber: p}
 }
 
 func (p *proxyInvoker) Glob(ctx *ipc.GlobContextStub, pattern string) error {
diff --git a/services/mgmt/node/impl/proxy_invoker_test.go b/services/mgmt/node/impl/proxy_invoker_test.go
index 0fcb836..b729d10 100644
--- a/services/mgmt/node/impl/proxy_invoker_test.go
+++ b/services/mgmt/node/impl/proxy_invoker_test.go
@@ -11,6 +11,7 @@
 	"veyron.io/veyron/veyron2/security"
 	"veyron.io/veyron/veyron2/services/mgmt/stats"
 	"veyron.io/veyron/veyron2/services/mounttable"
+	"veyron.io/veyron/veyron2/services/security/access"
 )
 
 // TODO(toddw): Add tests of Signature and MethodSignature.
@@ -45,7 +46,6 @@
 	}
 	disp := &proxyDispatcher{
 		naming.JoinAddressName(ep1.String(), "__debug/stats"),
-		security.Label(security.AllLabels),
 		stats.StatsServer(nil),
 	}
 	if err := server2.ServeDispatcher("", disp); err != nil {
@@ -97,10 +97,9 @@
 
 type proxyDispatcher struct {
 	remote  string
-	label   security.Label
 	sigStub signatureStub
 }
 
 func (d *proxyDispatcher) Lookup(suffix string) (interface{}, security.Authorizer, error) {
-	return &proxyInvoker{naming.Join(d.remote, suffix), d.label, d.sigStub}, nil, nil
+	return &proxyInvoker{naming.Join(d.remote, suffix), access.Debug, d.sigStub}, nil, nil
 }
diff --git a/services/mgmt/node/impl/util.go b/services/mgmt/node/impl/util.go
index 29ca3da..f700552 100644
--- a/services/mgmt/node/impl/util.go
+++ b/services/mgmt/node/impl/util.go
@@ -10,21 +10,29 @@
 	"veyron.io/veyron/veyron/services/mgmt/lib/binary"
 
 	"veyron.io/veyron/veyron2/context"
+	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/services/mgmt/application"
 	"veyron.io/veyron/veyron2/services/mgmt/repository"
+	"veyron.io/veyron/veyron2/verror2"
 	"veyron.io/veyron/veyron2/vlog"
 )
 
+// TODO(caprita): Set these timeout in a more principled manner.
+const (
+	childReadyTimeout = 20 * time.Second
+	ipcContextTimeout = time.Minute
+)
+
 func downloadBinary(workspace, fileName, name string) error {
-	data, err := binary.Download(name)
+	data, _, err := binary.Download(rt.R().NewContext(), name)
 	if err != nil {
 		vlog.Errorf("Download(%v) failed: %v", name, err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	path, perm := filepath.Join(workspace, fileName), os.FileMode(755)
 	if err := ioutil.WriteFile(path, data, perm); err != nil {
 		vlog.Errorf("WriteFile(%v, %v) failed: %v", path, perm, err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	return nil
 }
@@ -37,7 +45,7 @@
 	envelope, err := stub.Match(ctx, profiles)
 	if err != nil {
 		vlog.Errorf("Match(%v) failed: %v", profiles, err)
-		return nil, errOperationFailed
+		return nil, verror2.Make(ErrOperationFailed, ctx)
 	}
 	return &envelope, nil
 }
@@ -48,7 +56,7 @@
 	self := os.Args[0]
 	if err := os.Link(self, path); err != nil {
 		vlog.Errorf("Link(%v, %v) failed: %v", self, path, err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	return nil
 }
@@ -63,16 +71,16 @@
 	if err == nil {
 		if err := os.Remove(fi.Name()); err != nil {
 			vlog.Errorf("Remove(%v) failed: %v", fi.Name(), err)
-			return errOperationFailed
+			return verror2.Make(ErrOperationFailed, nil)
 		}
 	}
 	if err := os.Symlink(target, newLink); err != nil {
 		vlog.Errorf("Symlink(%v, %v) failed: %v", target, newLink, err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	if err := os.Rename(newLink, link); err != nil {
 		vlog.Errorf("Rename(%v, %v) failed: %v", newLink, link, err)
-		return errOperationFailed
+		return verror2.Make(ErrOperationFailed, nil)
 	}
 	return nil
 }
diff --git a/services/mgmt/node/impl/util_test.go b/services/mgmt/node/impl/util_test.go
index 0db0633..0d5acf2 100644
--- a/services/mgmt/node/impl/util_test.go
+++ b/services/mgmt/node/impl/util_test.go
@@ -19,6 +19,7 @@
 	"veyron.io/veyron/veyron2/security"
 	"veyron.io/veyron/veyron2/services/mgmt/node"
 	"veyron.io/veyron/veyron2/verror"
+	"veyron.io/veyron/veyron2/verror2"
 	"veyron.io/veyron/veyron2/vlog"
 
 	"veyron.io/veyron/veyron/lib/expect"
@@ -31,27 +32,33 @@
 	"veyron.io/veyron/veyron2/services/mgmt/application"
 )
 
-// Setting this environment variable to any non-empty value avoids removing the
-// node manager's workspace for successful test runs (for failed test runs, this
-// is already the case).  This is useful when developing test cases.
-const preserveNMWorkspaceEnv = "VEYRON_TEST_PRESERVE_NM_WORKSPACE"
+const (
+	// Setting this environment variable to any non-empty value avoids
+	// removing the node manager's workspace for successful test runs (for
+	// failed test runs, this is already the case).  This is useful when
+	// developing test cases.
+	preserveNMWorkspaceEnv = "VEYRON_TEST_PRESERVE_NM_WORKSPACE"
+
+	// TODO(caprita): Set the timeout in a more principled manner.
+	expectTimeout = 20 * time.Second
+)
 
 func loc(d int) string {
 	_, file, line, _ := runtime.Caller(d + 1)
 	return fmt.Sprintf("%s:%d", filepath.Base(file), line)
 }
 
-func startRootMT(t *testing.T, sh *modules.Shell) (string, modules.Handle, *expect.Session) {
+func startRootMT(t *testing.T, sh *modules.Shell) (string, modules.Handle) {
 	h, err := sh.Start(core.RootMTCommand, nil, "--", "--veyron.tcp.address=127.0.0.1:0")
 	if err != nil {
 		t.Fatalf("failed to start root mount table: %s", err)
 	}
-	s := expect.NewSession(t, h.Stdout(), time.Minute)
+	s := expect.NewSession(t, h.Stdout(), expectTimeout)
 	rootName := s.ExpectVar("MT_NAME")
 	if t.Failed() {
 		t.Fatalf("failed to read mt name: %s", s.Error())
 	}
-	return rootName, h, s
+	return rootName, h
 }
 
 func credentialsForChild(blessing string) (string, []string) {
@@ -59,28 +66,56 @@
 	return creds, []string{consts.VeyronCredentials + "=" + creds}
 }
 
+// setNSRoots sets the roots for the local runtime's namespace using the modules
+// function SetNamesaceRootCommand.
+func setNSRoots(t *testing.T, sh *modules.Shell, roots ...string) {
+	setRootsHandle, err := sh.Start(core.SetNamespaceRootsCommand, nil, roots...)
+	if err != nil {
+		t.Fatalf("%s: unexpected error: %s", loc(2), err)
+	}
+	if err := setRootsHandle.Shutdown(nil, os.Stderr); err != nil {
+		t.Fatalf("%s: SetNamespaceRootsCommand failed with %v", loc(2), err)
+	}
+}
+
 func createShellAndMountTable(t *testing.T) (*modules.Shell, func()) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	// The shell, will, by default share credentials with its children.
 	sh.ClearVar(consts.VeyronCredentials)
 
-	mtName, mtHandle, _ := startRootMT(t, sh)
+	mtName, mtHandle := startRootMT(t, sh)
+	vlog.VI(1).Infof("Started shell mounttable with name %v", mtName)
 	// Make sure the root mount table is the last process to be shutdown
 	// since the others will likely want to communicate with it during
 	// their shutdown process
 	sh.Forget(mtHandle)
 
+	// TODO(caprita): Define a GetNamespaceRootsCommand in modules/core and
+	// use that?
+	oldNamespaceRoots := rt.R().Namespace().Roots()
 	fn := func() {
 		vlog.VI(1).Info("------------ CLEANUP ------------")
 		vlog.VI(1).Info("---------------------------------")
-		sh.Cleanup(nil, os.Stderr)
-		mtHandle.Shutdown(nil, os.Stderr)
-		sh.Start(core.SetNamespaceRootsCommand, nil, "")
+		vlog.VI(1).Info("--(cleaning up shell)------------")
+		if err := sh.Cleanup(os.Stdout, os.Stderr); err != nil {
+			t.Fatalf("sh.Cleanup failed with %v", err)
+		}
+		vlog.VI(1).Info("--(done cleaning up shell)-------")
+		vlog.VI(1).Info("--(shutting down root mt)--------")
+		if err := mtHandle.Shutdown(os.Stdout, os.Stderr); err != nil {
+			t.Fatalf("mtHandle.Shutdown failed with %v", err)
+		}
+		vlog.VI(1).Info("--(done shutting down root mt)---")
+		vlog.VI(1).Info("--------- DONE CLEANUP ----------")
+		// Calling sh.Start after sh.Cleanup is not a good idea.
+		// TODO(caprita): set the roots by hand and avoid running the
+		// corresponding modules command.
+		setNSRoots(t, sh, oldNamespaceRoots...)
 	}
-
-	if _, err := sh.Start(core.SetNamespaceRootsCommand, nil, mtName); err != nil {
-		t.Fatalf("%s: unexpected error: %s", loc(1), err)
-	}
+	setNSRoots(t, sh, mtName)
 	sh.SetVar(consts.NamespaceRootPrefix, mtName)
 	return sh, fn
 }
@@ -91,7 +126,7 @@
 		t.Fatalf("%s: failed to start %q: %s", loc(1), cmd, err)
 		return nil, nil
 	}
-	s := expect.NewSession(t, h.Stdout(), 10*time.Second)
+	s := expect.NewSession(t, h.Stdout(), expectTimeout)
 	s.SetVerbosity(testing.Verbose())
 	return h, s
 }
@@ -137,7 +172,7 @@
 		vlog.Fatalf("NewServer() failed: %v", err)
 	}
 	spec := static.ListenSpec
-	spec.Address = "127.0.0.1:0"
+	spec.Address = "127.0.0.1:0" // Isn't this the default?
 	endpoint, err := server.Listen(spec)
 	if err != nil {
 		vlog.Fatalf("Listen(%s) failed: %v", static.ListenSpec, err)
@@ -149,7 +184,7 @@
 func resolveExpectNotFound(t *testing.T, name string) {
 	if results, err := rt.R().Namespace().Resolve(rt.R().NewContext(), name); err == nil {
 		t.Fatalf("Resolve(%v) succeeded with results %v when it was expected to fail", name, results)
-	} else if expectErr := naming.ErrNoSuchName.ID; !verror.Is(err, expectErr) {
+	} else if expectErr := naming.ErrNoSuchName.ID; !verror2.Is(err, expectErr) {
 		t.Fatalf("Resolve(%v) failed with error %v, expected error ID %v", name, err, expectErr)
 	}
 }
@@ -183,11 +218,7 @@
 }
 
 func updateNodeExpectError(t *testing.T, name string, errID verror.ID) {
-	if err := nodeStub(name).Update(rt.R().NewContext()); !verror.Is(err, errID) {
-		if errID == naming.ErrNoSuchName.ID && err.Error() == "no different version available" {
-			// TODO(bprosnitz) Remove this check when errUpdateNoOp is updated to verror2
-			return
-		}
+	if err := nodeStub(name).Update(rt.R().NewContext()); !verror2.Is(err, errID) {
 		t.Fatalf("%s: Update(%v) expected to fail with %v, got %v instead", loc(1), name, errID, err)
 	}
 }
@@ -199,11 +230,7 @@
 }
 
 func revertNodeExpectError(t *testing.T, name string, errID verror.ID) {
-	if err := nodeStub(name).Revert(rt.R().NewContext()); !verror.Is(err, errID) {
-		if errID == naming.ErrNoSuchName.ID && err.Error() == "no different version available" {
-			// TODO(bprosnitz) Remove this check when errUpdateNoOp is updated to verror2
-			return
-		}
+	if err := nodeStub(name).Revert(rt.R().NewContext()); !verror2.Is(err, errID) {
 		t.Fatalf("%s: Revert(%v) expected to fail with %v, got %v instead", loc(1), name, errID, err)
 	}
 }
@@ -273,7 +300,7 @@
 }
 
 func startAppExpectError(t *testing.T, appID string, expectedError verror.ID, opt ...veyron2.Runtime) {
-	if _, err := startAppImpl(t, appID, "forapp", opt...); err == nil || !verror.Is(err, expectedError) {
+	if _, err := startAppImpl(t, appID, "forapp", opt...); err == nil || !verror2.Is(err, expectedError) {
 		t.Fatalf("%s: Start(%v) expected to fail with %v, got %v instead", loc(1), appID, expectedError, err)
 	}
 }
@@ -297,7 +324,7 @@
 }
 
 func resumeAppExpectError(t *testing.T, appID, instanceID string, expectedError verror.ID, opt ...veyron2.Runtime) {
-	if err := appStub(appID, instanceID).Resume(ort(opt).NewContext()); err == nil || !verror.Is(err, expectedError) {
+	if err := appStub(appID, instanceID).Resume(ort(opt).NewContext()); err == nil || !verror2.Is(err, expectedError) {
 		t.Fatalf("%s: Resume(%v/%v) expected to fail with %v, got %v instead", loc(1), appID, instanceID, expectedError, err)
 	}
 }
@@ -309,11 +336,7 @@
 }
 
 func updateAppExpectError(t *testing.T, appID string, expectedError verror.ID) {
-	if err := appStub(appID).Update(rt.R().NewContext()); err == nil || !verror.Is(err, expectedError) {
-		if expectedError == naming.ErrNoSuchName.ID && err.Error() == "no different version available" {
-			// TODO(bprosnitz) Remove this check when errUpdateNoOp is updated to verror2
-			return
-		}
+	if err := appStub(appID).Update(rt.R().NewContext()); err == nil || !verror2.Is(err, expectedError) {
 		t.Fatalf("%s: Update(%v) expected to fail with %v, got %v instead", loc(1), appID, expectedError, err)
 	}
 }
@@ -325,11 +348,7 @@
 }
 
 func revertAppExpectError(t *testing.T, appID string, expectedError verror.ID) {
-	if err := appStub(appID).Revert(rt.R().NewContext()); err == nil || !verror.Is(err, expectedError) {
-		if expectedError == naming.ErrNoSuchName.ID && err.Error() == "no different version available" {
-			// TODO(bprosnitz) Remove this check when errUpdateNoOp is updated to verror2
-			return
-		}
+	if err := appStub(appID).Revert(rt.R().NewContext()); err == nil || !verror2.Is(err, expectedError) {
 		t.Fatalf("%s: Revert(%v) expected to fail with %v, got %v instead", loc(1), appID, expectedError, err)
 	}
 }
diff --git a/services/mgmt/node/noded/main.go b/services/mgmt/node/noded/main.go
index eea0702..c40f2a9 100644
--- a/services/mgmt/node/noded/main.go
+++ b/services/mgmt/node/noded/main.go
@@ -76,5 +76,5 @@
 	impl.InvokeCallback(name)
 
 	// Wait until shutdown.
-	<-signals.ShutdownOnSignals()
+	<-signals.ShutdownOnSignals(runtime)
 }
diff --git a/services/mgmt/profile/profile.vdl.go b/services/mgmt/profile/profile.vdl.go
index 97c0689..d3c766c 100644
--- a/services/mgmt/profile/profile.vdl.go
+++ b/services/mgmt/profile/profile.vdl.go
@@ -7,6 +7,9 @@
 
 import (
 	"veyron.io/veyron/veyron2/services/mgmt/build"
+
+	// The non-user imports are prefixed with "__" to prevent collisions.
+	__vdl "veyron.io/veyron/veyron2/vdl"
 )
 
 // Library describes a shared library that applications may use.
@@ -19,6 +22,11 @@
 	MinorVersion string
 }
 
+func (Library) __VDLReflect(struct {
+	Name string "veyron.io/veyron/veyron/services/mgmt/profile.Library"
+}) {
+}
+
 // Specification is how we represent a profile internally. It should
 // provide enough information to allow matching of binaries to nodes.
 type Specification struct {
@@ -36,3 +44,13 @@
 	// OS is the target operating system of the profile.
 	OS build.OperatingSystem
 }
+
+func (Specification) __VDLReflect(struct {
+	Name string "veyron.io/veyron/veyron/services/mgmt/profile.Specification"
+}) {
+}
+
+func init() {
+	__vdl.Register(Library{})
+	__vdl.Register(Specification{})
+}
diff --git a/services/mgmt/profile/profiled/main.go b/services/mgmt/profile/profiled/main.go
index d01b803..a811f12 100644
--- a/services/mgmt/profile/profiled/main.go
+++ b/services/mgmt/profile/profiled/main.go
@@ -45,5 +45,5 @@
 	vlog.Infof("Profile repository running at endpoint=%q", endpoint)
 
 	// Wait until shutdown.
-	<-signals.ShutdownOnSignals()
+	<-signals.ShutdownOnSignals(runtime)
 }
diff --git a/services/mgmt/repository/repository.vdl b/services/mgmt/repository/repository.vdl
index 3b553b8..ab9acb4 100644
--- a/services/mgmt/repository/repository.vdl
+++ b/services/mgmt/repository/repository.vdl
@@ -4,8 +4,8 @@
 
 import (
 	"veyron.io/veyron/veyron/services/mgmt/profile"
-	"veyron.io/veyron/veyron2/security"
 	"veyron.io/veyron/veyron2/services/mgmt/application"
+	"veyron.io/veyron/veyron2/services/security/access"
 	public "veyron.io/veyron/veyron2/services/mgmt/repository"
 )
 
@@ -17,7 +17,7 @@
 	// Put adds the given tuple of application version (specified
 	// through the object name suffix) and application envelope to all
 	// of the given application profiles.
-	Put(Profiles []string, Envelope application.Envelope) error {security.WriteLabel}
+	Put(Profiles []string, Envelope application.Envelope) error {access.Write}
 	// Remove removes the application envelope for the given profile
 	// name and application version (specified through the object name
 	// suffix). If no version is specified as part of the suffix, the
@@ -25,7 +25,7 @@
 	//
 	// TODO(jsimsa): Add support for using "*" to specify all profiles
 	// when Matt implements Globing (or Ken implements querying).
-	Remove(Profile string) error {security.WriteLabel}
+	Remove(Profile string) error {access.Write}
 }
 
 // Profile describes a profile internally. Besides the public Profile
@@ -34,11 +34,11 @@
 	public.Profile
 	// Specification returns the profile specification for the profile
 	// identified through the object name suffix.
-	Specification() (profile.Specification, error) {security.ReadLabel}
+	Specification() (profile.Specification, error) {access.Read}
 	// Put sets the profile specification for the profile identified
 	// through the object name suffix.
-	Put(Specification profile.Specification) error {security.WriteLabel}
+	Put(Specification profile.Specification) error {access.Write}
 	// Remove removes the profile specification for the profile
 	// identified through the object name suffix.
-	Remove() error {security.WriteLabel}
+	Remove() error {access.Write}
 }
diff --git a/services/mgmt/repository/repository.vdl.go b/services/mgmt/repository/repository.vdl.go
index 0b017b3..48541ae 100644
--- a/services/mgmt/repository/repository.vdl.go
+++ b/services/mgmt/repository/repository.vdl.go
@@ -8,12 +8,12 @@
 import (
 	"veyron.io/veyron/veyron/services/mgmt/profile"
 
-	"veyron.io/veyron/veyron2/security"
-
 	"veyron.io/veyron/veyron2/services/mgmt/application"
 
 	"veyron.io/veyron/veyron2/services/mgmt/repository"
 
+	"veyron.io/veyron/veyron2/services/security/access"
+
 	// The non-user imports are prefixed with "__" to prevent collisions.
 	__veyron2 "veyron.io/veyron/veyron2"
 	__context "veyron.io/veyron/veyron2/context"
@@ -232,7 +232,7 @@
 			OutArgs: []__ipc.ArgDesc{
 				{"", ``}, // error
 			},
-			Tags: []__vdlutil.Any{security.Label(4)},
+			Tags: []__vdlutil.Any{access.Tag("Write")},
 		},
 		{
 			Name: "Remove",
@@ -243,7 +243,7 @@
 			OutArgs: []__ipc.ArgDesc{
 				{"", ``}, // error
 			},
-			Tags: []__vdlutil.Any{security.Label(4)},
+			Tags: []__vdlutil.Any{access.Tag("Write")},
 		},
 	},
 }
@@ -254,10 +254,10 @@
 	result.Methods["Put"] = __ipc.MethodSignature{
 		InArgs: []__ipc.MethodArgument{
 			{Name: "Profiles", Type: 61},
-			{Name: "Envelope", Type: 65},
+			{Name: "Envelope", Type: 66},
 		},
 		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 66},
+			{Name: "", Type: 67},
 		},
 	}
 	result.Methods["Remove"] = __ipc.MethodSignature{
@@ -265,17 +265,18 @@
 			{Name: "Profile", Type: 3},
 		},
 		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 66},
+			{Name: "", Type: 67},
 		},
 	}
 
 	result.TypeDefs = []__vdlutil.Any{
-		__wiretype.StructType{
+		__wiretype.MapType{Key: 0x3, Elem: 0x3, Name: "", Tags: []string(nil)}, __wiretype.StructType{
 			[]__wiretype.FieldType{
 				__wiretype.FieldType{Type: 0x3, Name: "Title"},
 				__wiretype.FieldType{Type: 0x3d, Name: "Args"},
 				__wiretype.FieldType{Type: 0x3, Name: "Binary"},
 				__wiretype.FieldType{Type: 0x3d, Name: "Env"},
+				__wiretype.FieldType{Type: 0x41, Name: "Packages"},
 			},
 			"veyron.io/veyron/veyron2/services/mgmt/application.Envelope", []string(nil)},
 		__wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
@@ -535,7 +536,7 @@
 				{"", ``}, // profile.Specification
 				{"", ``}, // error
 			},
-			Tags: []__vdlutil.Any{security.Label(2)},
+			Tags: []__vdlutil.Any{access.Tag("Read")},
 		},
 		{
 			Name: "Put",
@@ -546,7 +547,7 @@
 			OutArgs: []__ipc.ArgDesc{
 				{"", ``}, // error
 			},
-			Tags: []__vdlutil.Any{security.Label(4)},
+			Tags: []__vdlutil.Any{access.Tag("Write")},
 		},
 		{
 			Name: "Remove",
@@ -554,7 +555,7 @@
 			OutArgs: []__ipc.ArgDesc{
 				{"", ``}, // error
 			},
-			Tags: []__vdlutil.Any{security.Label(4)},
+			Tags: []__vdlutil.Any{access.Tag("Write")},
 		},
 	},
 }
diff --git a/services/mgmt/root/rootd/main.go b/services/mgmt/root/rootd/main.go
index ff23fdc..45f9205 100644
--- a/services/mgmt/root/rootd/main.go
+++ b/services/mgmt/root/rootd/main.go
@@ -32,5 +32,5 @@
 	}
 
 	// Wait until shutdown.
-	<-signals.ShutdownOnSignals()
+	<-signals.ShutdownOnSignals(r)
 }
diff --git a/services/mgmt/stats/impl/stats_test.go b/services/mgmt/stats/impl/stats_test.go
index 6b526f6..fe502c4 100644
--- a/services/mgmt/stats/impl/stats_test.go
+++ b/services/mgmt/stats/impl/stats_test.go
@@ -107,6 +107,8 @@
 
 	// Test WatchGlob()
 	{
+		noRM := types.ResumeMarker{}
+		_ = noRM
 		stream, err := c.WatchGlob(rt.R().NewContext(), types.GlobRequest{Pattern: "testing/foo/bar"})
 		if err != nil {
 			t.Fatalf("c.WatchGlob failed: %v", err)
@@ -116,6 +118,8 @@
 			t.Fatalf("expected more stream values")
 		}
 		got := iterator.Value()
+		// TODO(toddw): This change is necessary for vom2:
+		//expected := types.Change{Name: "testing/foo/bar", Value: int64(10), ResumeMarker: noRM}
 		expected := types.Change{Name: "testing/foo/bar", Value: int64(10)}
 		if !reflect.DeepEqual(got, expected) {
 			t.Errorf("unexpected result. Got %#v, want %#v", got, expected)
@@ -127,6 +131,8 @@
 			t.Fatalf("expected more stream values")
 		}
 		got = iterator.Value()
+		// TODO(toddw): This change is necessary for vom2:
+		//expected := types.Change{Name: "testing/foo/bar", Value: int64(15), ResumeMarker: noRM}
 		expected = types.Change{Name: "testing/foo/bar", Value: int64(15)}
 		if !reflect.DeepEqual(got, expected) {
 			t.Errorf("unexpected result. Got %#v, want %#v", got, expected)
@@ -138,6 +144,8 @@
 			t.Fatalf("expected more stream values")
 		}
 		got = iterator.Value()
+		// TODO(toddw): This change is necessary for vom2:
+		//expected := types.Change{Name: "testing/foo/bar", Value: int64(17), ResumeMarker: noRM}
 		expected = types.Change{Name: "testing/foo/bar", Value: int64(17)}
 		if !reflect.DeepEqual(got, expected) {
 			t.Errorf("unexpected result. Got %#v, want %#v", got, expected)
@@ -171,6 +179,8 @@
 		want := istats.HistogramValue{
 			Count: 10,
 			Sum:   45,
+			Min:   0,
+			Max:   9,
 			Buckets: []istats.HistogramBucket{
 				istats.HistogramBucket{LowBound: 0, Count: 1},
 				istats.HistogramBucket{LowBound: 1, Count: 2},
diff --git a/services/mgmt/stats/types.go b/services/mgmt/stats/types.go
new file mode 100644
index 0000000..1791465
--- /dev/null
+++ b/services/mgmt/stats/types.go
@@ -0,0 +1,51 @@
+package stats
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"strconv"
+	"strings"
+)
+
+// Print writes textual output of the histogram values.
+func (v HistogramValue) Print(w io.Writer) {
+	avg := float64(v.Sum) / float64(v.Count)
+	fmt.Fprintf(w, "Count: %d  Min: %d  Max: %d  Avg: %.2f\n", v.Count, v.Min, v.Max, avg)
+	fmt.Fprintf(w, "%s\n", strings.Repeat("-", 60))
+	if v.Count <= 0 {
+		return
+	}
+
+	maxBucketDigitLen := len(strconv.FormatInt(v.Buckets[len(v.Buckets)-1].LowBound, 10))
+	if maxBucketDigitLen < 3 {
+		// For "inf".
+		maxBucketDigitLen = 3
+	}
+	maxCountDigitLen := len(strconv.FormatInt(v.Count, 10))
+	percentMulti := 100 / float64(v.Count)
+
+	accCount := int64(0)
+	for i, b := range v.Buckets {
+		fmt.Fprintf(w, "[%*d, ", maxBucketDigitLen, b.LowBound)
+		if i+1 < len(v.Buckets) {
+			fmt.Fprintf(w, "%*d)", maxBucketDigitLen, v.Buckets[i+1].LowBound)
+		} else {
+			fmt.Fprintf(w, "%*s)", maxBucketDigitLen, "inf")
+		}
+
+		accCount += b.Count
+		fmt.Fprintf(w, "  %*d  %5.1f%%  %5.1f%%", maxCountDigitLen, b.Count, float64(b.Count)*percentMulti, float64(accCount)*percentMulti)
+
+		const barScale = 0.1
+		barLength := int(float64(b.Count)*percentMulti*barScale + 0.5)
+		fmt.Fprintf(w, "  %s\n", strings.Repeat("#", barLength))
+	}
+}
+
+// String returns the textual output of the histogram values as string.
+func (v HistogramValue) String() string {
+	var b bytes.Buffer
+	v.Print(&b)
+	return b.String()
+}
diff --git a/services/mgmt/stats/types.vdl b/services/mgmt/stats/types.vdl
index 8aa3ec9..d11aa13 100644
--- a/services/mgmt/stats/types.vdl
+++ b/services/mgmt/stats/types.vdl
@@ -7,6 +7,10 @@
 	Count int64
 	// Sum is the sum of all the values added to the histogram.
 	Sum int64
+	// Min is the minimum of all the values added to the histogram.
+	Min int64
+	// Max is the maximum of all the values added to the histogram.
+	Max int64
 	// Buckets contains all the buckets of the histogram.
 	Buckets []HistogramBucket
 }
diff --git a/services/mgmt/stats/types.vdl.go b/services/mgmt/stats/types.vdl.go
index 7ad330c..4884f69 100644
--- a/services/mgmt/stats/types.vdl.go
+++ b/services/mgmt/stats/types.vdl.go
@@ -4,16 +4,30 @@
 // Packages stats defines the non-native types exported by the stats service.
 package stats
 
+import (
+	// The non-user imports are prefixed with "__" to prevent collisions.
+	__vdl "veyron.io/veyron/veyron2/vdl"
+)
+
 // HistogramValue is the value of Histogram objects.
 type HistogramValue struct {
 	// Count is the total number of values added to the histogram.
 	Count int64
 	// Sum is the sum of all the values added to the histogram.
 	Sum int64
+	// Min is the minimum of all the values added to the histogram.
+	Min int64
+	// Max is the maximum of all the values added to the histogram.
+	Max int64
 	// Buckets contains all the buckets of the histogram.
 	Buckets []HistogramBucket
 }
 
+func (HistogramValue) __VDLReflect(struct {
+	Name string "veyron.io/veyron/veyron/services/mgmt/stats.HistogramValue"
+}) {
+}
+
 // HistogramBucket is one histogram bucket.
 type HistogramBucket struct {
 	// LowBound is the lower bound of the bucket.
@@ -21,3 +35,13 @@
 	// Count is the number of values in the bucket.
 	Count int64
 }
+
+func (HistogramBucket) __VDLReflect(struct {
+	Name string "veyron.io/veyron/veyron/services/mgmt/stats.HistogramBucket"
+}) {
+}
+
+func init() {
+	__vdl.Register(HistogramValue{})
+	__vdl.Register(HistogramBucket{})
+}
diff --git a/services/mgmt/vtrace/impl/vtrace_test.go b/services/mgmt/vtrace/impl/vtrace_test.go
index 4e1d0c2..3600fd9 100644
--- a/services/mgmt/vtrace/impl/vtrace_test.go
+++ b/services/mgmt/vtrace/impl/vtrace_test.go
@@ -75,8 +75,8 @@
 	if err = stream.Err(); err != nil && err != io.EOF {
 		t.Fatalf("Unexpected error reading trace stream: %s", err)
 	}
-	if ntraces < 2 {
-		t.Fatalf("Expected at least 2 traces, got %#v", ntraces)
+	if ntraces != 1 {
+		t.Fatalf("Expected 1 trace, got %#v", ntraces)
 	}
 	if tr == nil {
 		t.Fatalf("Desired trace %x not found.", id)
diff --git a/services/mounttable/lib/mounttable.go b/services/mounttable/lib/mounttable.go
index 5ca2af2..719a321 100644
--- a/services/mounttable/lib/mounttable.go
+++ b/services/mounttable/lib/mounttable.go
@@ -10,13 +10,13 @@
 	"time"
 
 	"veyron.io/veyron/veyron/lib/glob"
-	vsecurity "veyron.io/veyron/veyron/security"
 
 	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/security"
 	"veyron.io/veyron/veyron2/services/mounttable"
+	"veyron.io/veyron/veyron2/services/security/access"
 	verror "veyron.io/veyron/veyron2/verror2"
 	"veyron.io/veyron/veyron2/vlog"
 )
@@ -58,7 +58,12 @@
 	children map[string]*node
 }
 
-// NewMountTable creates a new server that uses the default authorization policy.
+// NewMountTable creates a new server that uses the ACLs specified in
+// aclfile for authorization.
+//
+// aclfile is a JSON-encoded mapping from paths in the mounttable to the
+// access.TaggedACLMap for that path. The tags used in the map are the typical
+// access tags (the Tag type defined in veyron2/services/security/access).
 func NewMountTable(aclfile string) (*mountTable, error) {
 	acls, err := parseACLs(aclfile)
 	if err != nil {
@@ -74,7 +79,7 @@
 	if path == "" {
 		return nil, nil
 	}
-	var acls map[string]security.ACL
+	var acls map[string]access.TaggedACLMap
 	f, err := os.Open(path)
 	if err != nil {
 		return nil, err
@@ -85,7 +90,10 @@
 	}
 	result := make(map[string]security.Authorizer)
 	for name, acl := range acls {
-		result[name] = vsecurity.NewACLAuthorizer(acl)
+		result[name], err = access.TaggedACLAuthorizer(acl, access.TypicalTagType())
+		if err != nil {
+			return nil, fmt.Errorf("Unable to create ACL for %q: %v", name, err)
+		}
 	}
 	if result["/"] == nil {
 		return nil, fmt.Errorf("No acl for / in %s", path)
@@ -173,7 +181,7 @@
 	mt.Lock()
 	acl := mt.acls[name]
 	mt.Unlock()
-	vlog.VI(2).Infof("authorizeStep(%s) %s %s %s", name, c.RemoteBlessings(), c.Label(), acl)
+	vlog.VI(2).Infof("authorizeStep(%v) %v %v %v", name, c.RemoteBlessings(), c.MethodTags(), acl)
 	if acl != nil {
 		return acl.Authorize(c)
 	}
diff --git a/services/mounttable/lib/testdata/noRoot.acl b/services/mounttable/lib/testdata/noRoot.acl
index 0ff2383..b663a07 100644
--- a/services/mounttable/lib/testdata/noRoot.acl
+++ b/services/mounttable/lib/testdata/noRoot.acl
@@ -1,3 +1,6 @@
 {
-"/foo/bar": {"fake/root": "RW"},
-}
\ No newline at end of file
+"/foo/bar": {
+	"Read":  { "In": ["fake/root"] },
+        "Write": { "In": ["fake/root"] }
+}
+}
diff --git a/services/mounttable/lib/testdata/test.acl b/services/mounttable/lib/testdata/test.acl
index 597dda9..7990532 100644
--- a/services/mounttable/lib/testdata/test.acl
+++ b/services/mounttable/lib/testdata/test.acl
@@ -1,5 +1,14 @@
 {
-"/": {"In": {"root": "RW", "...": "R"}},
-"/stuff": {"In": {"root": "RW", "bob": "R"}},
-"/a": {"In": {"root": "RW", "alice": "R"}}
-}
\ No newline at end of file
+"/": {
+	"Read":  { "In": ["..."] },
+	"Write": { "In": ["root"] }
+},
+"/stuff": {
+	"Read":  { "In": ["bob", "root"] },
+        "Write": { "In": ["root"] }
+},
+"/a": {
+	"Read":  { "In": ["alice", "root"] },
+        "Write": { "In": ["root"] }
+}
+}
diff --git a/services/mounttable/mounttabled/mounttable.go b/services/mounttable/mounttabled/mounttable.go
index 7234a09..3286652 100644
--- a/services/mounttable/mounttabled/mounttable.go
+++ b/services/mounttable/mounttabled/mounttable.go
@@ -84,5 +84,5 @@
 	}
 
 	// Wait until signal is received.
-	vlog.Info("Received signal ", <-signals.ShutdownOnSignals())
+	vlog.Info("Received signal ", <-signals.ShutdownOnSignals(r))
 }
diff --git a/services/proxy/proxyd/main.go b/services/proxy/proxyd/main.go
index be03702..b31b919 100644
--- a/services/proxy/proxyd/main.go
+++ b/services/proxy/proxyd/main.go
@@ -6,6 +6,7 @@
 	"flag"
 	"net/http"
 	_ "net/http/pprof"
+	"strings"
 	"time"
 
 	"veyron.io/veyron/veyron2/naming"
@@ -47,7 +48,15 @@
 		publisher := publisher.New(r.NewContext(), r.Namespace(), time.Minute)
 		defer publisher.WaitForStop()
 		defer publisher.Stop()
-		publisher.AddServer(naming.JoinAddressName(proxy.Endpoint().String(), ""), false)
+		ep := naming.JoinAddressName(proxy.Endpoint().String(), "")
+		publisher.AddServer(ep, false)
+		// If the protocol is tcp we need to also publish the websocket endpoint.
+		// TODO(bjornick): Remove this hack before we launch.
+		if strings.HasPrefix(proxy.Endpoint().Addr().Network(), "tcp") {
+			wsEP := strings.Replace(ep, "@"+proxy.Endpoint().Addr().Network()+"@", "@ws@", 1)
+			publisher.AddServer(wsEP, false)
+		}
+
 		publisher.AddName(*name)
 	}
 
diff --git a/services/security/discharger.vdl b/services/security/discharger.vdl
index 037c6b4..a7dfbd3 100644
--- a/services/security/discharger.vdl
+++ b/services/security/discharger.vdl
@@ -12,5 +12,5 @@
   // respectively. (not enforced here because vdl does not know these types)
   // TODO(ataly,ashankar): Figure out a VDL representation for ThirdPartyCaveat
   // and Discharge and use those here?
-  Discharge(Caveat any, Impetus security.DischargeImpetus) (Discharge any, err error) {security.ReadLabel}
+  Discharge(Caveat any, Impetus security.DischargeImpetus) (Discharge any, err error)
 }
diff --git a/services/security/discharger.vdl.go b/services/security/discharger.vdl.go
index 420c1c6..8fbf3c6 100644
--- a/services/security/discharger.vdl.go
+++ b/services/security/discharger.vdl.go
@@ -171,7 +171,6 @@
 				{"Discharge", ``}, // __vdlutil.Any
 				{"err", ``},       // error
 			},
-			Tags: []__vdlutil.Any{security.Label(2)},
 		},
 	},
 }
diff --git a/tools/application/doc.go b/tools/application/doc.go
index 5c8f11f..ba58393 100644
--- a/tools/application/doc.go
+++ b/tools/application/doc.go
@@ -9,7 +9,8 @@
    application <command>
 
 The application commands are:
-   match       Shows the first matching envelope that matches the given profiles.
+   match       Shows the first matching envelope that matches the given
+               profiles.
    put         Add the given envelope to the application for the given profiles.
    remove      removes the application envelope for the given profile.
    edit        edits the application envelope for the given profile.
@@ -17,15 +18,32 @@
 Run "application help [command]" for command usage.
 
 The global flags are:
-   -alsologtostderr=true: log to standard error as well as files
-   -log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
-   -log_dir=: if non-empty, write log files to this directory
-   -logtostderr=false: log to standard error instead of files
-   -max_stack_buf_size=4292608: max size in bytes of the buffer to use for logging stack traces
-   -stderrthreshold=2: logs at or above this threshold go to stderr
-   -v=0: log level for V logs
-   -vmodule=: comma-separated list of pattern=N settings for file-filtered logging
-   -vv=0: log level for V logs
+ -alsologtostderr=true
+   log to standard error as well as files
+ -log_backtrace_at=:0
+   when logging hits line file:N, emit a stack trace
+ -log_dir=
+   if non-empty, write log files to this directory
+ -logtostderr=false
+   log to standard error instead of files
+ -max_stack_buf_size=4292608
+   max size in bytes of the buffer to use for logging stack traces
+ -stderrthreshold=2
+   logs at or above this threshold go to stderr
+ -v=0
+   log level for V logs
+ -veyron.credentials=
+   directory to use for storing security credentials
+ -veyron.namespace.root=[/proxy.envyor.com:8101]
+   local namespace root; can be repeated to provided multiple roots
+ -veyron.vtrace.cache_size=1024
+   The number of vtrace traces to store in memory.
+ -veyron.vtrace.dump_on_shutdown=false
+   If true, dump all stored traces on runtime shutdown.
+ -veyron.vtrace.sample_rate=0
+   Rate (from 0.0 to 1.0) to sample vtrace traces.
+ -vmodule=
+   comma-separated list of pattern=N settings for file-filtered logging
 
 Application Match
 
@@ -34,8 +52,8 @@
 Usage:
    application match <application> <profiles>
 
-<application> is the full name of the application.
-<profiles> is a comma-separated list of profiles.
+<application> is the full name of the application. <profiles> is a
+comma-separated list of profiles.
 
 Application Put
 
@@ -44,9 +62,9 @@
 Usage:
    application put <application> <profiles> <envelope>
 
-<application> is the full name of the application.
-<profiles> is a comma-separated list of profiles.
-<envelope> is the file that contains a JSON-encoded envelope.
+<application> is the full name of the application. <profiles> is a
+comma-separated list of profiles. <envelope> is the file that contains a
+JSON-encoded envelope.
 
 Application Remove
 
@@ -55,8 +73,7 @@
 Usage:
    application remove <application> <profile>
 
-<application> is the full name of the application.
-<profile> is a profile.
+<application> is the full name of the application. <profile> is a profile.
 
 Application Edit
 
@@ -65,21 +82,29 @@
 Usage:
    application edit <application> <profile>
 
-<application> is the full name of the application.
-<profile> is a profile.
+<application> is the full name of the application. <profile> is a profile.
 
 Application Help
 
 Help with no args displays the usage of the parent command.
+
 Help with args displays the usage of the specified sub-command or help topic.
+
 "help ..." recursively displays help for all commands and topics.
 
+The output is formatted to a target width in runes.  The target width is
+determined by checking the environment variable CMDLINE_WIDTH, falling back on
+the terminal width from the OS, falling back on 80 chars.  By setting
+CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
+if x == 0 or is unset one of the fallbacks is used.
+
 Usage:
    application help [flags] [command/topic ...]
 
 [command/topic ...] optionally identifies a specific sub-command or help topic.
 
-The help flags are:
-   -style=text: The formatting style for help output, either "text" or "godoc".
+The application help flags are:
+ -style=text
+   The formatting style for help output, either "text" or "godoc".
 */
 package main
diff --git a/tools/application/impl.go b/tools/application/impl.go
index e37608f..033775b 100644
--- a/tools/application/impl.go
+++ b/tools/application/impl.go
@@ -14,7 +14,6 @@
 	"veyron.io/lib/cmdline"
 	"veyron.io/veyron/veyron/services/mgmt/repository"
 	"veyron.io/veyron/veyron2/context"
-	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/services/mgmt/application"
 )
 
@@ -67,7 +66,7 @@
 	}
 	name, profiles := args[0], args[1]
 	app := repository.ApplicationClient(name)
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
 	defer cancel()
 	j, err := getEnvelopeJSON(ctx, app, profiles)
 	if err != nil {
@@ -99,7 +98,7 @@
 	if err != nil {
 		return fmt.Errorf("ReadFile(%v): %v", envelope, err)
 	}
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
 	defer cancel()
 	if err = putEnvelopeJSON(ctx, app, profiles, j); err != nil {
 		return err
@@ -125,7 +124,7 @@
 	}
 	name, profile := args[0], args[1]
 	app := repository.ApplicationClient(name)
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
 	defer cancel()
 	if err := app.Remove(ctx, profile); err != nil {
 		return err
@@ -159,7 +158,7 @@
 	f.Close()
 	defer os.Remove(fileName)
 
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
 	defer cancel()
 	envData, err := getEnvelopeJSON(ctx, app, profile)
 	if err != nil {
diff --git a/tools/application/impl_test.go b/tools/application/impl_test.go
index 010ace1..d7a6421 100644
--- a/tools/application/impl_test.go
+++ b/tools/application/impl_test.go
@@ -25,6 +25,9 @@
 		Args:   []string{"arg1", "arg2", "arg3"},
 		Binary: "/path/to/binary",
 		Env:    []string{"env1", "env2", "env3"},
+		Packages: map[string]string{
+			"pkg1": "/path/to/package1",
+		},
 	}
 	jsonEnv = `{
   "Title": "fifa world cup",
@@ -38,7 +41,10 @@
     "env1",
     "env2",
     "env3"
-  ]
+  ],
+  "Packages": {
+    "pkg1": "/path/to/package1"
+  }
 }`
 )
 
@@ -98,7 +104,13 @@
 }
 
 func TestApplicationClient(t *testing.T) {
-	runtime := rt.Init()
+	var err error
+	runtime, err = rt.New()
+	if err != nil {
+		t.Fatalf("Unexpected error initializing runtime: %s", err)
+	}
+	defer runtime.Cleanup()
+
 	server, endpoint, err := startServer(t, runtime)
 	if err != nil {
 		return
diff --git a/tools/application/main.go b/tools/application/main.go
index 9e5d556..3723981 100644
--- a/tools/application/main.go
+++ b/tools/application/main.go
@@ -1,15 +1,23 @@
 // The following enables go generate to generate the doc.go file.
-//go:generate go run $VEYRON_ROOT/lib/cmdline/testdata/gendoc.go .
+//go:generate go run $VEYRON_ROOT/veyron/go/src/veyron.io/lib/cmdline/testdata/gendoc.go .
 
 package main
 
 import (
+	"veyron.io/veyron/veyron2"
 	"veyron.io/veyron/veyron2/rt"
 
 	_ "veyron.io/veyron/veyron/profiles"
 )
 
+var runtime veyron2.Runtime
+
 func main() {
-	defer rt.Init().Cleanup()
+	var err error
+	runtime, err = rt.New()
+	if err != nil {
+		panic(err)
+	}
+	defer runtime.Cleanup()
 	root().Main()
 }
diff --git a/tools/binary/doc.go b/tools/binary/doc.go
index 04afd49..daae844 100644
--- a/tools/binary/doc.go
+++ b/tools/binary/doc.go
@@ -15,15 +15,32 @@
 Run "binary help [command]" for command usage.
 
 The global flags are:
-   -alsologtostderr=true: log to standard error as well as files
-   -log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
-   -log_dir=: if non-empty, write log files to this directory
-   -logtostderr=false: log to standard error instead of files
-   -max_stack_buf_size=4292608: max size in bytes of the buffer to use for logging stack traces
-   -stderrthreshold=2: logs at or above this threshold go to stderr
-   -v=0: log level for V logs
-   -vmodule=: comma-separated list of pattern=N settings for file-filtered logging
-   -vv=0: log level for V logs
+ -alsologtostderr=true
+   log to standard error as well as files
+ -log_backtrace_at=:0
+   when logging hits line file:N, emit a stack trace
+ -log_dir=
+   if non-empty, write log files to this directory
+ -logtostderr=false
+   log to standard error instead of files
+ -max_stack_buf_size=4292608
+   max size in bytes of the buffer to use for logging stack traces
+ -stderrthreshold=2
+   logs at or above this threshold go to stderr
+ -v=0
+   log level for V logs
+ -veyron.credentials=
+   directory to use for storing security credentials
+ -veyron.namespace.root=[/proxy.envyor.com:8101]
+   local namespace root; can be repeated to provided multiple roots
+ -veyron.vtrace.cache_size=1024
+   The number of vtrace traces to store in memory.
+ -veyron.vtrace.dump_on_shutdown=false
+   If true, dump all stored traces on runtime shutdown.
+ -veyron.vtrace.sample_rate=0
+   Rate (from 0.0 to 1.0) to sample vtrace traces.
+ -vmodule=
+   comma-separated list of pattern=N settings for file-filtered logging
 
 Binary Delete
 
@@ -42,8 +59,8 @@
 Usage:
    binary download <von> <filename>
 
-<von> is the veyron object name of the binary to download
-<filename> is the name of the file where the binary will be written
+<von> is the veyron object name of the binary to download <filename> is the name
+of the file where the binary will be written
 
 Binary Upload
 
@@ -53,21 +70,30 @@
 Usage:
    binary upload <von> <filename>
 
-<von> is the veyron object name of the binary to upload
-<filename> is the name of the file to upload
+<von> is the veyron object name of the binary to upload <filename> is the name
+of the file to upload
 
 Binary Help
 
 Help with no args displays the usage of the parent command.
+
 Help with args displays the usage of the specified sub-command or help topic.
+
 "help ..." recursively displays help for all commands and topics.
 
+The output is formatted to a target width in runes.  The target width is
+determined by checking the environment variable CMDLINE_WIDTH, falling back on
+the terminal width from the OS, falling back on 80 chars.  By setting
+CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
+if x == 0 or is unset one of the fallbacks is used.
+
 Usage:
    binary help [flags] [command/topic ...]
 
 [command/topic ...] optionally identifies a specific sub-command or help topic.
 
-The help flags are:
-   -style=text: The formatting style for help output, either "text" or "godoc".
+The binary help flags are:
+ -style=text
+   The formatting style for help output, either "text" or "godoc".
 */
 package main
diff --git a/tools/binary/impl.go b/tools/binary/impl.go
index 69f0f51..df34d6c 100644
--- a/tools/binary/impl.go
+++ b/tools/binary/impl.go
@@ -21,7 +21,7 @@
 		return cmd.UsageErrorf("delete: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	von := args[0]
-	if err := binary.Delete(von); err != nil {
+	if err := binary.Delete(runtime.NewContext(), von); err != nil {
 		return err
 	}
 	fmt.Fprintf(cmd.Stdout(), "Binary deleted successfully\n")
@@ -48,7 +48,7 @@
 		return cmd.UsageErrorf("download: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	von, filename := args[0], args[1]
-	if err := binary.DownloadToFile(von, filename); err != nil {
+	if err := binary.DownloadToFile(runtime.NewContext(), von, filename); err != nil {
 		return err
 	}
 	fmt.Fprintf(cmd.Stdout(), "Binary downloaded to file %s\n", filename)
@@ -71,11 +71,12 @@
 }
 
 func runUpload(cmd *cmdline.Command, args []string) error {
+	// TODO(rthellend): Add support for creating packages on the fly.
 	if expected, got := 2, len(args); expected != got {
 		return cmd.UsageErrorf("upload: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	von, filename := args[0], args[1]
-	if err := binary.UploadFromFile(von, filename); err != nil {
+	if err := binary.UploadFromFile(runtime.NewContext(), von, filename); err != nil {
 		return err
 	}
 	fmt.Fprintf(cmd.Stdout(), "Binary uploaded from file %s\n", filename)
diff --git a/tools/binary/impl_test.go b/tools/binary/impl_test.go
index 0f32f85..865c35d 100644
--- a/tools/binary/impl_test.go
+++ b/tools/binary/impl_test.go
@@ -27,7 +27,7 @@
 	suffix string
 }
 
-func (s *server) Create(ipc.ServerContext, int32) error {
+func (s *server) Create(ipc.ServerContext, int32, repository.MediaInfo) error {
 	vlog.Infof("Create() was called. suffix=%v", s.suffix)
 	return nil
 }
@@ -53,13 +53,13 @@
 	return "", 0, nil
 }
 
-func (s *server) Stat(ipc.ServerContext) ([]binary.PartInfo, error) {
+func (s *server) Stat(ipc.ServerContext) ([]binary.PartInfo, repository.MediaInfo, error) {
 	vlog.Infof("Stat() was called. suffix=%v", s.suffix)
 	h := md5.New()
 	text := "HelloWorld"
 	h.Write([]byte(text))
 	part := binary.PartInfo{Checksum: hex.EncodeToString(h.Sum(nil)), Size: int64(len(text))}
-	return []binary.PartInfo{part}, nil
+	return []binary.PartInfo{part}, repository.MediaInfo{Type: "text/plain"}, nil
 }
 
 func (s *server) Upload(ctx repository.BinaryUploadContext, _ int32) error {
@@ -107,7 +107,13 @@
 }
 
 func TestBinaryClient(t *testing.T) {
-	runtime := rt.Init()
+	var err error
+	runtime, err = rt.New()
+	if err != nil {
+		t.Fatalf("Unexpected error initializing runtime: %s", err)
+	}
+	defer runtime.Cleanup()
+
 	server, endpoint, err := startServer(t, runtime)
 	if err != nil {
 		return
diff --git a/tools/binary/main.go b/tools/binary/main.go
index 9e5d556..3723981 100644
--- a/tools/binary/main.go
+++ b/tools/binary/main.go
@@ -1,15 +1,23 @@
 // The following enables go generate to generate the doc.go file.
-//go:generate go run $VEYRON_ROOT/lib/cmdline/testdata/gendoc.go .
+//go:generate go run $VEYRON_ROOT/veyron/go/src/veyron.io/lib/cmdline/testdata/gendoc.go .
 
 package main
 
 import (
+	"veyron.io/veyron/veyron2"
 	"veyron.io/veyron/veyron2/rt"
 
 	_ "veyron.io/veyron/veyron/profiles"
 )
 
+var runtime veyron2.Runtime
+
 func main() {
-	defer rt.Init().Cleanup()
+	var err error
+	runtime, err = rt.New()
+	if err != nil {
+		panic(err)
+	}
+	defer runtime.Cleanup()
 	root().Main()
 }
diff --git a/tools/build/doc.go b/tools/build/doc.go
index 9d7fc7e..347c55a 100644
--- a/tools/build/doc.go
+++ b/tools/build/doc.go
@@ -13,49 +13,76 @@
 Run "build help [command]" for command usage.
 
 The global flags are:
-   -alsologtostderr=true: log to standard error as well as files
-   -log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
-   -log_dir=: if non-empty, write log files to this directory
-   -logtostderr=false: log to standard error instead of files
-   -max_stack_buf_size=4292608: max size in bytes of the buffer to use for logging stack traces
-   -stderrthreshold=2: logs at or above this threshold go to stderr
-   -v=0: log level for V logs
-   -vmodule=: comma-separated list of pattern=N settings for file-filtered logging
-   -vv=0: log level for V logs
+ -alsologtostderr=true
+   log to standard error as well as files
+ -log_backtrace_at=:0
+   when logging hits line file:N, emit a stack trace
+ -log_dir=
+   if non-empty, write log files to this directory
+ -logtostderr=false
+   log to standard error instead of files
+ -max_stack_buf_size=4292608
+   max size in bytes of the buffer to use for logging stack traces
+ -stderrthreshold=2
+   logs at or above this threshold go to stderr
+ -v=0
+   log level for V logs
+ -veyron.credentials=
+   directory to use for storing security credentials
+ -veyron.namespace.root=[/proxy.envyor.com:8101]
+   local namespace root; can be repeated to provided multiple roots
+ -veyron.vtrace.cache_size=1024
+   The number of vtrace traces to store in memory.
+ -veyron.vtrace.dump_on_shutdown=false
+   If true, dump all stored traces on runtime shutdown.
+ -veyron.vtrace.sample_rate=0
+   Rate (from 0.0 to 1.0) to sample vtrace traces.
+ -vmodule=
+   comma-separated list of pattern=N settings for file-filtered logging
 
 Build Build
 
-Build veyron Go packages using a remote build server. The command
-collects all source code files that are not part of the Go standard
-library that the target packages depend on, sends them to a build
-server, and receives the built binaries.
+Build veyron Go packages using a remote build server. The command collects all
+source code files that are not part of the Go standard library that the target
+packages depend on, sends them to a build server, and receives the built
+binaries.
 
 Usage:
    build build [flags] <name> <packages>
 
-<name> is a veyron object name of a build server
-<packages> is a list of packages to build, specified as arguments for
-each command. The format is similar to the go tool.  In its simplest
-form each package is an import path; e.g. "veyron/tools/build". A
-package that ends with "..." does a wildcard match against all
-packages with that prefix.
+<name> is a veyron object name of a build server <packages> is a list of
+packages to build, specified as arguments for each command. The format is
+similar to the go tool.  In its simplest form each package is an import path;
+e.g. "veyron/tools/build". A package that ends with "..." does a wildcard match
+against all packages with that prefix.
 
-The build flags are:
-   -arch=amd64: Target architecture.
-   -os=linux: Target operating system.
+The build build flags are:
+ -arch=amd64
+   Target architecture.
+ -os=darwin
+   Target operating system.
 
 Build Help
 
 Help with no args displays the usage of the parent command.
+
 Help with args displays the usage of the specified sub-command or help topic.
+
 "help ..." recursively displays help for all commands and topics.
 
+The output is formatted to a target width in runes.  The target width is
+determined by checking the environment variable CMDLINE_WIDTH, falling back on
+the terminal width from the OS, falling back on 80 chars.  By setting
+CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
+if x == 0 or is unset one of the fallbacks is used.
+
 Usage:
    build help [flags] [command/topic ...]
 
 [command/topic ...] optionally identifies a specific sub-command or help topic.
 
-The help flags are:
-   -style=text: The formatting style for help output, either "text" or "godoc".
+The build help flags are:
+ -style=text
+   The formatting style for help output, either "text" or "godoc".
 */
 package main
diff --git a/tools/build/impl.go b/tools/build/impl.go
index a4b9b87..e03779f 100644
--- a/tools/build/impl.go
+++ b/tools/build/impl.go
@@ -6,13 +6,12 @@
 	"io/ioutil"
 	"os"
 	"path/filepath"
-	"runtime"
+	goruntime "runtime"
 	"strings"
 	"time"
 
 	"veyron.io/lib/cmdline"
 	"veyron.io/veyron/veyron2/context"
-	"veyron.io/veyron/veyron2/rt"
 	vbuild "veyron.io/veyron/veyron2/services/mgmt/build"
 )
 
@@ -22,8 +21,8 @@
 )
 
 func init() {
-	cmdBuild.Flags.StringVar(&flagArch, "arch", runtime.GOARCH, "Target architecture.")
-	cmdBuild.Flags.StringVar(&flagOS, "os", runtime.GOOS, "Target operating system.")
+	cmdBuild.Flags.StringVar(&flagArch, "arch", goruntime.GOARCH, "Target architecture.")
+	cmdBuild.Flags.StringVar(&flagOS, "os", goruntime.GOOS, "Target operating system.")
 }
 
 var cmdRoot = &cmdline.Command{
@@ -140,7 +139,6 @@
 	binaries := make(chan vbuild.File)
 	go func() {
 		defer close(binaries)
-		rt.Init()
 		client := vbuild.BuilderClient(name)
 		stream, err := client.Build(ctx, vbuild.Architecture(flagArch), vbuild.OperatingSystem(flagOS))
 		if err != nil {
@@ -211,7 +209,7 @@
 	cancel, errchan := make(chan struct{}), make(chan error)
 	defer close(errchan)
 
-	ctx, ctxCancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ctx, ctxCancel := runtime.NewContext().WithTimeout(time.Minute)
 	defer ctxCancel()
 
 	// Start all stages of the pipeline.
diff --git a/tools/build/impl_test.go b/tools/build/impl_test.go
index 2778896..4f4d3f7 100644
--- a/tools/build/impl_test.go
+++ b/tools/build/impl_test.go
@@ -5,6 +5,7 @@
 	"strings"
 	"testing"
 
+	"veyron.io/veyron/veyron2"
 	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/rt"
@@ -39,8 +40,8 @@
 
 type dispatcher struct{}
 
-func startServer(t *testing.T) (ipc.Server, naming.Endpoint) {
-	server, err := rt.R().NewServer()
+func startServer(runtime veyron2.Runtime, t *testing.T) (ipc.Server, naming.Endpoint) {
+	server, err := runtime.NewServer()
 	if err != nil {
 		t.Fatalf("NewServer failed: %v", err)
 	}
@@ -62,8 +63,12 @@
 }
 
 func TestBuildClient(t *testing.T) {
-	rt.Init()
-	server, endpoint := startServer(t)
+	var err error
+	runtime, err = rt.New()
+	if err != nil {
+		t.Fatalf("Unexpected error initializing runtime: %s", err)
+	}
+	server, endpoint := startServer(runtime, t)
 	defer stopServer(t, server)
 
 	cmd := root()
diff --git a/tools/build/main.go b/tools/build/main.go
index 9e5d556..3723981 100644
--- a/tools/build/main.go
+++ b/tools/build/main.go
@@ -1,15 +1,23 @@
 // The following enables go generate to generate the doc.go file.
-//go:generate go run $VEYRON_ROOT/lib/cmdline/testdata/gendoc.go .
+//go:generate go run $VEYRON_ROOT/veyron/go/src/veyron.io/lib/cmdline/testdata/gendoc.go .
 
 package main
 
 import (
+	"veyron.io/veyron/veyron2"
 	"veyron.io/veyron/veyron2/rt"
 
 	_ "veyron.io/veyron/veyron/profiles"
 )
 
+var runtime veyron2.Runtime
+
 func main() {
-	defer rt.Init().Cleanup()
+	var err error
+	runtime, err = rt.New()
+	if err != nil {
+		panic(err)
+	}
+	defer runtime.Cleanup()
 	root().Main()
 }
diff --git a/tools/debug/doc.go b/tools/debug/doc.go
index e611553..ded0837 100644
--- a/tools/debug/doc.go
+++ b/tools/debug/doc.go
@@ -8,7 +8,8 @@
    debug <command>
 
 The debug commands are:
-   glob        Returns all matching entries from the namespace
+   glob        Returns all matching entries from the namespace.
+   vtrace      Returns vtrace traces.
    logs        Accesses log files
    stats       Accesses stats
    pprof       Accesses profiling data
@@ -16,15 +17,32 @@
 Run "debug help [command]" for command usage.
 
 The global flags are:
-   -alsologtostderr=true: log to standard error as well as files
-   -log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
-   -log_dir=: if non-empty, write log files to this directory
-   -logtostderr=false: log to standard error instead of files
-   -max_stack_buf_size=4292608: max size in bytes of the buffer to use for logging stack traces
-   -stderrthreshold=2: logs at or above this threshold go to stderr
-   -v=0: log level for V logs
-   -vmodule=: comma-separated list of pattern=N settings for file-filtered logging
-   -vv=0: log level for V logs
+ -alsologtostderr=true
+   log to standard error as well as files
+ -log_backtrace_at=:0
+   when logging hits line file:N, emit a stack trace
+ -log_dir=
+   if non-empty, write log files to this directory
+ -logtostderr=false
+   log to standard error instead of files
+ -max_stack_buf_size=4292608
+   max size in bytes of the buffer to use for logging stack traces
+ -stderrthreshold=2
+   logs at or above this threshold go to stderr
+ -v=0
+   log level for V logs
+ -veyron.credentials=
+   directory to use for storing security credentials
+ -veyron.namespace.root=[/proxy.envyor.com:8101]
+   local namespace root; can be repeated to provided multiple roots
+ -veyron.vtrace.cache_size=1024
+   The number of vtrace traces to store in memory.
+ -veyron.vtrace.dump_on_shutdown=false
+   If true, dump all stored traces on runtime shutdown.
+ -veyron.vtrace.sample_rate=0
+   Rate (from 0.0 to 1.0) to sample vtrace traces.
+ -vmodule=
+   comma-separated list of pattern=N settings for file-filtered logging
 
 Debug Glob
 
@@ -35,6 +53,15 @@
 
 <pattern> is a glob pattern to match.
 
+Debug Vtrace
+
+Returns matching vtrace traces (or all stored traces if no ids are given).
+
+Usage:
+   debug vtrace <name> [id ...]
+
+<name> is the name of a vtrace object. [id] is a vtrace trace id.
+
 Debug Logs
 
 Accesses log files
@@ -42,9 +69,9 @@
 Usage:
    debug logs <command>
 
-The logs commands are:
+The debug logs commands are:
    read        Reads the content of a log file object.
-   size        Returns the size of the a log file object
+   size        Returns the size of a log file object.
 
 Debug Logs Read
 
@@ -55,15 +82,20 @@
 
 <name> is the name of the log file object.
 
-The read flags are:
-   -f=false: When true, read will wait for new log entries when it reaches the end of the file.
-   -n=-1: The number of log entries to read.
-   -o=0: The position, in bytes, from which to start reading the log file.
-   -v=false: When true, read will be more verbose.
+The debug logs read flags are:
+ -f=false
+   When true, read will wait for new log entries when it reaches the end of the
+   file.
+ -n=-1
+   The number of log entries to read.
+ -o=0
+   The position, in bytes, from which to start reading the log file.
+ -v=false
+   When true, read will be more verbose.
 
 Debug Logs Size
 
-Returns the size of the a log file object.
+Returns the size of a log file object.
 
 Usage:
    debug logs size <name>
@@ -77,35 +109,41 @@
 Usage:
    debug stats <command>
 
-The stats commands are:
-   value       Returns the value of the a stats object
-   watchglob   Returns a stream of all matching entries and their values
+The debug stats commands are:
+   read        Returns the value of stats objects.
+   watch       Returns a stream of all matching entries and their values as they
+               change.
 
-Debug Stats Value
+Debug Stats Read
 
-Returns the value of the a stats object.
+Returns the value of stats objects.
 
 Usage:
-   debug stats value [flags] <name>
+   debug stats read [flags] <name> ...
 
-<name> is the name of the stats object.
+<name> is the name of a stats object, or a glob pattern to match against stats
+object names.
 
-The value flags are:
-   -raw=false: When true, the command will display the raw value of the object.
-   -type=false: When true, the type of the values will be displayed.
+The debug stats read flags are:
+ -raw=false
+   When true, the command will display the raw value of the object.
+ -type=false
+   When true, the type of the values will be displayed.
 
-Debug Stats Watchglob
+Debug Stats Watch
 
-Returns a stream of all matching entries and their values
+Returns a stream of all matching entries and their values as they change.
 
 Usage:
-   debug stats watchglob [flags] <pattern> ...
+   debug stats watch [flags] <pattern> ...
 
 <pattern> is a glob pattern to match.
 
-The watchglob flags are:
-   -raw=false: When true, the command will display the raw value of the object.
-   -type=false: When true, the type of the values will be displayed.
+The debug stats watch flags are:
+ -raw=false
+   When true, the command will display the raw value of the object.
+ -type=false
+   When true, the type of the values will be displayed.
 
 Debug Pprof
 
@@ -114,31 +152,31 @@
 Usage:
    debug pprof <command>
 
-The pprof commands are:
-   run         Runs the pprof tool
-   proxy       Runs an http proxy to a pprof object
+The debug pprof commands are:
+   run         Runs the pprof tool.
+   proxy       Runs an http proxy to a pprof object.
 
 Debug Pprof Run
 
-Runs the pprof tool
+Runs the pprof tool.
 
 Usage:
    debug pprof run [flags] <name> <profile> [passthru args] ...
 
-<name> is the name of the pprof object.
-<profile> the name of the profile to use.
+<name> is the name of the pprof object. <profile> the name of the profile to
+use.
 
 All the [passthru args] are passed to the pprof tool directly, e.g.
 
-$ debug pprof run a/b/c heap --text --lines
-$ debug pprof run a/b/c profile -gv
+$ debug pprof run a/b/c heap --text $ debug pprof run a/b/c profile -gv
 
-The run flags are:
-   -pprofcmd=veyron go tool pprof: The pprof command to use.
+The debug pprof run flags are:
+ -pprofcmd=veyron go tool pprof
+   The pprof command to use.
 
 Debug Pprof Proxy
 
-Runs an http proxy to a pprof object
+Runs an http proxy to a pprof object.
 
 Usage:
    debug pprof proxy <name>
@@ -148,15 +186,24 @@
 Debug Help
 
 Help with no args displays the usage of the parent command.
+
 Help with args displays the usage of the specified sub-command or help topic.
+
 "help ..." recursively displays help for all commands and topics.
 
+The output is formatted to a target width in runes.  The target width is
+determined by checking the environment variable CMDLINE_WIDTH, falling back on
+the terminal width from the OS, falling back on 80 chars.  By setting
+CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
+if x == 0 or is unset one of the fallbacks is used.
+
 Usage:
    debug help [flags] [command/topic ...]
 
 [command/topic ...] optionally identifies a specific sub-command or help topic.
 
-The help flags are:
-   -style=text: The formatting style for help output, either "text" or "godoc".
+The debug help flags are:
+ -style=text
+   The formatting style for help output, either "text" or "godoc".
 */
 package main
diff --git a/tools/debug/impl.go b/tools/debug/impl.go
index f3dc121..6a5a1fa 100644
--- a/tools/debug/impl.go
+++ b/tools/debug/impl.go
@@ -3,7 +3,6 @@
 import (
 	"bytes"
 	"fmt"
-	"io"
 	"os"
 	"os/exec"
 	"regexp"
@@ -19,14 +18,16 @@
 	istats "veyron.io/veyron/veyron/services/mgmt/stats"
 	"veyron.io/veyron/veyron2/context"
 	"veyron.io/veyron/veyron2/naming"
-	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/services/mgmt/logreader"
 	logtypes "veyron.io/veyron/veyron2/services/mgmt/logreader/types"
 	"veyron.io/veyron/veyron2/services/mgmt/pprof"
 	"veyron.io/veyron/veyron2/services/mgmt/stats"
+	vtracesvc "veyron.io/veyron/veyron2/services/mgmt/vtrace"
 	"veyron.io/veyron/veyron2/services/watch"
 	watchtypes "veyron.io/veyron/veyron2/services/watch/types"
-	"veyron.io/veyron/veyron2/vom"
+	"veyron.io/veyron/veyron2/uniqueid"
+	"veyron.io/veyron/veyron2/vdl/vdlutil"
+	"veyron.io/veyron/veyron2/vtrace"
 )
 
 var (
@@ -40,7 +41,7 @@
 )
 
 func init() {
-	vom.Register(istats.HistogramValue{})
+	vdlutil.Register(istats.HistogramValue{})
 
 	// logs read flags
 	cmdLogsRead.Flags.BoolVar(&follow, "f", false, "When true, read will wait for new log entries when it reaches the end of the file.")
@@ -60,6 +61,81 @@
 	cmdPProfRun.Flags.StringVar(&pprofCmd, "pprofcmd", "veyron go tool pprof", "The pprof command to use.")
 }
 
+var cmdVtrace = &cmdline.Command{
+	Run:      runVtrace,
+	Name:     "vtrace",
+	Short:    "Returns vtrace traces.",
+	Long:     "Returns matching vtrace traces (or all stored traces if no ids are given).",
+	ArgsName: "<name> [id ...]",
+	ArgsLong: `
+<name> is the name of a vtrace object.
+[id] is a vtrace trace id.
+`,
+}
+
+func doFetchTrace(ctx context.T, wg *sync.WaitGroup, client vtracesvc.StoreClientStub,
+	id uniqueid.ID, traces chan *vtrace.TraceRecord, errors chan error) {
+	defer wg.Done()
+
+	trace, err := client.Trace(ctx, id)
+	if err != nil {
+		errors <- err
+	} else {
+		traces <- &trace
+	}
+}
+
+func runVtrace(cmd *cmdline.Command, args []string) error {
+	ctx := runtime.NewContext()
+	arglen := len(args)
+	if arglen == 0 {
+		return cmd.UsageErrorf("vtrace: incorrect number of arguments, got %d want >= 1", arglen)
+	}
+
+	name := args[0]
+	client := vtracesvc.StoreClient(name)
+	if arglen == 1 {
+		call, err := client.AllTraces(ctx)
+		if err != nil {
+			return err
+		}
+		stream := call.RecvStream()
+		for stream.Advance() {
+			trace := stream.Value()
+			vtrace.FormatTrace(os.Stdout, &trace, nil)
+		}
+		if err := stream.Err(); err != nil {
+			return err
+		}
+		return call.Finish()
+	}
+
+	ntraces := len(args) - 1
+	traces := make(chan *vtrace.TraceRecord, ntraces)
+	errors := make(chan error, ntraces)
+	var wg sync.WaitGroup
+	wg.Add(ntraces)
+	for _, arg := range args[1:] {
+		id, err := uniqueid.FromHexString(arg)
+		if err != nil {
+			return err
+		}
+		go doFetchTrace(ctx, &wg, client, id, traces, errors)
+	}
+	go func() {
+		wg.Wait()
+		close(traces)
+		close(errors)
+	}()
+
+	for trace := range traces {
+		vtrace.FormatTrace(os.Stdout, trace, nil)
+	}
+
+	// Just return one of the errors.
+	return <-errors
+}
+
 var cmdGlob = &cmdline.Command{
 	Run:      runGlob,
 	Name:     "glob",
@@ -77,7 +153,7 @@
 	}
 	results := make(chan naming.MountEntry)
 	errors := make(chan error)
-	doGlobs(rt.R().NewContext(), args, results, errors)
+	doGlobs(runtime.NewContext(), args, results, errors)
 	var lastErr error
 	for {
 		select {
@@ -116,7 +192,7 @@
 	defer wg.Done()
 	ctx, cancel := ctx.WithTimeout(time.Minute)
 	defer cancel()
-	c, err := rt.R().Namespace().Glob(ctx, pattern)
+	c, err := runtime.Namespace().Glob(ctx, pattern)
 	if err != nil {
 		errors <- fmt.Errorf("%s: %v", pattern, err)
 		return
@@ -143,7 +219,7 @@
 	}
 	name := args[0]
 	lf := logreader.LogFileClient(name)
-	stream, err := lf.ReadLog(rt.R().NewContext(), startPos, int32(numEntries), follow)
+	stream, err := lf.ReadLog(runtime.NewContext(), startPos, int32(numEntries), follow)
 	if err != nil {
 		return err
 	}
@@ -186,7 +262,7 @@
 	}
 	name := args[0]
 	lf := logreader.LogFileClient(name)
-	size, err := lf.Size(rt.R().NewContext())
+	size, err := lf.Size(runtime.NewContext())
 	if err != nil {
 		return err
 	}
@@ -210,7 +286,7 @@
 	if min, got := 1, len(args); got < min {
 		return cmd.UsageErrorf("read: incorrect number of arguments, got %d, want >=%d", got, min)
 	}
-	ctx := rt.R().NewContext()
+	ctx := runtime.NewContext()
 	globResults := make(chan naming.MountEntry)
 	errors := make(chan error)
 	doGlobs(ctx, args, globResults, errors)
@@ -271,7 +347,7 @@
 
 	results := make(chan string)
 	errors := make(chan error)
-	ctx := rt.R().NewContext()
+	ctx := runtime.NewContext()
 	var wg sync.WaitGroup
 	wg.Add(len(args))
 	for _, arg := range args {
@@ -346,40 +422,13 @@
 	}
 	switch v := value.(type) {
 	case istats.HistogramValue:
-		writeASCIIHistogram(&buf, v)
+		v.Print(&buf)
 	default:
 		fmt.Fprintf(&buf, "%v", v)
 	}
 	return buf.String()
 }
 
-func writeASCIIHistogram(w io.Writer, h istats.HistogramValue) {
-	scale := h.Count
-	if scale > 100 {
-		scale = 100
-	}
-	var avg float64
-	if h.Count > 0 {
-		avg = float64(h.Sum) / float64(h.Count)
-	}
-	fmt.Fprintf(w, "Count: %d Sum: %d Avg: %f\n", h.Count, h.Sum, avg)
-	for i, b := range h.Buckets {
-		var r string
-		if i+1 < len(h.Buckets) {
-			r = fmt.Sprintf("[%d,%d[", b.LowBound, h.Buckets[i+1].LowBound)
-		} else {
-			r = fmt.Sprintf("[%d,Inf", b.LowBound)
-		}
-		fmt.Fprintf(w, "%-18s: ", r)
-		if b.Count > 0 && h.Count > 0 {
-			fmt.Fprintf(w, "%s %d (%.1f%%)", strings.Repeat("*", int(b.Count*scale/h.Count)), b.Count, 100*float64(b.Count)/float64(h.Count))
-		}
-		if i+1 < len(h.Buckets) {
-			fmt.Fprintln(w)
-		}
-	}
-}
-
 var cmdPProfRun = &cmdline.Command{
 	Run:      runPProf,
 	Name:     "run",
@@ -406,7 +455,7 @@
 		return showPProfProfiles(cmd, name)
 	}
 	profile := args[1]
-	listener, err := client.StartProxy(rt.R(), name)
+	listener, err := client.StartProxy(runtime, name)
 	if err != nil {
 		return err
 	}
@@ -429,7 +478,7 @@
 }
 
 func showPProfProfiles(cmd *cmdline.Command, name string) error {
-	v, err := pprof.PProfClient(name).Profiles(rt.R().NewContext())
+	v, err := pprof.PProfClient(name).Profiles(runtime.NewContext())
 	if err != nil {
 		return err
 	}
@@ -466,7 +515,7 @@
 		return cmd.UsageErrorf("proxy: incorrect number of arguments, got %d, want %d", got, want)
 	}
 	name := args[0]
-	listener, err := client.StartProxy(rt.R(), name)
+	listener, err := client.StartProxy(runtime, name)
 	if err != nil {
 		return err
 	}
@@ -477,7 +526,7 @@
 	fmt.Fprintln(cmd.Stdout())
 	fmt.Fprintln(cmd.Stdout(), "Hit CTRL-C to exit")
 
-	<-signals.ShutdownOnSignals()
+	<-signals.ShutdownOnSignals(runtime)
 	return nil
 }
 
@@ -487,6 +536,7 @@
 	Long:  "Command-line tool for interacting with the debug server.",
 	Children: []*cmdline.Command{
 		cmdGlob,
+		cmdVtrace,
 		&cmdline.Command{
 			Name:     "logs",
 			Short:    "Accesses log files",
diff --git a/tools/debug/main.go b/tools/debug/main.go
index 9e5d556..3723981 100644
--- a/tools/debug/main.go
+++ b/tools/debug/main.go
@@ -1,15 +1,23 @@
 // The following enables go generate to generate the doc.go file.
-//go:generate go run $VEYRON_ROOT/lib/cmdline/testdata/gendoc.go .
+//go:generate go run $VEYRON_ROOT/veyron/go/src/veyron.io/lib/cmdline/testdata/gendoc.go .
 
 package main
 
 import (
+	"veyron.io/veyron/veyron2"
 	"veyron.io/veyron/veyron2/rt"
 
 	_ "veyron.io/veyron/veyron/profiles"
 )
 
+var runtime veyron2.Runtime
+
 func main() {
-	defer rt.Init().Cleanup()
+	var err error
+	runtime, err = rt.New()
+	if err != nil {
+		panic(err)
+	}
+	defer runtime.Cleanup()
 	root().Main()
 }
diff --git a/tools/debug/test.sh b/tools/debug/test.sh
index 8c38207..17a016b 100755
--- a/tools/debug/test.sh
+++ b/tools/debug/test.sh
@@ -8,6 +8,7 @@
 source "${VEYRON_ROOT}/scripts/lib/shell_test.sh"
 
 readonly WORKDIR="${shell_test_WORK_DIR}"
+readonly DEBUG_FLAGS="--veyron.vtrace.sample_rate=1"
 
 build() {
   DEBUG_BIN="$(shell_test::build_go_binary 'veyron.io/veyron/veyron/tools/debug')"
@@ -35,7 +36,7 @@
 
   # Test top level glob.
   local -r DBGLOG="${WORKDIR}/debug.log"
-  GOT=$("${DEBUG_BIN}" glob "${EP}/__debug/*" 2> "${DBGLOG}") \
+  GOT=$("${DEBUG_BIN}" "${DEBUG_FLAGS}" glob "${EP}/__debug/*" 2> "${DBGLOG}") \
     || (dumplogs "${DBGLOG}"; shell_test::fail "line ${LINENO}: failed to run debug")
   WANT="${EP}/__debug/logs
 ${EP}/__debug/pprof
@@ -44,28 +45,39 @@
   shell_test::assert_eq "${GOT}" "${WANT}" "${LINENO}"
 
   # Test logs glob.
-  GOT=$("${DEBUG_BIN}" glob "${EP}/__debug/logs/*" 2> "${DBGLOG}" | wc -l) \
+  GOT=$("${DEBUG_BIN}" "${DEBUG_FLAGS}" glob "${EP}/__debug/logs/*" 2> "${DBGLOG}" | wc -l) \
     || (dumplogs "${DBGLOG}"; shell_test::fail "line ${LINENO}: failed to run debug")
   shell_test::assert_gt "${GOT}" "0" "${LINENO}"
 
   # Test logs size.
   echo "This is a log file" > "${TMPDIR}/my-test-log-file"
-  GOT=$("${DEBUG_BIN}" logs size "${EP}/__debug/logs/my-test-log-file" 2> "${DBGLOG}") \
+  GOT=$("${DEBUG_BIN}" "${DEBUG_FLAGS}" logs size "${EP}/__debug/logs/my-test-log-file" 2> "${DBGLOG}") \
     || (dumplogs "${DBGLOG}"; shell_test::fail "line ${LINENO}: failed to run debug")
   WANT=$(echo "This is a log file" | wc -c | tr -d ' ')
   shell_test::assert_eq "${GOT}" "${WANT}" "${LINENO}"
 
   # Test logs read.
-  GOT=$("${DEBUG_BIN}" logs read "${EP}/__debug/logs/my-test-log-file" 2> "${DBGLOG}") \
+  GOT=$("${DEBUG_BIN}" "${DEBUG_FLAGS}" logs read "${EP}/__debug/logs/my-test-log-file" 2> "${DBGLOG}") \
     || (dumplogs "${DBGLOG}"; shell_test::fail "line ${LINENO}: failed to run debug")
   WANT="This is a log file"
   shell_test::assert_eq "${GOT}" "${WANT}" "${LINENO}"
 
   # Test stats read.
-  GOT=$("${DEBUG_BIN}" stats read "${EP}/__debug/stats/ipc/server/routing-id/*/methods/ReadLog/latency-ms" 2> "${DBGLOG}" | wc -l) \
+  GOT=$("${DEBUG_BIN}" "${DEBUG_FLAGS}" stats read "${EP}/__debug/stats/ipc/server/routing-id/*/methods/ReadLog/latency-ms" 2> "${DBGLOG}" | wc -l) \
     || (dumplogs "${DBGLOG}"; shell_test::fail "line ${LINENO}: failed to run debug")
   shell_test::assert_gt "${GOT}" "0" "${LINENO}"
 
+  # Test fetching all vtrace traces.
+  GOT=$("${DEBUG_BIN}" "${DEBUG_FLAGS}" vtrace "${EP}/__debug/vtrace" 2> "${DBGLOG}" | egrep -o "^Trace - ([^ ]+)" | cut -b 9- | sort) \
+    || (dumplogs "${DBGLOG}"; shell_test::fail "line ${LINENO}: failed to run debug")
+  shell_test::assert_eq $(echo "${GOT}" | wc -l | tr -d ' ') "6" "${LINENO}"
+
+  # Test fetching individual traces.
+  IDS=$(echo "$GOT" | tr '\n' ' ')
+  GOT2=$("${DEBUG_BIN}" "${DEBUG_FLAGS}" vtrace "${EP}/__debug/vtrace" ${IDS}  2> "${DBGLOG}" | egrep -o "^Trace - ([^ ]+)" | cut -b 9- | sort) \
+    || (dumplogs "${DBGLOG}"; shell_test::fail "line ${LINENO}: failed to run debug")
+  shell_test::assert_eq "${GOT2}" "${GOT}" "${LINENO}"
+
   # Test stats watch.
   local TMP=$(shell::tmp_file)
   touch "${TMP}"
@@ -73,7 +85,7 @@
     "${DEBUG_BIN}" stats watch -raw "${EP}/__debug/stats/ipc/server/routing-id/*/methods/ReadLog/latency-ms")
   shell::timed_wait_for "${shell_test_DEFAULT_MESSAGE_TIMEOUT}" "${TMP}" "ReadLog/latency-ms"
   kill "${DEBUG_PID}"
-  grep -q "Count:1 " "${TMP}" || (dumplogs "${TMP}"; shell_test::fail "line ${LINENO}: failed to find expected output")
+  grep -q "Count: 1 " "${TMP}" || (dumplogs "${TMP}"; shell_test::fail "line ${LINENO}: failed to find expected output")
 
   # Test pprof.
   if ! "${DEBUG_BIN}" pprof run "${EP}/__debug/pprof" heap --text &> "${DBGLOG}"; then
diff --git a/tools/mgmt/nodex/acl_fmt.go b/tools/mgmt/nodex/acl_fmt.go
new file mode 100644
index 0000000..1690edd
--- /dev/null
+++ b/tools/mgmt/nodex/acl_fmt.go
@@ -0,0 +1,84 @@
+package main
+
+import (
+	"fmt"
+	"sort"
+	"strings"
+
+	"veyron.io/veyron/veyron2/security"
+)
+
+// aclEntries maps blessing patterns to the kind of access they should have.
+type aclEntries map[string]accessTags
+
+// accessTags maps access tags to whether they should be blacklisted
+// (i.e., part of the NotIn list) or not (part of the In list).
+//
+// TODO(ashankar,caprita): This structure is not friendly to a blessing
+// appearing in both the "In" and "NotIn" lists of an ACL. Arguably, such an
+// ACL is silly (In: ["foo"], NotIn: ["foo"]), but is legal. This structure can
+// end up hiding that.
+type accessTags map[string]bool
+
+// String representation of access tags.  Between String and parseAccessTags,
+// the "get" and "set" commands are able to speak the same language: the output
+// of "get" and be copied/pasted into "set".
+func (tags accessTags) String() string {
+	// Sort tags and then apply "!".
+	var list []string
+	for tag, _ := range tags {
+		list = append(list, tag)
+	}
+	sort.Strings(list)
+	for ix, tag := range list {
+		if tags[tag] {
+			list[ix] = "!" + list[ix]
+		}
+	}
+	return strings.Join(list, ",")
+}
+
+func parseAccessTags(input string) (accessTags, error) {
+	ret := make(accessTags)
+	if input == "^" {
+		return ret, nil
+	}
+	for _, tag := range strings.Split(input, ",") {
+		blacklist := strings.HasPrefix(tag, "!")
+		if blacklist {
+			tag = tag[1:]
+		}
+		if len(tag) == 0 {
+			return nil, fmt.Errorf("empty access tag in %q", input)
+		}
+		ret[tag] = blacklist
+	}
+	return ret, nil
+}
+
+func (entries aclEntries) String() string {
+	var list []string
+	for pattern, _ := range entries {
+		list = append(list, pattern)
+	}
+	sort.Strings(list)
+	for ix, pattern := range list {
+		list[ix] = fmt.Sprintf("%s %v", pattern, entries[pattern])
+	}
+	return strings.Join(list, "\n")
+}
+
+func (entries aclEntries) Tags(pattern string) accessTags {
+	tags, exists := entries[pattern]
+	if !exists {
+		tags = make(accessTags)
+		entries[pattern] = tags
+	}
+	return tags
+}
+
+type byPattern []security.BlessingPattern
+
+func (a byPattern) Len() int           { return len(a) }
+func (a byPattern) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a byPattern) Less(i, j int) bool { return a[i] < a[j] }
diff --git a/tools/mgmt/nodex/acl_impl.go b/tools/mgmt/nodex/acl_impl.go
index ca2b0a9..e9d2f7c 100644
--- a/tools/mgmt/nodex/acl_impl.go
+++ b/tools/mgmt/nodex/acl_impl.go
@@ -4,7 +4,6 @@
 
 import (
 	"fmt"
-	"sort"
 
 	"veyron.io/lib/cmdline"
 	"veyron.io/veyron/veyron2/rt"
@@ -25,19 +24,6 @@
 application installation or instance.`,
 }
 
-type formattedACLEntry struct {
-	blessing string
-	inout    string
-	label    string
-}
-
-// Code to make formattedACLEntry sorted.
-type byBlessing []formattedACLEntry
-
-func (a byBlessing) Len() int           { return len(a) }
-func (a byBlessing) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
-func (a byBlessing) Less(i, j int) bool { return a[i].blessing < a[j].blessing }
-
 func runGet(cmd *cmdline.Command, args []string) error {
 	if expected, got := 1, len(args); expected != got {
 		return cmd.UsageErrorf("get: incorrect number of arguments, expected %d, got %d", expected, got)
@@ -48,21 +34,17 @@
 	if err != nil {
 		return fmt.Errorf("GetACL on %s failed: %v", vanaName, err)
 	}
-
-	// TODO(rjkroege): Update for custom labels.
-	output := make([]formattedACLEntry, 0)
-	for k, _ := range objACL.In {
-		output = append(output, formattedACLEntry{string(k), "", objACL.In[k].String()})
+	// Convert objACL (TaggedACLMap) into aclEntries for pretty printing.
+	entries := make(aclEntries)
+	for tag, acl := range objACL {
+		for _, p := range acl.In {
+			entries.Tags(string(p))[tag] = false
+		}
+		for _, b := range acl.NotIn {
+			entries.Tags(b)[tag] = true
+		}
 	}
-	for k, _ := range objACL.NotIn {
-		output = append(output, formattedACLEntry{string(k), "!", objACL.NotIn[k].String()})
-	}
-
-	sort.Sort(byBlessing(output))
-
-	for _, e := range output {
-		fmt.Fprintf(cmd.Stdout(), "%s %s%s\n", e.blessing, e.inout, e.label)
-	}
+	fmt.Fprintf(cmd.Stdout(), "%v", entries)
 	return nil
 }
 
@@ -71,32 +53,28 @@
 	Name:     "set",
 	Short:    "Set ACLs for the given target.",
 	Long:     "Set ACLs for the given target",
-	ArgsName: "<node manager name>  (<blessing> [!]<label>)...",
+	ArgsName: "<node manager name>  (<blessing> [!]<tag>(,[!]<tag>)*",
 	ArgsLong: `
 <node manager name> can be a Vanadium name for a node manager,
 application installation or instance.
 
 <blessing> is a blessing pattern.
+If the same pattern is repeated multiple times in the command, then
+the only the last occurrence will be honored.
 
-<label> is a character sequence defining a set of rights: some subset
-of the defined standard Vanadium labels of XRWADM where X is resolve,
-R is read, W for write, A for admin, D for debug and M is for
-monitoring. By default, the combination of <blessing>, <label>
-replaces whatever entry is present in the ACL's In field for the
-<blessing> but it can instead be added to the NotIn field by prefacing
-<label> with a '!' character. Use the <label> of 0 to clear the label.
+<tag> is a subset of defined access types ("Admin", "Read", "Write" etc.).
+If the access right is prefixed with a '!' then <blessing> is added to the
+NotIn list for that right. Using "^" as a "tag" causes all occurrences of
+<blessing> in the current ACL to be cleared.
 
-For example: root/self !0 will clear the NotIn field for blessingroot/self.`,
-}
+Examples:
+set root/self ^
+will remove "root/self" from the In and NotIn lists for all access rights.
 
-type inAdditionTuple struct {
-	blessing security.BlessingPattern
-	ls       *security.LabelSet
-}
-
-type notInAdditionTuple struct {
-	blessing string
-	ls       *security.LabelSet
+set root/self Read,!Write
+will add "root/self" to the In list for Read access and the NotIn list
+for Write access (and remove "root/self" from both the In and NotIn
+lists of all other access rights)`,
 }
 
 func runSet(cmd *cmdline.Command, args []string) error {
@@ -107,70 +85,32 @@
 	vanaName := args[0]
 	pairs := args[1:]
 
-	// Parse each pair and aggregate what should happen to all of them
-	notInDeletions := make([]string, 0)
-	inDeletions := make([]security.BlessingPattern, 0)
-	inAdditions := make([]inAdditionTuple, 0)
-	notInAdditions := make([]notInAdditionTuple, 0)
-
+	entries := make(aclEntries)
 	for i := 0; i < len(pairs); i += 2 {
-		blessing, label := pairs[i], pairs[i+1]
-		if label == "" || label == "!" {
-			return cmd.UsageErrorf("failed to parse LabelSet pair %s, %s", blessing, label)
+		blessing := pairs[i]
+		tags, err := parseAccessTags(pairs[i+1])
+		if err != nil {
+			return cmd.UsageErrorf("failed to parse access tags for %q: %v", blessing, err)
 		}
-
-		switch {
-		case label == "!0":
-			notInDeletions = append(notInDeletions, blessing)
-		case label == "0":
-			inDeletions = append(inDeletions, security.BlessingPattern(blessing))
-		case label[0] == '!':
-			// e.g. !RW
-			ls := new(security.LabelSet)
-			if err := ls.FromString(label[1:]); err != nil {
-				return cmd.UsageErrorf("failed to parse LabelSet %s:  %v", label, err)
-			}
-			notInAdditions = append(notInAdditions, notInAdditionTuple{blessing, ls})
-		default:
-			// e.g. X
-			ls := new(security.LabelSet)
-			if err := ls.FromString(label); err != nil {
-				return fmt.Errorf("failed to parse LabelSet %s:  %v", label, err)
-			}
-			inAdditions = append(inAdditions, inAdditionTuple{security.BlessingPattern(blessing), ls})
-		}
+		entries[blessing] = tags
 	}
 
-	// Set the ACLs on the specified name.
+	// Set the ACLs on the specified names.
 	for {
 		objACL, etag, err := node.ApplicationClient(vanaName).GetACL(rt.R().NewContext())
 		if err != nil {
 			return cmd.UsageErrorf("GetACL(%s) failed: %v", vanaName, err)
 		}
-
-		// Insert into objACL
-		for _, b := range notInDeletions {
-			if _, contains := objACL.NotIn[b]; !contains {
-				fmt.Fprintf(cmd.Stderr(), "WARNING: ignoring attempt to remove non-existing NotIn ACL for %s\n", b)
+		for blessingOrPattern, tags := range entries {
+			objACL.Clear(blessingOrPattern) // Clear out any existing references
+			for tag, blacklist := range tags {
+				if blacklist {
+					objACL.Blacklist(blessingOrPattern, tag)
+				} else {
+					objACL.Add(security.BlessingPattern(blessingOrPattern), tag)
+				}
 			}
-			delete(objACL.NotIn, b)
 		}
-
-		for _, b := range inDeletions {
-			if _, contains := objACL.In[b]; !contains {
-				fmt.Fprintf(cmd.Stderr(), "WARNING: ignoring attempt to remove non-existing In ACL for %s\n", b)
-			}
-			delete(objACL.In, b)
-		}
-
-		for _, b := range inAdditions {
-			objACL.In[b.blessing] = *b.ls
-		}
-
-		for _, b := range notInAdditions {
-			objACL.NotIn[b.blessing] = *b.ls
-		}
-
 		switch err := node.ApplicationClient(vanaName).SetACL(rt.R().NewContext(), objACL, etag); {
 		case err != nil && !verror.Is(err, access.ErrBadEtag):
 			return cmd.UsageErrorf("SetACL(%s) failed: %v", vanaName, err)
diff --git a/tools/mgmt/nodex/acl_test.go b/tools/mgmt/nodex/acl_test.go
index 9f4d581..25aec7e 100644
--- a/tools/mgmt/nodex/acl_test.go
+++ b/tools/mgmt/nodex/acl_test.go
@@ -4,6 +4,7 @@
 	"bytes"
 	"fmt"
 	"reflect"
+	"regexp"
 	"strings"
 	"testing"
 
@@ -29,30 +30,33 @@
 	cmd.Init(nil, &stdout, &stderr)
 	nodeName := naming.JoinAddressName(endpoint.String(), "")
 
-	// Test the 'list' command.
+	// Test the 'get' command.
 	tape.SetResponses([]interface{}{GetACLResponse{
-		acl: security.ACL{
-			In: map[security.BlessingPattern]security.LabelSet{
-				"root/self/...": security.AllLabels,
-				"root/other":    security.LabelSet(security.ReadLabel),
+		acl: access.TaggedACLMap{
+			"Admin": access.ACL{
+				In:    []security.BlessingPattern{"self/..."},
+				NotIn: []string{"self/bad"},
 			},
-			NotIn: map[string]security.LabelSet{
-				"root/bob/...": security.LabelSet(security.WriteLabel),
+			"Read": access.ACL{
+				In: []security.BlessingPattern{"other", "self/..."},
 			},
 		},
 		etag: "anEtagForToday",
 		err:  nil,
-	},
-	})
+	}})
 
 	if err := cmd.Execute([]string{"acl", "get", nodeName}); err != nil {
-		t.Fatalf("%v, ouput: %v, error: %v", err)
+		t.Fatalf("%v, output: %v, error: %v", err)
 	}
-	if expected, got := "root/bob/... !W\nroot/other R\nroot/self/... XRWADM", strings.TrimSpace(stdout.String()); got != expected {
-		t.Fatalf("Unexpected output from get. Got %q, expected %q", got, expected)
+	if expected, got := strings.TrimSpace(`
+other Read
+self/... Admin,Read
+self/bad !Admin
+`), strings.TrimSpace(stdout.String()); got != expected {
+		t.Errorf("Unexpected output from get. Got %q, expected %q", got, expected)
 	}
 	if got, expected := tape.Play(), []interface{}{"GetACL"}; !reflect.DeepEqual(expected, got) {
-		t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
+		t.Errorf("invalid call sequence. Got %#v, want %#v", got, expected)
 	}
 	tape.Rewind()
 	stdout.Reset()
@@ -104,21 +108,21 @@
 	if err := cmd.Execute([]string{"acl", "set", nodeName, "foo", "!"}); err == nil {
 		t.Fatalf("failed to detect invalid parameter")
 	}
-	if expected, got := "ERROR: failed to parse LabelSet pair foo, !", strings.TrimSpace(stderr.String()); !strings.HasPrefix(got, expected) {
-		t.Fatalf("Unexpected output from list. Got %q, expected prefix %q", got, expected)
+	if expected, got := "ERROR: failed to parse access tags for \"foo\": empty access tag", strings.TrimSpace(stderr.String()); !strings.HasPrefix(got, expected) {
+		t.Errorf("Unexpected output from list. Got %q, expected prefix %q", got, expected)
 	}
 
 	// Correct operation in the absence of errors.
 	stderr.Reset()
 	stdout.Reset()
 	tape.SetResponses([]interface{}{GetACLResponse{
-		acl: security.ACL{
-			In: map[security.BlessingPattern]security.LabelSet{
-				"root/self/...": security.AllLabels,
-				"root/other":    security.LabelSet(security.ReadLabel),
+		acl: access.TaggedACLMap{
+			"Admin": access.ACL{
+				In: []security.BlessingPattern{"self/..."},
 			},
-			NotIn: map[string]security.LabelSet{
-				"root/bob": security.LabelSet(security.WriteLabel),
+			"Read": access.ACL{
+				In:    []security.BlessingPattern{"other/...", "self/..."},
+				NotIn: []string{"other/bob"},
 			},
 		},
 		etag: "anEtagForToday",
@@ -126,14 +130,13 @@
 	},
 		verror.Make(access.ErrBadEtag, fmt.Sprintf("etag mismatch in:%s vers:%s", "anEtagForToday", "anEtagForTomorrow")),
 		GetACLResponse{
-			acl: security.ACL{
-				In: map[security.BlessingPattern]security.LabelSet{
-					"root/self/...": security.AllLabels,
-					"root/other":    security.LabelSet(security.ReadLabel),
+			acl: access.TaggedACLMap{
+				"Admin": access.ACL{
+					In: []security.BlessingPattern{"self/..."},
 				},
-				NotIn: map[string]security.LabelSet{
-					"root/bob":       security.LabelSet(security.WriteLabel),
-					"root/alice/cat": security.LabelSet(security.AdminLabel),
+				"Read": access.ACL{
+					In:    []security.BlessingPattern{"other/...", "self/..."},
+					NotIn: []string{"other/bob/baddevice"},
 				},
 			},
 			etag: "anEtagForTomorrow",
@@ -142,7 +145,20 @@
 		nil,
 	})
 
-	if err := cmd.Execute([]string{"acl", "set", nodeName, "root/vana/bad", "!XR", "root/vana/...", "RD", "root/other", "0", "root/bob", "!0"}); err != nil {
+	// set command that:
+	// - Adds entry for "friends/..." to "Write" & "Admin"
+	// - Adds a blacklist entry for "friend/alice"  for "Admin"
+	// - Edits existing entry for "self/..." (adding "Write" access)
+	// - Removes entry for "other/bob/baddevice"
+	if err := cmd.Execute([]string{
+		"acl",
+		"set",
+		nodeName,
+		"friends/...", "Admin,Write",
+		"friends/alice", "!Admin,Write",
+		"self/...", "Admin,Write,Read",
+		"other/bob/baddevice", "^",
+	}); err != nil {
 		t.Fatalf("SetACL failed: %v", err)
 	}
 
@@ -152,18 +168,22 @@
 	if expected, got := "WARNING: trying again because of asynchronous change", strings.TrimSpace(stderr.String()); got != expected {
 		t.Fatalf("Unexpected output from list. Got %q, expected %q", got, expected)
 	}
-
 	expected := []interface{}{
 		"GetACL",
 		SetACLStimulus{
 			fun: "SetACL",
-			acl: security.ACL{
-				In: map[security.BlessingPattern]security.LabelSet{
-					"root/self/...": security.AllLabels,
-					"root/vana/...": security.LabelSet(security.ReadLabel | security.DebugLabel),
+			acl: access.TaggedACLMap{
+				"Admin": access.ACL{
+					In:    []security.BlessingPattern{"friends/...", "self/..."},
+					NotIn: []string{"friends/alice"},
 				},
-				NotIn: map[string]security.LabelSet{
-					"root/vana/bad": security.LabelSet(security.ResolveLabel | security.ReadLabel),
+				"Read": access.ACL{
+					In:    []security.BlessingPattern{"other/...", "self/..."},
+					NotIn: []string{"other/bob"},
+				},
+				"Write": access.ACL{
+					In:    []security.BlessingPattern{"friends/...", "friends/alice", "self/..."},
+					NotIn: []string{},
 				},
 			},
 			etag: "anEtagForToday",
@@ -171,14 +191,18 @@
 		"GetACL",
 		SetACLStimulus{
 			fun: "SetACL",
-			acl: security.ACL{
-				In: map[security.BlessingPattern]security.LabelSet{
-					"root/self/...": security.AllLabels,
-					"root/vana/...": security.LabelSet(security.ReadLabel | security.DebugLabel),
+			acl: access.TaggedACLMap{
+				"Admin": access.ACL{
+					In:    []security.BlessingPattern{"friends/...", "self/..."},
+					NotIn: []string{"friends/alice"},
 				},
-				NotIn: map[string]security.LabelSet{
-					"root/alice/cat": security.LabelSet(security.AdminLabel),
-					"root/vana/bad":  security.LabelSet(security.ResolveLabel | security.ReadLabel),
+				"Read": access.ACL{
+					In:    []security.BlessingPattern{"other/...", "self/..."},
+					NotIn: []string{},
+				},
+				"Write": access.ACL{
+					In:    []security.BlessingPattern{"friends/...", "friends/alice", "self/..."},
+					NotIn: []string{},
 				},
 			},
 			etag: "anEtagForTomorrow",
@@ -186,7 +210,7 @@
 	}
 
 	if got := tape.Play(); !reflect.DeepEqual(expected, got) {
-		t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
+		t.Errorf("invalid call sequence. Got %#v, want %#v", got, expected)
 	}
 	tape.Rewind()
 	stdout.Reset()
@@ -194,17 +218,17 @@
 
 	// GetACL fails.
 	tape.SetResponses([]interface{}{GetACLResponse{
-		acl:  security.ACL{In: nil, NotIn: nil},
+		acl:  access.TaggedACLMap{},
 		etag: "anEtagForToday",
 		err:  verror.BadArgf("oops!"),
 	},
 	})
 
-	if err := cmd.Execute([]string{"acl", "set", nodeName, "root/vana/bad", "!XR", "root/vana/...", "RD", "root/other", "0", "root/bob", "!0"}); err == nil {
+	if err := cmd.Execute([]string{"acl", "set", nodeName, "vana/bad", "Read"}); err == nil {
 		t.Fatalf("GetACL RPC inside acl set command failed but error wrongly not detected")
 	}
-	if expected, got := "ERROR: GetACL("+nodeName+") failed: oops!", strings.TrimSpace(stderr.String()); !strings.HasPrefix(got, expected) {
-		t.Fatalf("Unexpected output from list. Got %q, prefix %q", got, expected)
+	if expected, got := `^ERROR: GetACL\(`+nodeName+`\) failed:.*oops!`, strings.TrimSpace(stderr.String()); !regexp.MustCompile(expected).MatchString(got) {
+		t.Fatalf("Unexpected output from list. Got %q, regexp %q", got, expected)
 	}
 	if expected, got := "", strings.TrimSpace(stdout.String()); got != expected {
 		t.Fatalf("Unexpected output from list. Got %q, expected %q", got, expected)
@@ -214,21 +238,17 @@
 	}
 
 	if got := tape.Play(); !reflect.DeepEqual(expected, got) {
-		t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
+		t.Errorf("invalid call sequence. Got %#v, want %#v", got, expected)
 	}
 	tape.Rewind()
 	stdout.Reset()
 	stderr.Reset()
 
-	// SetACL fails with not a bad etag failure.
+	// SetACL fails with something other than a bad etag failure.
 	tape.SetResponses([]interface{}{GetACLResponse{
-		acl: security.ACL{
-			In: map[security.BlessingPattern]security.LabelSet{
-				"root/self/...": security.AllLabels,
-				"root/other":    security.LabelSet(security.ReadLabel),
-			},
-			NotIn: map[string]security.LabelSet{
-				"root/bob": security.LabelSet(security.WriteLabel),
+		acl: access.TaggedACLMap{
+			"Read": access.ACL{
+				In: []security.BlessingPattern{"other", "self/..."},
 			},
 		},
 		etag: "anEtagForToday",
@@ -237,27 +257,24 @@
 		verror.BadArgf("oops!"),
 	})
 
-	if err := cmd.Execute([]string{"acl", "set", nodeName, "root/vana/bad", "!XR", "root/vana/...", "RD", "root/other", "0", "root/bob", "!0"}); err == nil {
+	if err := cmd.Execute([]string{"acl", "set", nodeName, "friend", "Read"}); err == nil {
 		t.Fatalf("SetACL should have failed: %v", err)
 	}
 	if expected, got := "", strings.TrimSpace(stdout.String()); got != expected {
 		t.Fatalf("Unexpected output from list. Got %q, expected %q", got, expected)
 	}
-	if expected, got := "ERROR: SetACL("+nodeName+") failed: oops!", strings.TrimSpace(stderr.String()); !strings.HasPrefix(got, expected) {
-		t.Fatalf("Unexpected output from list. Got %q, prefix %q", got, expected)
+	if expected, got := `^ERROR: SetACL\(`+nodeName+`\) failed:.*oops!`, strings.TrimSpace(stderr.String()); !regexp.MustCompile(expected).MatchString(got) {
+		t.Fatalf("Unexpected output from list. Got %q, regexp %q", got, expected)
 	}
 
 	expected = []interface{}{
 		"GetACL",
 		SetACLStimulus{
 			fun: "SetACL",
-			acl: security.ACL{
-				In: map[security.BlessingPattern]security.LabelSet{
-					"root/self/...": security.AllLabels,
-					"root/vana/...": security.LabelSet(security.ReadLabel | security.DebugLabel),
-				},
-				NotIn: map[string]security.LabelSet{
-					"root/vana/bad": security.LabelSet(security.ResolveLabel | security.ReadLabel),
+			acl: access.TaggedACLMap{
+				"Read": access.ACL{
+					In:    []security.BlessingPattern{"friend", "other", "self/..."},
+					NotIn: []string{},
 				},
 			},
 			etag: "anEtagForToday",
@@ -265,46 +282,7 @@
 	}
 
 	if got := tape.Play(); !reflect.DeepEqual(expected, got) {
-		t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
-	}
-	tape.Rewind()
-	stdout.Reset()
-	stderr.Reset()
-
-	// Trying to delete non-existent items.
-	stderr.Reset()
-	stdout.Reset()
-	tape.SetResponses([]interface{}{GetACLResponse{
-		acl: security.ACL{
-			In:    map[security.BlessingPattern]security.LabelSet{},
-			NotIn: map[string]security.LabelSet{},
-		},
-		etag: "anEtagForToday",
-		err:  nil,
-	},
-		nil,
-	})
-
-	if err := cmd.Execute([]string{"acl", "set", nodeName, "root/vana/notin/missing", "!0", "root/vana/in/missing", "0"}); err != nil {
-		t.Fatalf("SetACL failed: %v", err)
-	}
-	if expected, got := "", strings.TrimSpace(stdout.String()); got != expected {
-		t.Fatalf("Unexpected output from list. Got %q, expected %q", got, expected)
-	}
-	if expected, got := "WARNING: ignoring attempt to remove non-existing NotIn ACL for root/vana/notin/missing\nWARNING: ignoring attempt to remove non-existing In ACL for root/vana/in/missing", strings.TrimSpace(stderr.String()); got != expected {
-		t.Fatalf("Unexpected output from list. Got %q, expected %q", got, expected)
-	}
-
-	expected = []interface{}{
-		"GetACL",
-		SetACLStimulus{
-			fun:  "SetACL",
-			acl:  security.ACL{},
-			etag: "anEtagForToday",
-		},
-	}
-	if got := tape.Play(); !reflect.DeepEqual(expected, got) {
-		t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
+		t.Errorf("invalid call sequence. Got %#v, want %#v", got, expected)
 	}
 	tape.Rewind()
 	stdout.Reset()
diff --git a/tools/mgmt/nodex/doc.go b/tools/mgmt/nodex/doc.go
index 6b3ff6d..2ea903d 100644
--- a/tools/mgmt/nodex/doc.go
+++ b/tools/mgmt/nodex/doc.go
@@ -47,8 +47,6 @@
    Rate (from 0.0 to 1.0) to sample vtrace traces.
  -vmodule=
    comma-separated list of pattern=N settings for file-filtered logging
- -vv=0
-   log level for V logs
 
 Nodex Install
 
diff --git a/tools/mgmt/nodex/main.go b/tools/mgmt/nodex/main.go
index 9e5d556..b0e270d 100644
--- a/tools/mgmt/nodex/main.go
+++ b/tools/mgmt/nodex/main.go
@@ -1,5 +1,5 @@
 // The following enables go generate to generate the doc.go file.
-//go:generate go run $VEYRON_ROOT/lib/cmdline/testdata/gendoc.go .
+//go:generate go run $VEYRON_ROOT/veyron/go/src/veyron.io/lib/cmdline/testdata/gendoc.go .
 
 package main
 
diff --git a/tools/mgmt/nodex/nodemanager_mock_test.go b/tools/mgmt/nodex/nodemanager_mock_test.go
index 0fa29fd..6449110 100644
--- a/tools/mgmt/nodex/nodemanager_mock_test.go
+++ b/tools/mgmt/nodex/nodemanager_mock_test.go
@@ -10,6 +10,7 @@
 	"veyron.io/veyron/veyron2/security"
 	"veyron.io/veyron/veyron2/services/mgmt/binary"
 	"veyron.io/veyron/veyron2/services/mgmt/node"
+	"veyron.io/veyron/veyron2/services/security/access"
 	"veyron.io/veyron/veyron2/vlog"
 
 	"veyron.io/veyron/veyron/profiles"
@@ -92,18 +93,18 @@
 
 // Mock ACL getting and setting
 type GetACLResponse struct {
-	acl  security.ACL
+	acl  access.TaggedACLMap
 	etag string
 	err  error
 }
 
 type SetACLStimulus struct {
 	fun  string
-	acl  security.ACL
+	acl  access.TaggedACLMap
 	etag string
 }
 
-func (mni *mockNodeInvoker) SetACL(_ ipc.ServerContext, acl security.ACL, etag string) error {
+func (mni *mockNodeInvoker) SetACL(_ ipc.ServerContext, acl access.TaggedACLMap, etag string) error {
 	ri := mni.tape.Record(SetACLStimulus{"SetACL", acl, etag})
 	switch r := ri.(type) {
 	case nil:
@@ -115,7 +116,7 @@
 	return nil
 }
 
-func (mni *mockNodeInvoker) GetACL(ipc.ServerContext) (security.ACL, string, error) {
+func (mni *mockNodeInvoker) GetACL(ipc.ServerContext) (access.TaggedACLMap, string, error) {
 	ir := mni.tape.Record("GetACL")
 	r := ir.(GetACLResponse)
 	return r.acl, r.etag, r.err
diff --git a/tools/mounttable/doc.go b/tools/mounttable/doc.go
index fc63e5a..6e8eb92 100644
--- a/tools/mounttable/doc.go
+++ b/tools/mounttable/doc.go
@@ -16,24 +16,41 @@
 Run "mounttable help [command]" for command usage.
 
 The global flags are:
-   -alsologtostderr=true: log to standard error as well as files
-   -log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
-   -log_dir=: if non-empty, write log files to this directory
-   -logtostderr=false: log to standard error instead of files
-   -max_stack_buf_size=4292608: max size in bytes of the buffer to use for logging stack traces
-   -stderrthreshold=2: logs at or above this threshold go to stderr
-   -v=0: log level for V logs
-   -vmodule=: comma-separated list of pattern=N settings for file-filtered logging
-   -vv=0: log level for V logs
+ -alsologtostderr=true
+   log to standard error as well as files
+ -log_backtrace_at=:0
+   when logging hits line file:N, emit a stack trace
+ -log_dir=
+   if non-empty, write log files to this directory
+ -logtostderr=false
+   log to standard error instead of files
+ -max_stack_buf_size=4292608
+   max size in bytes of the buffer to use for logging stack traces
+ -stderrthreshold=2
+   logs at or above this threshold go to stderr
+ -v=0
+   log level for V logs
+ -veyron.credentials=
+   directory to use for storing security credentials
+ -veyron.namespace.root=[/proxy.envyor.com:8101]
+   local namespace root; can be repeated to provided multiple roots
+ -veyron.vtrace.cache_size=1024
+   The number of vtrace traces to store in memory.
+ -veyron.vtrace.dump_on_shutdown=false
+   If true, dump all stored traces on runtime shutdown.
+ -veyron.vtrace.sample_rate=0
+   Rate (from 0.0 to 1.0) to sample vtrace traces.
+ -vmodule=
+   comma-separated list of pattern=N settings for file-filtered logging
 
 Mounttable Glob
 
 returns all matching entries in the mount table
 
 Usage:
-   mounttable glob <mount name> <pattern>
+   mounttable glob [<mount name>] <pattern>
 
-<mount name> is a mount name on a mount table.
+<mount name> is a mount name on a mount table.  Defaults to namespace root.
 <pattern> is a glob pattern that is matched against all the entries below the
 specified mount name.
 
@@ -44,10 +61,10 @@
 Usage:
    mounttable mount <mount name> <name> <ttl>
 
-<mount name> is a mount name on a mount table.
-<name> is the rooted object name of the server.
-<ttl> is the TTL of the new entry. It is a decimal number followed by a unit
-suffix (s, m, h). A value of 0s represents an infinite duration.
+<mount name> is a mount name on a mount table. <name> is the rooted object name
+of the server. <ttl> is the TTL of the new entry. It is a decimal number
+followed by a unit suffix (s, m, h). A value of 0s represents an infinite
+duration.
 
 Mounttable Unmount
 
@@ -56,8 +73,8 @@
 Usage:
    mounttable unmount <mount name> <name>
 
-<mount name> is a mount name on a mount table.
-<name> is the rooted object name of the server.
+<mount name> is a mount name on a mount table. <name> is the rooted object name
+of the server.
 
 Mounttable Resolvestep
 
@@ -71,15 +88,24 @@
 Mounttable Help
 
 Help with no args displays the usage of the parent command.
+
 Help with args displays the usage of the specified sub-command or help topic.
+
 "help ..." recursively displays help for all commands and topics.
 
+The output is formatted to a target width in runes.  The target width is
+determined by checking the environment variable CMDLINE_WIDTH, falling back on
+the terminal width from the OS, falling back on 80 chars.  By setting
+CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
+if x == 0 or is unset one of the fallbacks is used.
+
 Usage:
    mounttable help [flags] [command/topic ...]
 
 [command/topic ...] optionally identifies a specific sub-command or help topic.
 
-The help flags are:
-   -style=text: The formatting style for help output, either "text" or "godoc".
+The mounttable help flags are:
+ -style=text
+   The formatting style for help output, either "text" or "godoc".
 */
 package main
diff --git a/tools/mounttable/impl.go b/tools/mounttable/impl.go
index efa69fc..6afca98 100644
--- a/tools/mounttable/impl.go
+++ b/tools/mounttable/impl.go
@@ -8,12 +8,11 @@
 	"veyron.io/veyron/veyron2/context"
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/options"
-	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/services/mounttable"
 )
 
 func bindMT(ctx context.T, name string) (mounttable.MountTableClientMethods, error) {
-	e, err := rt.R().Namespace().ResolveToMountTableX(ctx, name)
+	e, err := runtime.Namespace().ResolveToMountTableX(ctx, name)
 	if err != nil {
 		return nil, err
 	}
@@ -48,7 +47,7 @@
 	if expected, got := 2, len(args); expected != got {
 		return cmd.UsageErrorf("glob: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
 	defer cancel()
 	c, err := bindMT(ctx, args[0])
 	if err != nil {
@@ -117,9 +116,9 @@
 			}
 		}
 	}
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
 	defer cancel()
-	call, err := rt.R().Client().StartCall(ctx, args[0], "Mount", []interface{}{args[1], seconds, 0}, options.NoResolve(true))
+	call, err := runtime.Client().StartCall(ctx, args[0], "Mount", []interface{}{args[1], seconds, 0}, options.NoResolve(true))
 	if err != nil {
 		return err
 	}
@@ -147,9 +146,9 @@
 	if expected, got := 2, len(args); expected != got {
 		return cmd.UsageErrorf("unmount: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
 	defer cancel()
-	call, err := rt.R().Client().StartCall(ctx, args[0], "Unmount", []interface{}{args[1]}, options.NoResolve(true))
+	call, err := runtime.Client().StartCall(ctx, args[0], "Unmount", []interface{}{args[1]}, options.NoResolve(true))
 	if err != nil {
 		return err
 	}
@@ -176,9 +175,9 @@
 	if expected, got := 1, len(args); expected != got {
 		return cmd.UsageErrorf("mount: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
 	defer cancel()
-	call, err := rt.R().Client().StartCall(ctx, args[0], "ResolveStepX", []interface{}{}, options.NoResolve(true))
+	call, err := runtime.Client().StartCall(ctx, args[0], "ResolveStepX", []interface{}{}, options.NoResolve(true))
 	if err != nil {
 		return err
 	}
diff --git a/tools/mounttable/impl_test.go b/tools/mounttable/impl_test.go
index 90e83e2..9c59eb6 100644
--- a/tools/mounttable/impl_test.go
+++ b/tools/mounttable/impl_test.go
@@ -85,7 +85,13 @@
 }
 
 func TestMountTableClient(t *testing.T) {
-	runtime := rt.Init()
+	var err error
+	runtime, err = rt.New()
+	if err != nil {
+		t.Fatalf("Unexpected error initializing runtime: %s", err)
+	}
+	defer runtime.Cleanup()
+
 	server, endpoint, err := startServer(t, runtime)
 	if err != nil {
 		return
diff --git a/tools/mounttable/main.go b/tools/mounttable/main.go
index 9e5d556..3723981 100644
--- a/tools/mounttable/main.go
+++ b/tools/mounttable/main.go
@@ -1,15 +1,23 @@
 // The following enables go generate to generate the doc.go file.
-//go:generate go run $VEYRON_ROOT/lib/cmdline/testdata/gendoc.go .
+//go:generate go run $VEYRON_ROOT/veyron/go/src/veyron.io/lib/cmdline/testdata/gendoc.go .
 
 package main
 
 import (
+	"veyron.io/veyron/veyron2"
 	"veyron.io/veyron/veyron2/rt"
 
 	_ "veyron.io/veyron/veyron/profiles"
 )
 
+var runtime veyron2.Runtime
+
 func main() {
-	defer rt.Init().Cleanup()
+	var err error
+	runtime, err = rt.New()
+	if err != nil {
+		panic(err)
+	}
+	defer runtime.Cleanup()
 	root().Main()
 }
diff --git a/tools/namespace/doc.go b/tools/namespace/doc.go
index addc28d..a6e8159 100644
--- a/tools/namespace/doc.go
+++ b/tools/namespace/doc.go
@@ -4,9 +4,10 @@
 /*
 The namespace tool facilitates interaction with the Veyron namespace.
 
-The namespace roots are set from environment variables that have a name
-starting with NAMESPACE_ROOT, e.g. NAMESPACE_ROOT, NAMESPACE_ROOT_2,
-NAMESPACE_ROOT_GOOGLE, etc.
+The namespace roots are set from the command line via veyron.namespace.root
+options or from environment variables that have a name starting with
+NAMESPACE_ROOT, e.g. NAMESPACE_ROOT, NAMESPACE_ROOT_2, NAMESPACE_ROOT_GOOGLE,
+etc. The command line options override the environment.
 
 Usage:
    namespace <command>
@@ -22,15 +23,32 @@
 Run "namespace help [command]" for command usage.
 
 The global flags are:
-   -alsologtostderr=true: log to standard error as well as files
-   -log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
-   -log_dir=: if non-empty, write log files to this directory
-   -logtostderr=false: log to standard error instead of files
-   -max_stack_buf_size=4292608: max size in bytes of the buffer to use for logging stack traces
-   -stderrthreshold=2: logs at or above this threshold go to stderr
-   -v=0: log level for V logs
-   -vmodule=: comma-separated list of pattern=N settings for file-filtered logging
-   -vv=0: log level for V logs
+ -alsologtostderr=true
+   log to standard error as well as files
+ -log_backtrace_at=:0
+   when logging hits line file:N, emit a stack trace
+ -log_dir=
+   if non-empty, write log files to this directory
+ -logtostderr=false
+   log to standard error instead of files
+ -max_stack_buf_size=4292608
+   max size in bytes of the buffer to use for logging stack traces
+ -stderrthreshold=2
+   logs at or above this threshold go to stderr
+ -v=0
+   log level for V logs
+ -veyron.credentials=
+   directory to use for storing security credentials
+ -veyron.namespace.root=[/proxy.envyor.com:8101]
+   local namespace root; can be repeated to provided multiple roots
+ -veyron.vtrace.cache_size=1024
+   The number of vtrace traces to store in memory.
+ -veyron.vtrace.dump_on_shutdown=false
+   If true, dump all stored traces on runtime shutdown.
+ -veyron.vtrace.sample_rate=0
+   Rate (from 0.0 to 1.0) to sample vtrace traces.
+ -vmodule=
+   comma-separated list of pattern=N settings for file-filtered logging
 
 Namespace Glob
 
@@ -49,10 +67,10 @@
 Usage:
    namespace mount <name> <server> <ttl>
 
-<name> is the name to add to the namespace.
-<server> is the object address of the server to add.
-<ttl> is the TTL of the new entry. It is a decimal number followed by a unit
-suffix (s, m, h). A value of 0s represents an infinite duration.
+<name> is the name to add to the namespace. <server> is the object address of
+the server to add. <ttl> is the TTL of the new entry. It is a decimal number
+followed by a unit suffix (s, m, h). A value of 0s represents an infinite
+duration.
 
 Namespace Unmount
 
@@ -61,8 +79,8 @@
 Usage:
    namespace unmount <name> <server>
 
-<name> is the name to remove from the namespace.
-<server> is the object address of the server to remove.
+<name> is the name to remove from the namespace. <server> is the object address
+of the server to remove.
 
 Namespace Resolve
 
@@ -94,15 +112,24 @@
 Namespace Help
 
 Help with no args displays the usage of the parent command.
+
 Help with args displays the usage of the specified sub-command or help topic.
+
 "help ..." recursively displays help for all commands and topics.
 
+The output is formatted to a target width in runes.  The target width is
+determined by checking the environment variable CMDLINE_WIDTH, falling back on
+the terminal width from the OS, falling back on 80 chars.  By setting
+CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
+if x == 0 or is unset one of the fallbacks is used.
+
 Usage:
    namespace help [flags] [command/topic ...]
 
 [command/topic ...] optionally identifies a specific sub-command or help topic.
 
-The help flags are:
-   -style=text: The formatting style for help output, either "text" or "godoc".
+The namespace help flags are:
+ -style=text
+   The formatting style for help output, either "text" or "godoc".
 */
 package main
diff --git a/tools/namespace/impl.go b/tools/namespace/impl.go
index a1f1f47..b4c1e03 100644
--- a/tools/namespace/impl.go
+++ b/tools/namespace/impl.go
@@ -6,7 +6,6 @@
 
 	"veyron.io/lib/cmdline"
 	"veyron.io/veyron/veyron2/naming"
-	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/vlog"
 )
 
@@ -27,8 +26,8 @@
 		return cmd.UsageErrorf("glob: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	pattern := args[0]
-	ns := rt.R().Namespace()
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ns := runtime.Namespace()
+	ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
 	defer cancel()
 	c, err := ns.Glob(ctx, pattern)
 	if err != nil {
@@ -40,6 +39,10 @@
 		for _, s := range res.Servers {
 			fmt.Fprintf(cmd.Stdout(), " %s (Expires %s)", s.Server, s.Expires)
 		}
+		if res.Error != nil {
+			fmt.Fprintln(cmd.Stdout())
+			fmt.Fprintf(cmd.Stdout(), "result error: %v", res.Error)
+		}
 		fmt.Fprintln(cmd.Stdout())
 	}
 	return nil
@@ -71,8 +74,8 @@
 	if err != nil {
 		return fmt.Errorf("TTL parse error: %v", err)
 	}
-	ns := rt.R().Namespace()
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ns := runtime.Namespace()
+	ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
 	defer cancel()
 	if err = ns.Mount(ctx, name, server, ttl); err != nil {
 		vlog.Infof("ns.Mount(%q, %q, %s) failed: %v", name, server, ttl, err)
@@ -100,8 +103,8 @@
 	}
 	name := args[0]
 	server := args[1]
-	ns := rt.R().Namespace()
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ns := runtime.Namespace()
+	ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
 	defer cancel()
 	if err := ns.Unmount(ctx, name, server); err != nil {
 		vlog.Infof("ns.Unmount(%q, %q) failed: %v", name, server, err)
@@ -125,8 +128,8 @@
 		return cmd.UsageErrorf("resolve: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	name := args[0]
-	ns := rt.R().Namespace()
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ns := runtime.Namespace()
+	ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
 	defer cancel()
 	servers, err := ns.Resolve(ctx, name)
 	if err != nil {
@@ -153,8 +156,8 @@
 		return cmd.UsageErrorf("resolvetomt: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	name := args[0]
-	ns := rt.R().Namespace()
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ns := runtime.Namespace()
+	ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
 	defer cancel()
 	e, err := ns.ResolveToMountTableX(ctx, name)
 	if err != nil {
@@ -181,8 +184,8 @@
 		return cmd.UsageErrorf("unresolve: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	name := args[0]
-	ns := rt.R().Namespace()
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ns := runtime.Namespace()
+	ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
 	defer cancel()
 	servers, err := ns.Unresolve(ctx, name)
 	if err != nil {
diff --git a/tools/namespace/main.go b/tools/namespace/main.go
index 9e5d556..3723981 100644
--- a/tools/namespace/main.go
+++ b/tools/namespace/main.go
@@ -1,15 +1,23 @@
 // The following enables go generate to generate the doc.go file.
-//go:generate go run $VEYRON_ROOT/lib/cmdline/testdata/gendoc.go .
+//go:generate go run $VEYRON_ROOT/veyron/go/src/veyron.io/lib/cmdline/testdata/gendoc.go .
 
 package main
 
 import (
+	"veyron.io/veyron/veyron2"
 	"veyron.io/veyron/veyron2/rt"
 
 	_ "veyron.io/veyron/veyron/profiles"
 )
 
+var runtime veyron2.Runtime
+
 func main() {
-	defer rt.Init().Cleanup()
+	var err error
+	runtime, err = rt.New()
+	if err != nil {
+		panic(err)
+	}
+	defer runtime.Cleanup()
 	root().Main()
 }
diff --git a/tools/naming/simulator/driver.go b/tools/naming/simulator/driver.go
index 9242830..01685f9 100644
--- a/tools/naming/simulator/driver.go
+++ b/tools/naming/simulator/driver.go
@@ -19,7 +19,6 @@
 	"veyron.io/veyron/veyron2/rt"
 
 	"veyron.io/veyron/veyron/lib/expect"
-	"veyron.io/veyron/veyron/lib/flags/consts"
 	"veyron.io/veyron/veyron/lib/modules"
 	_ "veyron.io/veyron/veyron/profiles"
 )
@@ -109,11 +108,12 @@
 		return
 	}
 
-	shell := modules.NewShell()
-	defer shell.Cleanup(os.Stderr, os.Stderr)
-	if os.Getenv(consts.VeyronCredentials) == "" {
-		shell.CreateAndUseNewCredentials()
+	shell, err := modules.NewShell(nil)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "unexpected error: %s\n", err)
+		os.Exit(1)
 	}
+	defer shell.Cleanup(os.Stderr, os.Stderr)
 
 	scanner := bufio.NewScanner(os.Stdin)
 	lineno := 1
diff --git a/tools/naming/simulator/driver_test.go b/tools/naming/simulator/driver_test.go
index d4dac88..5ccb5cb 100644
--- a/tools/naming/simulator/driver_test.go
+++ b/tools/naming/simulator/driver_test.go
@@ -40,7 +40,10 @@
 }
 
 func TestVariables(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	sh.SetVar("foo", "bar")
 	cases := []struct {
 		input  string
diff --git a/tools/principal/main.go b/tools/principal/main.go
index 9096bb3..ed12032 100644
--- a/tools/principal/main.go
+++ b/tools/principal/main.go
@@ -53,7 +53,13 @@
 that this tool is running in.
 `,
 		Run: func(cmd *cmdline.Command, args []string) error {
-			p := rt.Init().Principal()
+			runtime, err := rt.New()
+			if err != nil {
+				panic(err)
+			}
+			defer runtime.Cleanup()
+
+			p := runtime.Principal()
 			fmt.Printf("Public key : %v\n", p.PublicKey())
 			fmt.Println("---------------- BlessingStore ----------------")
 			fmt.Printf("%v", p.BlessingStore().DebugString())
@@ -140,7 +146,14 @@
 				}
 				caveats = append(caveats, cav)
 			}
-			blessing, err := rt.Init().Principal().BlessSelf(name, caveats...)
+
+			runtime, err := rt.New()
+			if err != nil {
+				panic(err)
+			}
+			defer runtime.Cleanup()
+
+			blessing, err := runtime.Principal().BlessSelf(name, caveats...)
 			if err != nil {
 				return fmt.Errorf("failed to create self-signed blessing for name %q: %v", name, err)
 			}
@@ -189,11 +202,16 @@
 			if len(args) != 2 {
 				return fmt.Errorf("require exactly two arguments, provided %d", len(args))
 			}
-			r := rt.Init()
-			p := r.Principal()
+
+			runtime, err := rt.New()
+			if err != nil {
+				panic(err)
+			}
+			defer runtime.Cleanup()
+
+			p := runtime.Principal()
 
 			var with security.Blessings
-			var err error
 			var caveats []security.Caveat
 			if len(flagBlessWith) > 0 {
 				if with, err = decodeBlessings(flagBlessWith); err != nil {
@@ -217,7 +235,7 @@
 			if len(flagBlessRemoteKey) > 0 {
 				// Send blessings to a "server" started by a "recvblessings" command
 				granter := &granter{p, with, extension, caveats, flagBlessRemoteKey}
-				return sendBlessings(r, tobless, granter, flagBlessRemoteToken)
+				return sendBlessings(runtime, tobless, granter, flagBlessRemoteToken)
 			}
 			// Blessing a principal whose key is available locally.
 			var key security.PublicKey
@@ -261,7 +279,13 @@
 blessings set on the store with the "..." pattern).
 `,
 		Run: func(cmd *cmdline.Command, args []string) error {
-			return dumpBlessings(rt.Init().Principal().BlessingStore().ForPeer(args...))
+			runtime, err := rt.New()
+			if err != nil {
+				panic(err)
+			}
+			defer runtime.Cleanup()
+
+			return dumpBlessings(runtime.Principal().BlessingStore().ForPeer(args...))
 		},
 	}
 
@@ -273,7 +297,13 @@
 the environment that this tool is running in.
 `,
 		Run: func(cmd *cmdline.Command, args []string) error {
-			return dumpBlessings(rt.Init().Principal().BlessingStore().Default())
+			runtime, err := rt.New()
+			if err != nil {
+				panic(err)
+			}
+			defer runtime.Cleanup()
+
+			return dumpBlessings(runtime.Principal().BlessingStore().Default())
 		},
 	}
 
@@ -311,7 +341,14 @@
 				return fmt.Errorf("failed to decode provided blessings: %v", err)
 			}
 			pattern := security.BlessingPattern(args[1])
-			p := rt.Init().Principal()
+
+			runtime, err := rt.New()
+			if err != nil {
+				panic(err)
+			}
+			defer runtime.Cleanup()
+
+			p := runtime.Principal()
 			if _, err := p.BlessingStore().Set(blessings, pattern); err != nil {
 				return fmt.Errorf("failed to set blessings %v for peers %v: %v", blessings, pattern, err)
 			}
@@ -347,7 +384,14 @@
 			if err != nil {
 				return fmt.Errorf("failed to decode provided blessings: %v", err)
 			}
-			p := rt.Init().Principal()
+
+			runtime, err := rt.New()
+			if err != nil {
+				panic(err)
+			}
+			defer runtime.Cleanup()
+
+			p := runtime.Principal()
 			if err := p.BlessingStore().SetDefault(blessings); err != nil {
 				return fmt.Errorf("failed to set blessings %v as default: %v", blessings, err)
 			}
@@ -433,7 +477,12 @@
 		Run: func(cmd *cmdline.Command, args []string) error {
 			// Initialize the runtime first so that any local errors are reported
 			// before the HTTP roundtrips for obtaining the macaroon begin.
-			r := rt.Init()
+			runtime, err := rt.New()
+			if err != nil {
+				panic(err)
+			}
+			defer runtime.Cleanup()
+
 			blessedChan := make(chan string)
 			defer close(blessedChan)
 			macaroonChan, err := getMacaroonForBlessRPC(flagSeekBlessingsFrom, blessedChan)
@@ -442,7 +491,7 @@
 			}
 			macaroon := <-macaroonChan
 			service := <-macaroonChan
-			ctx, cancel := r.NewContext().WithTimeout(time.Minute)
+			ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
 			defer cancel()
 
 			var reply security.WireBlessings
@@ -459,17 +508,17 @@
 			<-macaroonChan
 
 			if flagSeekBlessingsSetDefault {
-				if err := r.Principal().BlessingStore().SetDefault(blessings); err != nil {
+				if err := runtime.Principal().BlessingStore().SetDefault(blessings); err != nil {
 					return fmt.Errorf("failed to set blessings %v as default: %v", blessings, err)
 				}
 			}
 			if pattern := security.BlessingPattern(flagSeekBlessingsForPeer); len(pattern) > 0 {
-				if _, err := r.Principal().BlessingStore().Set(blessings, pattern); err != nil {
+				if _, err := runtime.Principal().BlessingStore().Set(blessings, pattern); err != nil {
 					return fmt.Errorf("failed to set blessings %v for peers %v: %v", blessings, pattern, err)
 				}
 			}
 			if flagAddToRoots {
-				if err := r.Principal().AddToRoots(blessings); err != nil {
+				if err := runtime.Principal().AddToRoots(blessings); err != nil {
 					return fmt.Errorf("AddToRoots failed: %v", err)
 				}
 			}
@@ -514,8 +563,14 @@
 			if len(args) != 0 {
 				return fmt.Errorf("command accepts no arguments")
 			}
-			r := rt.Init()
-			server, err := r.NewServer()
+
+			runtime, err := rt.New()
+			if err != nil {
+				panic(err)
+			}
+			defer runtime.Cleanup()
+
+			server, err := runtime.NewServer()
 			if err != nil {
 				return fmt.Errorf("failed to create server to listen for blessings: %v", err)
 			}
@@ -529,7 +584,7 @@
 				return fmt.Errorf("unable to generate token: %v", err)
 			}
 			service := &recvBlessingsService{
-				principal: r.Principal(),
+				principal: runtime.Principal(),
 				token:     base64.URLEncoding.EncodeToString(token[:]),
 				notify:    make(chan error),
 			}
@@ -542,7 +597,7 @@
 			fmt.Println("You may want to adjust flags affecting the caveats on this blessing, for example using")
 			fmt.Println("the --for flag, or change the extension to something more meaningful")
 			fmt.Println()
-			fmt.Printf("principal bless --remote_key=%v --remote_token=%v %v %v\n", r.Principal().PublicKey(), service.token, naming.JoinAddressName(ep.String(), ""), extension)
+			fmt.Printf("principal bless --remote_key=%v --remote_token=%v %v %v\n", runtime.Principal().PublicKey(), service.token, naming.JoinAddressName(ep.String(), ""), extension)
 			fmt.Println()
 			fmt.Println("...waiting for sender..")
 			return <-service.notify
diff --git a/tools/profile/doc.go b/tools/profile/doc.go
index 6a71540..1054a09 100644
--- a/tools/profile/doc.go
+++ b/tools/profile/doc.go
@@ -17,15 +17,32 @@
 Run "profile help [command]" for command usage.
 
 The global flags are:
-   -alsologtostderr=true: log to standard error as well as files
-   -log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
-   -log_dir=: if non-empty, write log files to this directory
-   -logtostderr=false: log to standard error instead of files
-   -max_stack_buf_size=4292608: max size in bytes of the buffer to use for logging stack traces
-   -stderrthreshold=2: logs at or above this threshold go to stderr
-   -v=0: log level for V logs
-   -vmodule=: comma-separated list of pattern=N settings for file-filtered logging
-   -vv=0: log level for V logs
+ -alsologtostderr=true
+   log to standard error as well as files
+ -log_backtrace_at=:0
+   when logging hits line file:N, emit a stack trace
+ -log_dir=
+   if non-empty, write log files to this directory
+ -logtostderr=false
+   log to standard error instead of files
+ -max_stack_buf_size=4292608
+   max size in bytes of the buffer to use for logging stack traces
+ -stderrthreshold=2
+   logs at or above this threshold go to stderr
+ -v=0
+   log level for V logs
+ -veyron.credentials=
+   directory to use for storing security credentials
+ -veyron.namespace.root=[/proxy.envyor.com:8101]
+   local namespace root; can be repeated to provided multiple roots
+ -veyron.vtrace.cache_size=1024
+   The number of vtrace traces to store in memory.
+ -veyron.vtrace.dump_on_shutdown=false
+   If true, dump all stored traces on runtime shutdown.
+ -veyron.vtrace.sample_rate=0
+   Rate (from 0.0 to 1.0) to sample vtrace traces.
+ -vmodule=
+   comma-separated list of pattern=N settings for file-filtered logging
 
 Profile Label
 
@@ -75,15 +92,24 @@
 Profile Help
 
 Help with no args displays the usage of the parent command.
+
 Help with args displays the usage of the specified sub-command or help topic.
+
 "help ..." recursively displays help for all commands and topics.
 
+The output is formatted to a target width in runes.  The target width is
+determined by checking the environment variable CMDLINE_WIDTH, falling back on
+the terminal width from the OS, falling back on 80 chars.  By setting
+CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
+if x == 0 or is unset one of the fallbacks is used.
+
 Usage:
    profile help [flags] [command/topic ...]
 
 [command/topic ...] optionally identifies a specific sub-command or help topic.
 
-The help flags are:
-   -style=text: The formatting style for help output, either "text" or "godoc".
+The profile help flags are:
+ -style=text
+   The formatting style for help output, either "text" or "godoc".
 */
 package main
diff --git a/tools/profile/impl.go b/tools/profile/impl.go
index 459b2ab..8869787 100644
--- a/tools/profile/impl.go
+++ b/tools/profile/impl.go
@@ -7,7 +7,6 @@
 	"veyron.io/lib/cmdline"
 	"veyron.io/veyron/veyron/services/mgmt/profile"
 	"veyron.io/veyron/veyron/services/mgmt/repository"
-	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/services/mgmt/build"
 )
 
@@ -26,7 +25,7 @@
 	}
 	name := args[0]
 	p := repository.ProfileClient(name)
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
 	defer cancel()
 	label, err := p.Label(ctx)
 	if err != nil {
@@ -51,7 +50,7 @@
 	}
 	name := args[0]
 	p := repository.ProfileClient(name)
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
 	defer cancel()
 	desc, err := p.Description(ctx)
 	if err != nil {
@@ -76,7 +75,7 @@
 	}
 	name := args[0]
 	p := repository.ProfileClient(name)
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
 	defer cancel()
 	spec, err := p.Specification(ctx)
 	if err != nil {
@@ -111,7 +110,7 @@
 		Label:       "example",
 		OS:          build.Linux,
 	}
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
 	defer cancel()
 	if err := p.Put(ctx, spec); err != nil {
 		return err
@@ -135,7 +134,7 @@
 	}
 	name := args[0]
 	p := repository.ProfileClient(name)
-	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+	ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
 	defer cancel()
 	if err := p.Remove(ctx); err != nil {
 		return err
diff --git a/tools/profile/impl_test.go b/tools/profile/impl_test.go
index 1dd149d..b442271 100644
--- a/tools/profile/impl_test.go
+++ b/tools/profile/impl_test.go
@@ -108,7 +108,13 @@
 }
 
 func TestProfileClient(t *testing.T) {
-	runtime := rt.Init()
+	var err error
+	runtime, err = rt.New()
+	if err != nil {
+		t.Fatalf("Unexpected error initializing runtime: %s", err)
+	}
+	defer runtime.Cleanup()
+
 	server, endpoint, err := startServer(t, runtime)
 	if err != nil {
 		return
diff --git a/tools/profile/main.go b/tools/profile/main.go
index 9e5d556..8423078 100644
--- a/tools/profile/main.go
+++ b/tools/profile/main.go
@@ -1,15 +1,23 @@
 // The following enables go generate to generate the doc.go file.
-//go:generate go run $VEYRON_ROOT/lib/cmdline/testdata/gendoc.go .
+//go:generate go run $VEYRON_ROOT/tools/go/src/tools/lib/cmdline/testdata/gendoc.go .
 
 package main
 
 import (
+	"veyron.io/veyron/veyron2"
 	"veyron.io/veyron/veyron2/rt"
 
 	_ "veyron.io/veyron/veyron/profiles"
 )
 
+var runtime veyron2.Runtime
+
 func main() {
-	defer rt.Init().Cleanup()
+	var err error
+	runtime, err = rt.New()
+	if err != nil {
+		panic(err)
+	}
+	defer runtime.Cleanup()
 	root().Main()
 }
diff --git a/tools/servicerunner/main.go b/tools/servicerunner/main.go
index 839af0d..2e8560e 100644
--- a/tools/servicerunner/main.go
+++ b/tools/servicerunner/main.go
@@ -64,18 +64,16 @@
 
 	vars := map[string]string{}
 
-	sh := modules.NewShell()
-	defer sh.Cleanup(os.Stderr, os.Stderr)
-	// NOTE(sadovsky): Shell only does this for tests. It would be better if it
-	// either always did it or never did it.
-	if os.Getenv(consts.VeyronCredentials) == "" {
-		panicOnError(sh.CreateAndUseNewCredentials())
-		v, ok := sh.GetVar(consts.VeyronCredentials)
-		if !ok {
-			panic("Missing " + consts.VeyronCredentials)
-		}
-		vars[consts.VeyronCredentials] = v
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		panic(fmt.Sprintf("modules.NewShell: %s", err))
 	}
+	defer sh.Cleanup(os.Stderr, os.Stderr)
+	v, ok := sh.GetVar(consts.VeyronCredentials)
+	if !ok {
+		panic("modules.Shell: missing " + consts.VeyronCredentials)
+	}
+	vars[consts.VeyronCredentials] = v
 
 	h, err := sh.Start("root", nil, "--", "--veyron.tcp.address=127.0.0.1:0")
 	panicOnError(err)
diff --git a/tools/servicerunner/servicerunner_test.go b/tools/servicerunner/servicerunner_test.go
new file mode 100644
index 0000000..fb72ff6
--- /dev/null
+++ b/tools/servicerunner/servicerunner_test.go
@@ -0,0 +1,46 @@
+// Runs the servicerunner binary and checks that it outputs a JSON line to
+// stdout with the expected variables.
+package main
+
+import (
+	"bufio"
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
+	"os/exec"
+	"path"
+	"testing"
+)
+
+func check(t *testing.T, err error) {
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestMain(t *testing.T) {
+	tmpdir, err := ioutil.TempDir("", "servicerunner_test")
+	check(t, err)
+
+	bin := path.Join(tmpdir, "servicerunner")
+	fmt.Println("Building", bin)
+	check(t, exec.Command("veyron", "go", "build", "-o", bin, "veyron.io/veyron/veyron/tools/servicerunner").Run())
+
+	cmd := exec.Command(bin)
+	stdout, err := cmd.StdoutPipe()
+	check(t, err)
+	check(t, cmd.Start())
+
+	line, err := bufio.NewReader(stdout).ReadBytes('\n')
+	check(t, err)
+	vars := map[string]string{}
+	check(t, json.Unmarshal(line, &vars))
+	fmt.Println(vars)
+	for _, name := range []string{"VEYRON_CREDENTIALS", "MT_NAME", "PROXY_ADDR", "WSPR_ADDR"} {
+		if _, ok := vars[name]; !ok {
+			t.Error("Missing", name)
+		}
+	}
+
+	check(t, cmd.Process.Kill())
+}
diff --git a/tools/vrpc/doc.go b/tools/vrpc/doc.go
index a2cb64e..69f90d6 100644
--- a/tools/vrpc/doc.go
+++ b/tools/vrpc/doc.go
@@ -2,9 +2,9 @@
 // DO NOT UPDATE MANUALLY
 
 /*
-The vrpc tool facilitates interaction with Veyron RPC servers. In particular,
-it can be used to 1) find out what API a Veyron RPC server exports and
-2) send requests to a Veyron RPC server.
+The vrpc tool facilitates interaction with Veyron RPC servers. In particular, it
+can be used to 1) find out what API a Veyron RPC server exports and 2) send
+requests to a Veyron RPC server.
 
 Usage:
    vrpc <command>
@@ -16,59 +16,103 @@
 Run "vrpc help [command]" for command usage.
 
 The global flags are:
-   -alsologtostderr=true: log to standard error as well as files
-   -log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
-   -log_dir=: if non-empty, write log files to this directory
-   -logtostderr=false: log to standard error instead of files
-   -max_stack_buf_size=4292608: max size in bytes of the buffer to use for logging stack traces
-   -stderrthreshold=2: logs at or above this threshold go to stderr
-   -v=0: log level for V logs
-   -vmodule=: comma-separated list of pattern=N settings for file-filtered logging
-   -vv=0: log level for V logs
+ -acl=
+   acl is an optional JSON-encoded security.ACL that is used to construct a
+   security.Authorizer. Example: {"In":{"veyron/alice/...":"RW"}} is a
+   JSON-encoded ACL that allows all delegates of "veyron/alice" to access all
+   methods with ReadLabel or WriteLabel. If this flag is provided then the
+   \"--acl_file\" must be absent.
+ -acl_file=
+   acl_file is an optional path to a file containing a JSON-encoded security.ACL
+   that is used to construct a security.Authorizer. If this flag is provided
+   then the "--acl_file" flag must be absent.
+ -alsologtostderr=true
+   log to standard error as well as files
+ -log_backtrace_at=:0
+   when logging hits line file:N, emit a stack trace
+ -log_dir=
+   if non-empty, write log files to this directory
+ -logtostderr=false
+   log to standard error instead of files
+ -max_stack_buf_size=4292608
+   max size in bytes of the buffer to use for logging stack traces
+ -stderrthreshold=2
+   logs at or above this threshold go to stderr
+ -v=0
+   log level for V logs
+ -veyron.credentials=
+   directory to use for storing security credentials
+ -veyron.namespace.root=[/proxy.envyor.com:8101]
+   local namespace root; can be repeated to provided multiple roots
+ -veyron.proxy=
+   object name of proxy service to use to export services across network
+   boundaries
+ -veyron.tcp.address=:0
+   address to listen on
+ -veyron.tcp.protocol=tcp
+   protocol to listen with
+ -veyron.vtrace.cache_size=1024
+   The number of vtrace traces to store in memory.
+ -veyron.vtrace.dump_on_shutdown=false
+   If true, dump all stored traces on runtime shutdown.
+ -veyron.vtrace.sample_rate=0
+   Rate (from 0.0 to 1.0) to sample vtrace traces.
+ -vmodule=
+   comma-separated list of pattern=N settings for file-filtered logging
 
 Vrpc Describe
 
-Describe connects to the Veyron RPC server identified by <server>, finds out what
-its API is, and outputs a succint summary of this API to the standard output.
+Describe connects to the Veyron RPC server identified by <server>, finds out
+what its API is, and outputs a succint summary of this API to the standard
+output.
 
 Usage:
    vrpc describe <server>
 
-<server> identifies the Veyron RPC server. It can either be the object address of
-the server or an Object name in which case the vrpc will use Veyron's name
+<server> identifies the Veyron RPC server. It can either be the object address
+of the server or an Object name in which case the vrpc will use Veyron's name
 resolution to match this name to an end-point.
 
 Vrpc Invoke
 
-Invoke connects to the Veyron RPC server identified by <server>, invokes the method
-identified by <method>, supplying the arguments identified by <args>, and outputs
-the results of the invocation to the standard output.
+Invoke connects to the Veyron RPC server identified by <server>, invokes the
+method identified by <method>, supplying the arguments identified by <args>, and
+outputs the results of the invocation to the standard output.
 
 Usage:
    vrpc invoke <server> <method> <args>
 
-<server> identifies the Veyron RPC server. It can either be the object address of
-the server or an Object name in which case the vrpc will use Veyron's name
+<server> identifies the Veyron RPC server. It can either be the object address
+of the server or an Object name in which case the vrpc will use Veyron's name
 resolution to match this name to an end-point.
 
 <method> identifies the name of the method to be invoked.
 
 <args> identifies the arguments of the method to be invoked. It should be a list
-of values in a VOM JSON format that can be reflected to the correct type
-using Go's reflection.
+of values in a VOM JSON format that can be reflected to the correct type using
+Go's reflection.
 
 Vrpc Help
 
 Help with no args displays the usage of the parent command.
+
 Help with args displays the usage of the specified sub-command or help topic.
+
 "help ..." recursively displays help for all commands and topics.
 
+The output is formatted to a target width in runes.  The target width is
+determined by checking the environment variable CMDLINE_WIDTH, falling back on
+the terminal width from the OS, falling back on 80 chars.  By setting
+CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
+if x == 0 or is unset one of the fallbacks is used.
+
 Usage:
    vrpc help [flags] [command/topic ...]
 
 [command/topic ...] optionally identifies a specific sub-command or help topic.
 
-The help flags are:
-   -style=text: The formatting style for help output, either "text" or "godoc".
+The vrpc help flags are:
+ -style=text
+   The formatting style for help output, either "text" or "godoc".
 */
 package main
diff --git a/tools/vrpc/impl.go b/tools/vrpc/impl.go
index 7d0e560..3133ea4 100644
--- a/tools/vrpc/impl.go
+++ b/tools/vrpc/impl.go
@@ -13,7 +13,6 @@
 	"veyron.io/veyron/veyron2/context"
 	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/naming"
-	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/vdl/vdlutil"
 	"veyron.io/veyron/veyron2/vom"
 	"veyron.io/veyron/veyron2/wiretype"
@@ -53,8 +52,6 @@
 		return cmd.UsageErrorf("describe: incorrect number of arguments, expected 1, got %d", len(args))
 	}
 
-	runtime := rt.R()
-
 	client, err := setupClient(cmd, runtime)
 	if err != nil {
 		return err
@@ -93,8 +90,6 @@
 	}
 	server, method, args := args[0], args[1], args[2:]
 
-	runtime := rt.R()
-
 	client, err := setupClient(cmd, runtime)
 	if err != nil {
 		return err
@@ -126,15 +121,15 @@
 	// Benj implements support for decoding arbitrary structs to an
 	// empty interface, this will no longer be needed.
 	var x1 idl_test_base.Struct
-	vom.Register(x1)
+	vdlutil.Register(x1)
 	var x2 idl_node.Description
-	vom.Register(x2)
+	vdlutil.Register(x2)
 	var x3 idl_binary.Description
-	vom.Register(x3)
+	vdlutil.Register(x3)
 	var x4 naming.VDLMountedServer
-	vom.Register(x4)
+	vdlutil.Register(x4)
 	var x5 naming.VDLMountEntry
-	vom.Register(x5)
+	vdlutil.Register(x5)
 
 	// Decode the inputs from vomJSON-formatted command-line arguments.
 	inputs := make([]interface{}, len(args))
diff --git a/tools/vrpc/impl_test.go b/tools/vrpc/impl_test.go
index f585f2b..cfbef5d 100644
--- a/tools/vrpc/impl_test.go
+++ b/tools/vrpc/impl_test.go
@@ -169,7 +169,13 @@
 }
 
 func TestVRPC(t *testing.T) {
-	runtime := rt.Init()
+	var err error
+	runtime, err = rt.New()
+	if err != nil {
+		t.Fatalf("Unexpected error initializing runtime: %s", err)
+	}
+	defer runtime.Cleanup()
+
 	// Skip defer runtime.Cleanup() to avoid messing up other tests in the
 	// same process.
 	server, endpoint, err := startServer(t, runtime)
diff --git a/tools/vrpc/main.go b/tools/vrpc/main.go
index f52ab6f..3723981 100644
--- a/tools/vrpc/main.go
+++ b/tools/vrpc/main.go
@@ -1,13 +1,23 @@
 // The following enables go generate to generate the doc.go file.
-//go:generate go run $VEYRON_ROOT/lib/cmdline/testdata/gendoc.go .
+//go:generate go run $VEYRON_ROOT/veyron/go/src/veyron.io/lib/cmdline/testdata/gendoc.go .
 
 package main
 
 import (
+	"veyron.io/veyron/veyron2"
 	"veyron.io/veyron/veyron2/rt"
+
+	_ "veyron.io/veyron/veyron/profiles"
 )
 
+var runtime veyron2.Runtime
+
 func main() {
-	defer rt.Init().Cleanup()
+	var err error
+	runtime, err = rt.New()
+	if err != nil {
+		panic(err)
+	}
+	defer runtime.Cleanup()
 	root().Main()
 }
diff --git a/tools/vrpc/test_base/test_base.vdl.go b/tools/vrpc/test_base/test_base.vdl.go
index eec0c49..a411da3 100644
--- a/tools/vrpc/test_base/test_base.vdl.go
+++ b/tools/vrpc/test_base/test_base.vdl.go
@@ -9,6 +9,7 @@
 	__veyron2 "veyron.io/veyron/veyron2"
 	__context "veyron.io/veyron/veyron2/context"
 	__ipc "veyron.io/veyron/veyron2/ipc"
+	__vdl "veyron.io/veyron/veyron2/vdl"
 	__vdlutil "veyron.io/veyron/veyron2/vdl/vdlutil"
 	__wiretype "veyron.io/veyron/veyron2/wiretype"
 )
@@ -23,6 +24,15 @@
 	Y int32
 }
 
+func (Struct) __VDLReflect(struct {
+	Name string "veyron.io/veyron/veyron/tools/vrpc/test_base.Struct"
+}) {
+}
+
+func init() {
+	__vdl.Register(Struct{})
+}
+
 // TypeTesterClientMethods is the client interface
 // containing TypeTester methods.
 type TypeTesterClientMethods interface {