Merge "veyron2/vom2: Support typeobject decoding."
diff --git a/runtimes/GO.PACKAGE b/runtimes/GO.PACKAGE
index b80bb38..729132d 100644
--- a/runtimes/GO.PACKAGE
+++ b/runtimes/GO.PACKAGE
@@ -2,9 +2,10 @@
 	"dependencies": {
 		"incoming": [
 			{"allow": "veyron.io/veyron/veyron/runtimes/..."},
-			{"allow": "veyron.io/veyron/veyron/services/...", "comment": "temporarily allowing dependency from services"},
 			{"allow": "veyron.io/veyron/veyron2/rt/..."},
 			{"allow": "veyron.io/veyron/veyron/lib/...", "comment":"temporarily allowing dependency from lib"},
+			{"allow": "veyron.io/veyron/veyron/profiles/...", "comment":"temporarily allowing dependency from profiles"},
+			{"allow": "veyron.io/veyron/veyron/services/...", "comment": "temporarily allowing dependency from services"},
 			{"deny": "..."}
 		]
 	}
diff --git a/runtimes/google/ipc/client.go b/runtimes/google/ipc/client.go
index 8451c3e..c4903d2 100644
--- a/runtimes/google/ipc/client.go
+++ b/runtimes/google/ipc/client.go
@@ -590,13 +590,15 @@
 // validation for a server's blessings are eanbled.
 // Returning zero values affects more than third-party caveats, so yeah, have
 // to remove them soon!
-func (c serverAuthContext) Timestamp() time.Time                    { return c.timestamp }
-func (serverAuthContext) Method() string                            { return "" }
-func (serverAuthContext) MethodTags() []interface{}                 { return nil }
-func (serverAuthContext) Name() string                              { return "" }
-func (serverAuthContext) Suffix() string                            { return "" }
-func (serverAuthContext) Label() (l security.Label)                 { return l }
-func (serverAuthContext) Discharges() map[string]security.Discharge { return nil }
+func (c serverAuthContext) Timestamp() time.Time    { return c.timestamp }
+func (serverAuthContext) Method() string            { return "" }
+func (serverAuthContext) MethodTags() []interface{} { return nil }
+func (serverAuthContext) Name() string              { return "" }
+func (serverAuthContext) Suffix() string            { return "" }
+func (serverAuthContext) Label() (l security.Label) { return l }
+
+// TODO(ataly): Remove this once the method is added to the flow type?
+func (serverAuthContext) RemoteDischarges() map[string]security.Discharge { return nil }
 
 func splitObjectName(name string) (mtPattern, serverPattern security.BlessingPattern, objectName string) {
 	objectName = name
diff --git a/runtimes/google/ipc/server.go b/runtimes/google/ipc/server.go
index 522ead9..649e8b4 100644
--- a/runtimes/google/ipc/server.go
+++ b/runtimes/google/ipc/server.go
@@ -22,6 +22,8 @@
 	"veyron.io/veyron/veyron2/vtrace"
 
 	"veyron.io/veyron/veyron/lib/netstate"
+	"veyron.io/veyron/veyron/lib/stats"
+	"veyron.io/veyron/veyron/runtimes/google/ipc/stream/vc"
 	"veyron.io/veyron/veyron/runtimes/google/lib/publisher"
 	inaming "veyron.io/veyron/veyron/runtimes/google/naming"
 	ivtrace "veyron.io/veyron/veyron/runtimes/google/vtrace"
@@ -68,6 +70,7 @@
 
 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())
 	s := &server{
 		ctx:         ctx,
 		streamMgr:   streamMgr,
@@ -75,20 +78,40 @@
 		listeners:   make(map[stream.Listener]*dhcpListener),
 		stoppedChan: make(chan struct{}),
 		ns:          ns,
-		stats:       newIPCStats(naming.Join("ipc", "server", streamMgr.RoutingID().String())),
+		stats:       newIPCStats(statsPrefix),
 		traceStore:  store,
 	}
+	var (
+		principal security.Principal
+		blessings security.Blessings
+	)
 	for _, opt := range opts {
 		switch opt := opt.(type) {
 		case stream.ListenerOpt:
 			// Collect all ServerOpts that are also ListenerOpts.
 			s.listenerOpts = append(s.listenerOpts, opt)
+			switch opt := opt.(type) {
+			case vc.LocalPrincipal:
+				principal = opt.Principal
+			case options.ServerBlessings:
+				blessings = opt.Blessings
+			}
 		case options.ServesMountTable:
 			s.servesMountTable = bool(opt)
 		case options.ReservedNameDispatcher:
 			s.reservedOpt = opt
 		}
 	}
+	blessingsStatsName := naming.Join(statsPrefix, "security", "blessings")
+	if blessings != nil {
+		// TODO(caprita): revist printing the blessings with %s, and
+		// instead expose them as a list.
+		stats.NewString(blessingsStatsName).Set(fmt.Sprintf("%s", blessings))
+	} else if principal != nil { // principal should have been passed in, but just in case.
+		stats.NewStringFunc(blessingsStatsName, func() string {
+			return fmt.Sprintf("%s (default)", principal.BlessingStore().Default())
+		})
+	}
 	return s, nil
 }
 
@@ -472,11 +495,14 @@
 	s.Lock()
 	defer s.Unlock()
 	ivtrace.FromContext(s.ctx).Annotate("Serving under name: " + name)
+	if len(name) == 0 {
+		return fmt.Errorf("empty name")
+	}
 	if s.stopped {
 		return errServerStopped
 	}
-	if len(name) == 0 {
-		return fmt.Errorf("empty name")
+	if s.disp == nil {
+		return fmt.Errorf("Adding name before calling Serve or ServeDispatcher is not allowed")
 	}
 	s.publisher.AddName(name)
 	// TODO(cnicolaou): remove this map when the publisher's RemoveName
@@ -492,6 +518,9 @@
 	if s.stopped {
 		return errServerStopped
 	}
+	if s.disp == nil {
+		return fmt.Errorf("Removing name before calling Serve or ServeDispatcher is not allowed")
+	}
 	if _, present := s.names[name]; !present {
 		return fmt.Errorf("%q has not been previously used for this server", name)
 	}
@@ -898,7 +927,7 @@
 
 // Implementations of ipc.ServerContext methods.
 
-func (fs *flowServer) Discharges() map[string]security.Discharge {
+func (fs *flowServer) RemoteDischarges() map[string]security.Discharge {
 	//nologcall
 	return fs.discharges
 }
diff --git a/runtimes/google/ipc/stats.go b/runtimes/google/ipc/stats.go
index 5f6f2ed..334ce23 100644
--- a/runtimes/google/ipc/stats.go
+++ b/runtimes/google/ipc/stats.go
@@ -48,7 +48,7 @@
 	defer s.mu.Unlock()
 	m, ok := s.methods[method]
 	if !ok {
-		name := naming.Join(s.prefix, method, "latency-ms")
+		name := naming.Join(s.prefix, "methods", method, "latency-ms")
 		s.methods[method] = &perMethodStats{
 			latency: stats.NewHistogram(name, histogram.Options{
 				NumBuckets:         25,
diff --git a/runtimes/google/ipc/stream/vc/auth.go b/runtimes/google/ipc/stream/vc/auth.go
index 439ead8..5fe37cf 100644
--- a/runtimes/google/ipc/stream/vc/auth.go
+++ b/runtimes/google/ipc/stream/vc/auth.go
@@ -5,13 +5,11 @@
 	"errors"
 	"fmt"
 	"io"
-	"time"
 
 	"veyron.io/veyron/veyron/runtimes/google/ipc/stream/crypto"
 	"veyron.io/veyron/veyron/runtimes/google/lib/iobuf"
 
 	"veyron.io/veyron/veyron2/ipc/version"
-	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/security"
 	"veyron.io/veyron/veyron2/vom"
 )
@@ -58,10 +56,9 @@
 	if server, err = readBlessings(conn, authServerContextTag, crypter, v); err != nil {
 		return nil, nil, err
 	}
-	serverB := server.ForContext(&serverAuthContext{
-		self:      principal,
-		remote:    server,
-		timestamp: time.Now(),
+	serverB := server.ForContext(security.NewContext(&security.ContextParams{
+		LocalPrincipal:  principal,
+		RemoteBlessings: server,
 		// TODO(ashankar): Get the local and remote endpoint here?
 		// There is also a bootstrapping problem here. For example, let's say
 		// (1) server has the blessing "provider/server" with a PeerIdentity caveat of "provider/client"
@@ -69,7 +66,7 @@
 		// How do we get that working?
 		// One option is to have a UnionOfBlessings of all blessings of the client in the BlessingStore
 		// made available to serverAuthContext.LocalBlessings for this call.
-	})
+	}))
 	client = principal.BlessingStore().ForPeer(serverB...)
 	if client == nil {
 		return nil, nil, fmt.Errorf("no blessing tagged for peer %v in the BlessingStore", serverB)
@@ -132,24 +129,3 @@
 	}
 	return b, nil
 }
-
-// security.Context implementation used when extracting blessings from what the
-// server presents during authentication.
-type serverAuthContext struct {
-	self      security.Principal
-	remote    security.Blessings
-	timestamp time.Time
-}
-
-func (c *serverAuthContext) Timestamp() time.Time                      { return c.timestamp }
-func (*serverAuthContext) Method() string                              { return "" }
-func (*serverAuthContext) MethodTags() []interface{}                   { return nil }
-func (*serverAuthContext) Name() string                                { return "" }
-func (*serverAuthContext) Suffix() string                              { return "" }
-func (*serverAuthContext) Label() (l security.Label)                   { return l }
-func (c *serverAuthContext) Discharges() map[string]security.Discharge { return nil }
-func (c *serverAuthContext) LocalPrincipal() security.Principal        { return c.self }
-func (c *serverAuthContext) LocalBlessings() security.Blessings        { return nil }
-func (c *serverAuthContext) RemoteBlessings() security.Blessings       { return c.remote }
-func (c *serverAuthContext) LocalEndpoint() naming.Endpoint            { return nil }
-func (c *serverAuthContext) RemoteEndpoint() naming.Endpoint           { return nil }
diff --git a/runtimes/google/lib/follow/bsd_darwin_linux_windows_config.go b/runtimes/google/lib/follow/bsd_darwin_linux_windows_config.go
deleted file mode 100644
index 09a9cf9..0000000
--- a/runtimes/google/lib/follow/bsd_darwin_linux_windows_config.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// +build darwin freebsd linux netbsd openbsd windows
-
-package follow
-
-// newFSWatcher starts and returns a new fsnotify-based fsWatcher.
-// filename specifies the file to watch.
-func newFSWatcher(filename string) (fsWatcher, error) {
-	return newFSNotifyWatcher(filename)
-}
diff --git a/runtimes/google/lib/follow/notify_reader_test.go b/runtimes/google/lib/follow/notify_reader_test.go
deleted file mode 100644
index 380f6ce..0000000
--- a/runtimes/google/lib/follow/notify_reader_test.go
+++ /dev/null
@@ -1,79 +0,0 @@
-// +build darwin freebsd linux netbsd openbsd windows
-
-package follow
-
-import (
-	"io/ioutil"
-	"os"
-	"testing"
-	"time"
-)
-
-// TestNotifyReadPartial tests partial reads with the fsnotify-based fsReader
-func TestNotifyReadPartial(t *testing.T) {
-	// Create the test file.
-	testFile, err := ioutil.TempFile(os.TempDir(), "follow.reader.notify.partial")
-	if err != nil {
-		t.Fatalf("ioutil.TempFile() failed: %v", err)
-	}
-	testFile.Close()
-	testFileName := testFile.Name()
-	defer os.Remove(testFileName)
-
-	// Create the fsnotify-based fsWatcher.
-	watcher, err := newFSNotifyWatcher(testFileName)
-	if err != nil {
-		t.Fatalf("newCustomFSWatcher() failed: %v", err)
-	}
-
-	timeout := time.Second
-	if err := testReadPartial(testFileName, watcher, timeout); err != nil {
-		t.Fatal("testReadPartial() failed: %v", err)
-	}
-}
-
-// TestNotifyReadFull tests full reads with the fsnotify-based fsReader
-func TestNotifyReadFull(t *testing.T) {
-	// Create the test file.
-	testFile, err := ioutil.TempFile(os.TempDir(), "follow.reader.notify.full")
-	if err != nil {
-		t.Fatalf("ioutil.TempFile() failed: %v", err)
-	}
-	testFile.Close()
-	testFileName := testFile.Name()
-	defer os.Remove(testFileName)
-
-	// Create the fsnotify-based fsWatcher.
-	watcher, err := newFSNotifyWatcher(testFileName)
-	if err != nil {
-		t.Fatalf("newCustomFSWatcher() failed: %v", err)
-	}
-
-	timeout := time.Second
-	if err := testReadFull(testFileName, watcher, timeout); err != nil {
-		t.Fatal("testReadFull() failed: %v", err)
-	}
-}
-
-// TestNotifyClose tests close with the fsnotify-based fsReader
-func TestNotifyClose(t *testing.T) {
-	// Create the test file.
-	testFile, err := ioutil.TempFile(os.TempDir(), "follow.reader.notify.close")
-	if err != nil {
-		t.Fatalf("ioutil.TempFile() failed: %v", err)
-	}
-	testFile.Close()
-	testFileName := testFile.Name()
-	defer os.Remove(testFileName)
-
-	// Create the fsnotify-based fsWatcher.
-	watcher, err := newFSNotifyWatcher(testFileName)
-	if err != nil {
-		t.Fatalf("newCustomFSWatcher() failed: %v", err)
-	}
-
-	timeout := time.Second
-	if err := testClose(testFileName, watcher, timeout); err != nil {
-		t.Fatal("testClose() failed: %v", err)
-	}
-}
diff --git a/runtimes/google/lib/follow/notify_watcher.go b/runtimes/google/lib/follow/notify_watcher.go
deleted file mode 100644
index ed79e9f..0000000
--- a/runtimes/google/lib/follow/notify_watcher.go
+++ /dev/null
@@ -1,85 +0,0 @@
-// +build darwin freebsd linux netbsd openbsd windows
-
-package follow
-
-import (
-	"fmt"
-	"github.com/howeyc/fsnotify"
-	"io"
-	"sync"
-
-	vsync "veyron.io/veyron/veyron/runtimes/google/lib/sync"
-)
-
-type fsNotifyWatcher struct {
-	filename string
-	source   *fsnotify.Watcher
-	// cancel signals Wait to terminate.
-	cancel chan struct{}
-	// pending allows Close to block till ongoing calls to Wait terminate.
-	pending vsync.WaitGroup
-	// mu and closed ensure that Close is idempotent.
-	mu     sync.Mutex
-	closed bool // GUARDED_BY(mu)
-}
-
-// newFSNotifyWatcher returns an fsnotify-based fsWatcher.
-// Wait() blocks until it receives a file modification event from fsnotify.
-func newFSNotifyWatcher(filename string) (fsWatcher, error) {
-	source, err := fsnotify.NewWatcher()
-	if err != nil {
-		return nil, err
-	}
-	if err := source.Watch(filename); err != nil {
-		source.Close()
-		return nil, err
-	}
-	return &fsNotifyWatcher{
-		source: source,
-		cancel: make(chan struct{}),
-	}, nil
-}
-
-func (w *fsNotifyWatcher) Wait() error {
-	// After Close returns, any call to Wait must return io.EOF.
-	if !w.pending.TryAdd() {
-		return io.EOF
-	}
-	defer w.pending.Done()
-
-	for {
-		select {
-		case event := <-w.source.Event:
-			if event.IsModify() {
-				// Drain the event queue.
-				drained := false
-				for !drained {
-					select {
-					case <-w.source.Event:
-					default:
-						drained = true
-					}
-				}
-				return nil
-			}
-			return fmt.Errorf("Unexpected event %v", event)
-		case err := <-w.source.Error:
-			return err
-		case <-w.cancel:
-			// After Close returns, any call to Wait must return io.EOF.
-			return io.EOF
-		}
-	}
-}
-
-func (w *fsNotifyWatcher) Close() error {
-	w.mu.Lock()
-	defer w.mu.Unlock()
-	if w.closed {
-		return nil
-	}
-	w.closed = true
-	close(w.cancel)
-	w.pending.Wait()
-	return w.source.Close()
-}
diff --git a/runtimes/google/lib/follow/notify_watcher_test.go b/runtimes/google/lib/follow/notify_watcher_test.go
deleted file mode 100644
index 8ee84a5..0000000
--- a/runtimes/google/lib/follow/notify_watcher_test.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// +build darwin freebsd linux netbsd openbsd windows
-
-package follow
-
-import (
-	"io/ioutil"
-	"os"
-	"testing"
-	"time"
-)
-
-func TestModificationNotify(t *testing.T) {
-	// Create the test file.
-	testFile, err := ioutil.TempFile(os.TempDir(), "follow.modification.notify")
-	if err != nil {
-		t.Fatalf("ioutil.TempFile() failed: %v", err)
-	}
-	defer testFile.Close()
-	testFileName := testFile.Name()
-	defer os.Remove(testFileName)
-
-	watcher, err := newFSNotifyWatcher(testFileName)
-	if err != nil {
-		t.Fatalf("newCustomFSWatcer() failed: %v", err)
-	}
-	timeout := time.Second
-	if err := testModification(testFile, watcher, timeout); err != nil {
-		t.Fatalf("testModification() failed: %v", err)
-	}
-}
diff --git a/runtimes/google/lib/follow/other_config.go b/runtimes/google/lib/follow/other_config.go
deleted file mode 100644
index 8feb648..0000000
--- a/runtimes/google/lib/follow/other_config.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// +build !darwin,!freebsd,!linux,!netbsd,!openbsd,!windows
-
-package follow
-
-// newFSWatcher starts and returns a new os.Stat()-based fsWatcher.
-// filename specifies the file to watch.
-func newFSWatcher(filename string) (fsWatcher, error) {
-	return newFSStatWatcher(filename)
-}
diff --git a/runtimes/google/lib/follow/reader.go b/runtimes/google/lib/follow/reader.go
deleted file mode 100644
index ab488cd..0000000
--- a/runtimes/google/lib/follow/reader.go
+++ /dev/null
@@ -1,106 +0,0 @@
-package follow
-
-import (
-	"io"
-	"os"
-	"sync"
-)
-
-// fsReader is an implementation of io.ReadCloser that reads synchronously
-// from a file, blocking until at least one byte is written to the file and is
-// available for reading.
-type fsReader struct {
-	mu sync.Mutex
-	// The file to read.
-	file *os.File // GUARDED_BY(mu)
-	// The watcher of modifications to the file.
-	watcher fsWatcher
-	// True if the reader is open for reading, false otherwise.
-	closed bool // GUARDED_BY(mu)
-}
-
-// NewReader creates a new reader that reads synchronously from a file,
-// blocking until at least one byte is written to the file and is available
-// for reading.
-// The returned io.ReadCloser supports limited concurrency:
-// 1) Reads may not be called concurrently.
-// 2) Close may be called concurrently with Read, and will terminate Read.
-func NewReader(filename string) (reader io.ReadCloser, err error) {
-	var file *os.File
-	var watcher fsWatcher
-	defer func() {
-		if err == nil {
-			return
-		}
-		var closeFileErr, closeWatcherErr error
-		if file != nil {
-			closeFileErr = file.Close()
-		}
-		if watcher != nil {
-			closeWatcherErr = watcher.Close()
-		}
-		err = composeErrors(err, closeFileErr, closeWatcherErr)
-	}()
-	file, err = os.Open(filename)
-	if err != nil {
-		return nil, err
-	}
-	watcher, err = newFSWatcher(filename)
-	if err != nil {
-		return nil, err
-	}
-	return newCustomReader(file, watcher)
-}
-
-func newCustomReader(file *os.File, watcher fsWatcher) (io.ReadCloser, error) {
-	reader := &fsReader{
-		file:    file,
-		watcher: watcher,
-	}
-	return reader, nil
-}
-
-func (r *fsReader) Read(p []byte) (int, error) {
-	// If the reader has been closed, return an error.
-	r.mu.Lock()
-	if r.closed {
-		return 0, io.EOF
-	}
-
-	for {
-		// Read any bytes that are available.
-		if n, err := r.file.Read(p); err != io.EOF {
-			r.mu.Unlock()
-			return n, err
-		}
-		r.mu.Unlock()
-
-		// Wait until the file is modified one or more times. The new
-		// bytes from each corresponding modification have been
-		// written to the file already, and therefore won't be skipped.
-		if err := r.watcher.Wait(); err != nil {
-			return 0, err
-		}
-
-		r.mu.Lock()
-	}
-}
-
-// Close closes the reader synchronously.
-// 1) Terminates ongoing reads. (reads return io.EOF)
-// 2) Prevents future reads. (reads return io.EOF)
-// 3) Frees system resources associated with the reader.
-// Close is idempotent.
-func (r *fsReader) Close() error {
-	r.mu.Lock()
-	defer r.mu.Unlock()
-	if r.closed {
-		return nil
-	}
-	// Mark the reader closed.
-	r.closed = true
-	// Release resources.
-	closeFileErr := r.file.Close()
-	closeWatcherErr := r.watcher.Close()
-	return composeErrors(closeFileErr, closeWatcherErr)
-}
diff --git a/runtimes/google/lib/follow/stat_reader_test.go b/runtimes/google/lib/follow/stat_reader_test.go
deleted file mode 100644
index 21adb53..0000000
--- a/runtimes/google/lib/follow/stat_reader_test.go
+++ /dev/null
@@ -1,83 +0,0 @@
-package follow
-
-import (
-	"io/ioutil"
-	"os"
-	"testing"
-	"time"
-)
-
-// TestStatReadPartial tests partial reads with the os.Stat()-based fsReader
-func TestStatReadPartial(t *testing.T) {
-	// Create the test file.
-	testFile, err := ioutil.TempFile(os.TempDir(), "follow.reader.stat.partial")
-	if err != nil {
-		t.Fatalf("ioutil.TempFile() failed: %v", err)
-	}
-	testFile.Close()
-	testFileName := testFile.Name()
-	defer os.Remove(testFileName)
-
-	// Create the os.Stat()-based fsWatcher.
-	minSleep := 10 * time.Millisecond
-	maxSleep := 100 * time.Millisecond
-	watcher, err := newCustomFSStatWatcher(testFileName, minSleep, maxSleep)
-	if err != nil {
-		t.Fatalf("newCustomFSWatcher() failed: %v", err)
-	}
-
-	timeout := time.Second
-	if err := testReadPartial(testFileName, watcher, timeout); err != nil {
-		t.Fatalf("testReadPartial() failed: %v", err)
-	}
-}
-
-// TestStatReadFull tests full reads with the os.Stat()-based fsReader
-func TestStatReadFull(t *testing.T) {
-	// Create the test file.
-	testFile, err := ioutil.TempFile(os.TempDir(), "follow.reader.stat.full")
-	if err != nil {
-		t.Fatalf("ioutil.TempFile() failed: %v", err)
-	}
-	testFile.Close()
-	testFileName := testFile.Name()
-	defer os.Remove(testFileName)
-
-	// Create the os.Stat()-based fsWatcher.
-	minSleep := 10 * time.Millisecond
-	maxSleep := 100 * time.Millisecond
-	watcher, err := newCustomFSStatWatcher(testFileName, minSleep, maxSleep)
-	if err != nil {
-		t.Fatalf("newCustomFSWatcher() failed: %v", err)
-	}
-
-	timeout := time.Second
-	if err := testReadFull(testFileName, watcher, timeout); err != nil {
-		t.Fatalf("testReadFull() failed: %v", err)
-	}
-}
-
-// TestStatClose tests close with the os.Stat()-based fsReader
-func TestStatClose(t *testing.T) {
-	// Create the test file.
-	testFile, err := ioutil.TempFile(os.TempDir(), "follow.reader.stat.close")
-	if err != nil {
-		t.Fatalf("ioutil.TempFile() failed: %v", err)
-	}
-	testFile.Close()
-	testFileName := testFile.Name()
-	defer os.Remove(testFileName)
-
-	// Create the os.Stat()-based fsWatcher.
-	minSleep := 10 * time.Millisecond
-	maxSleep := 100 * time.Millisecond
-	watcher, err := newCustomFSStatWatcher(testFileName, minSleep, maxSleep)
-	if err != nil {
-		t.Fatalf("newCustomFSWatcher() failed: %v", err)
-	}
-
-	timeout := time.Second
-	if err := testClose(testFileName, watcher, timeout); err != nil {
-		t.Fatalf("testClose() failed: %v", err)
-	}
-}
diff --git a/runtimes/google/lib/follow/stat_watcher.go b/runtimes/google/lib/follow/stat_watcher.go
deleted file mode 100644
index 6c288f8..0000000
--- a/runtimes/google/lib/follow/stat_watcher.go
+++ /dev/null
@@ -1,100 +0,0 @@
-package follow
-
-import (
-	"io"
-	"os"
-	"sync"
-	"time"
-
-	vsync "veyron.io/veyron/veyron/runtimes/google/lib/sync"
-)
-
-const (
-	defaultMinSleep = 10 * time.Millisecond
-	defaultMaxSleep = 5 * time.Second
-)
-
-type fsStatWatcher struct {
-	minSleep     time.Duration
-	maxSleep     time.Duration
-	file         *os.File
-	lastFileSize int64
-	// cancel signals Wait to terminate.
-	cancel chan struct{}
-	// pending allows Close to block till ongoing calls to Wait terminate.
-	pending vsync.WaitGroup
-	// mu and closed ensure that Close is idempotent.
-	mu     sync.Mutex
-	closed bool // GUARDED_BY(mu)
-}
-
-// newFSStatWatcher returns an fsWatcher that polls os.Stat(), observing file
-// size. If the file size is larger than the previously-recorded file size,
-// the watcher assumes the file has been modified.
-// Wait() polls os.Stat() at an interval specified by minSleep, doubling that
-// interval as long the file is not modified, upto a maximum interval specified
-// by maxSleep. This allows faster detection during periods of frequent
-// modification but conserves resources during periods of inactivity.
-// The default values of minSleep and maxSleep can be overriden using the
-// newCustomFSStatWatcher() constructor.
-func newFSStatWatcher(filename string) (fsWatcher, error) {
-	return newCustomFSStatWatcher(filename, defaultMinSleep, defaultMaxSleep)
-}
-
-func newCustomFSStatWatcher(filename string, minSleep, maxSleep time.Duration) (fsWatcher, error) {
-	file, err := os.Open(filename)
-	if err != nil {
-		return nil, err
-	}
-	fileInfo, err := file.Stat()
-	if err != nil {
-		file.Close()
-		return nil, err
-	}
-	return &fsStatWatcher{
-		minSleep:     minSleep,
-		maxSleep:     maxSleep,
-		file:         file,
-		lastFileSize: fileInfo.Size(),
-		cancel:       make(chan struct{}),
-	}, nil
-}
-
-func (w *fsStatWatcher) Wait() error {
-	// After Close returns, any call to Wait must return io.EOF.
-	if !w.pending.TryAdd() {
-		return io.EOF
-	}
-	defer w.pending.Done()
-
-	sleep := w.minSleep
-	for {
-		select {
-		case <-w.cancel:
-			// After Close returns, any call to Wait must return io.EOF.
-			return io.EOF
-		default:
-		}
-		fileInfo, err := w.file.Stat()
-		if err != nil {
-			return err
-		} else if fileSize := fileInfo.Size(); w.lastFileSize < fileSize {
-			w.lastFileSize = fileSize
-			return nil
-		}
-		time.Sleep(sleep)
-		sleep = minDuration(sleep*2, w.maxSleep)
-	}
-}
-
-func (w *fsStatWatcher) Close() error {
-	w.mu.Lock()
-	defer w.mu.Unlock()
-	if w.closed {
-		return nil
-	}
-	w.closed = true
-	close(w.cancel)
-	w.pending.Wait()
-	return w.file.Close()
-}
diff --git a/runtimes/google/lib/follow/stat_watcher_test.go b/runtimes/google/lib/follow/stat_watcher_test.go
deleted file mode 100644
index 67d14e8..0000000
--- a/runtimes/google/lib/follow/stat_watcher_test.go
+++ /dev/null
@@ -1,30 +0,0 @@
-package follow
-
-import (
-	"io/ioutil"
-	"os"
-	"testing"
-	"time"
-)
-
-func TestModificationStat(t *testing.T) {
-	// Create the test file.
-	testFile, err := ioutil.TempFile(os.TempDir(), "follow.modification.stat")
-	if err != nil {
-		t.Fatalf("ioutil.TempFile() failed: %v", err)
-	}
-	defer testFile.Close()
-	testFileName := testFile.Name()
-	defer os.Remove(testFileName)
-
-	minSleep := 10 * time.Millisecond
-	maxSleep := 100 * time.Millisecond
-	watcher, err := newCustomFSStatWatcher(testFileName, minSleep, maxSleep)
-	if err != nil {
-		t.Fatalf("newCustomFSWatcher() failed : %v", err)
-	}
-	timeout := 100 * time.Millisecond
-	if err := testModification(testFile, watcher, timeout); err != nil {
-		t.Fatalf("testModification() failed: %v", err)
-	}
-}
diff --git a/runtimes/google/lib/follow/test_util.go b/runtimes/google/lib/follow/test_util.go
deleted file mode 100644
index 0da3fac..0000000
--- a/runtimes/google/lib/follow/test_util.go
+++ /dev/null
@@ -1,279 +0,0 @@
-package follow
-
-import (
-	"errors"
-	"fmt"
-	"io"
-	"os"
-	"time"
-)
-
-var (
-	errTimedOut               = errors.New("timed out")
-	errCantAppend             = errors.New("cannot append string to file")
-	errUnexpectedModification = errors.New("unexpected modification event")
-)
-
-func events(watcher fsWatcher) <-chan error {
-	events := make(chan error)
-	go func() {
-		for {
-			event := watcher.Wait()
-			events <- event
-			if event == io.EOF {
-				break
-			}
-		}
-	}()
-	return events
-}
-
-// readString reads a string of the specified length from the reader.
-// Returns an error if:
-//  (A) reader.Read returned an error
-//  (A) reader.Read timed out
-func readString(reader io.Reader, length int, timeout time.Duration) (string, error) {
-	p := make([]byte, length, length)
-
-	c := make(chan string)
-	e := make(chan error)
-	go func() {
-		n, err := reader.Read(p)
-		if err != nil {
-			e <- err
-			return
-		}
-		c <- string(p[:n])
-	}()
-
-	timer := time.After(timeout)
-	select {
-	case err := <-e:
-		return "", err
-	case s := <-c:
-		return s, nil
-	case <-timer:
-		return "", errTimedOut
-	}
-}
-
-// writeString appends a string to a file, and flushes its new contents to
-// stable storage.
-func writeString(file *os.File, s string) error {
-	n, err := io.WriteString(file, s)
-	if err != nil {
-		return errors.New(fmt.Sprintf("io.WriteString() failed: %v", err))
-	}
-	if n < len(s) {
-		return errCantAppend
-	}
-	file.Sync()
-	return nil
-}
-
-// expectSilence tests that no events are received on the events channel
-// within the duration specified by timeout.
-func expectSilence(events <-chan error, timeout time.Duration) error {
-	timer := time.After(timeout)
-	select {
-	case err := <-events:
-		if err != nil {
-			return err
-		}
-		return errUnexpectedModification
-	case <-timer:
-		// all's well
-		return nil
-	}
-}
-
-// expectModification tests that a modification event is received on the events
-// channel within the duration specified by timeout.
-func expectModification(events <-chan error, timeout time.Duration) error {
-	timer := time.After(timeout)
-	select {
-	case <-timer:
-		return errTimedOut
-	case err := <-events:
-		if err != nil {
-			return err
-		}
-		// all's well
-		return nil
-	}
-}
-
-// testModification tests that the watcher sends events when the file is
-// modified.
-func testModification(file *os.File, watcher fsWatcher, timeout time.Duration) error {
-	events := events(watcher)
-	// no modifications, expect no events.
-	if err := expectSilence(events, timeout); err != nil {
-		return errors.New(fmt.Sprintf("expectSilence() failed with no modifications: %v ", err))
-	}
-	// modify once, expect event.
-	if err := writeString(file, "modification one"); err != nil {
-		return errors.New(fmt.Sprintf("writeString() failed on modification one: %v ", err))
-	}
-	if err := expectModification(events, timeout); err != nil {
-		return errors.New(fmt.Sprintf("expectModication() failed on modification one: %v ", err))
-	}
-	// no further modifications, expect no events.
-	if err := expectSilence(events, timeout); err != nil {
-		return errors.New(fmt.Sprintf("expectSilence() failed after modification one: %v ", err))
-	}
-	// modify again, expect event.
-	if err := writeString(file, "modification two"); err != nil {
-		return errors.New(fmt.Sprintf("writeString() failed on modification two: %v ", err))
-	}
-	if err := expectModification(events, time.Hour); err != nil {
-		return errors.New(fmt.Sprintf("expectModification() failed on modification two: %v ", err))
-	}
-	// no further modifications, expect no events.
-	if err := expectSilence(events, timeout); err != nil {
-		return errors.New(fmt.Sprintf("expectSilence() failed after modification two: %v ", err))
-	}
-	return nil
-}
-
-// testClose tests the implementation of fsReader.Read(). Specifically,
-// tests that Read() blocks if the requested bytes are not available for
-// reading in the underlying file.
-func testReadPartial(testFileName string, watcher fsWatcher, timeout time.Duration) error {
-	s0 := "part"
-
-	// Open the file for writing.
-	testfileW, err := os.OpenFile(testFileName, os.O_WRONLY, 0)
-	if err != nil {
-		return errors.New(fmt.Sprintf("os.OpenFile() failed: %v", err))
-	}
-	defer testfileW.Close()
-
-	// Open the file for reading.
-	testfileR, err := os.Open(testFileName)
-	if err != nil {
-		return errors.New(fmt.Sprintf("os.Open() failed: %v", err))
-	}
-	// Create the reader.
-	reader, err := newCustomReader(testfileR, watcher)
-	if err != nil {
-		return errors.New(fmt.Sprintf("newCustomReader() failed: %v", err))
-	}
-	defer reader.Close()
-
-	// Write a part of the string.
-	if err := writeString(testfileW, s0); err != nil {
-		return errors.New(fmt.Sprintf("writeString() failed: %v ", err))
-	}
-
-	// Some bytes written, but not enough to fill the buffer. Read should
-	// still succeed.
-	s, err := readString(reader, len(s0)+1, timeout)
-	if s != s0 {
-		return errors.New(fmt.Sprintf("Expected to read: %v, but read: %v", s0, s))
-	}
-	// No more bytes written, so read should block.
-	s, err = readString(reader, len(s0)+1, timeout)
-	if err != errTimedOut {
-		return errors.New(fmt.Sprintf("readString() failed, expected timeout: %v", err))
-	}
-	if s != "" {
-		return errors.New(fmt.Sprintf("Did not expect to read: %v", s))
-	}
-
-	return nil
-}
-
-// testClose tests the implementation of fsReader.Read(). Specifically,
-// tests that Read() returns the requested bytes when they are available
-// for reading in the underlying file.
-func testReadFull(testFileName string, watcher fsWatcher, timeout time.Duration) error {
-	s0, s1, s2 := "partitioned", "parti", "tioned"
-
-	// Open the file for writing.
-	testfileW, err := os.OpenFile(testFileName, os.O_WRONLY, 0)
-	if err != nil {
-		return errors.New(fmt.Sprintf("os.Open() failed: %v", err))
-	}
-	defer testfileW.Close()
-
-	// Open the file for reading.
-	testfileR, err := os.Open(testFileName)
-	if err != nil {
-		return errors.New(fmt.Sprintf("os.Open() failed: %v", err))
-	}
-	// Create the reader.
-	reader, err := newCustomReader(testfileR, watcher)
-	if err != nil {
-		return errors.New(fmt.Sprintf("newCustomReader() failed: %v", err))
-	}
-	defer reader.Close()
-
-	// Write part one of the string.
-	if err := writeString(testfileW, s1); err != nil {
-		return errors.New(fmt.Sprintf("writeString() failed on part one: %v ", err))
-	}
-
-	// Write part two of the string.
-	if err := writeString(testfileW, s2); err != nil {
-		return errors.New(fmt.Sprintf("writeString() failed on part two: %v ", err))
-	}
-
-	// Enough bytes written, so read should succeed.
-	s, err := readString(reader, len(s0), timeout)
-	if err != nil {
-		return errors.New(fmt.Sprintf("readString() failed: %v", err))
-	}
-	if s != s0 {
-		return errors.New(fmt.Sprintf("Expected to read: %v, but read: %v", s0, s))
-	}
-
-	return nil
-}
-
-// testClose tests the implementation of fsReader.Close()
-func testClose(testFileName string, watcher fsWatcher, timeout time.Duration) error {
-	s := "word"
-
-	// Open the file for writing.
-	testfileW, err := os.OpenFile(testFileName, os.O_WRONLY, 0)
-	if err != nil {
-		return errors.New(fmt.Sprintf("os.OpenFile() failed: %v", err))
-	}
-	defer testfileW.Close()
-
-	// Open the file for reading.
-	testfileR, err := os.Open(testFileName)
-	if err != nil {
-		return errors.New(fmt.Sprintf("os.Open() failed: %v", err))
-	}
-	// Create the reader.
-	reader, err := newCustomReader(testfileR, watcher)
-	if err != nil {
-		return errors.New(fmt.Sprintf("newCustomReader() failed: %v", err))
-	}
-
-	// Close the reader.
-	if err := reader.Close(); err != nil {
-		return errors.New(fmt.Sprintf("Close() failed: %v", err))
-	}
-
-	// Close the reader again.
-	if err := reader.Close(); err != nil {
-		return errors.New(fmt.Sprintf("Duplicate Close() failed: %v", err))
-	}
-
-	// Write the string.
-	if err := writeString(testfileW, s); err != nil {
-		return errors.New(fmt.Sprintf("writeString() failed: %v ", err))
-	}
-
-	// Reader is closed, readString() should fail.
-	if _, err := readString(reader, len(s), timeout); err == nil {
-		return errors.New("Expected readString() to fail")
-	} else if err != io.EOF {
-		return errors.New(fmt.Sprintf("readString() failed with unexpected error: %v", err))
-	}
-
-	return nil
-}
diff --git a/runtimes/google/lib/follow/util.go b/runtimes/google/lib/follow/util.go
deleted file mode 100644
index a44d6b0..0000000
--- a/runtimes/google/lib/follow/util.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package follow
-
-import (
-	"bytes"
-	"errors"
-	"fmt"
-	"time"
-)
-
-// composeErrors composes several (some nil) errors, returning a single error:
-//  (A) If the input errors are all nil, nil is returned.
-//  (B) If exactly one error is non-nil, that error is returned.
-//  (C) Otherwise, a composite error is returned. The composite error message
-//      lists all non-nil individual error messages. However, the composite
-//      error does not provide direct access to individual errors.
-func composeErrors(errs ...error) error {
-	// n is the number of non-nil errors.
-	n := 0
-	// lastErr is the last-seen non-nil error.
-	var lastErr error
-	for _, err := range errs {
-		if err != nil {
-			n++
-			lastErr = err
-		}
-	}
-	// all input errors are nil, return nil.
-	if n == 0 {
-		return nil
-	}
-	// exactly one error is non-nil, return it.
-	if n == 1 {
-		return lastErr
-	}
-	// more than one error is non-nil, build a composite error message.
-	var msgBuffer bytes.Buffer
-	fmt.Fprintf(&msgBuffer, "Encountered %v errors:\n", n)
-	i := 0
-	for _, err := range errs {
-		if err != nil {
-			i++
-			fmt.Fprintf(&msgBuffer, "error %d: %v:\n", i, err)
-		}
-	}
-	return errors.New(msgBuffer.String())
-}
-
-// minDuration takes two durations and returns the shorter.
-func minDuration(d1, d2 time.Duration) time.Duration {
-	if d2 < d1 {
-		return d2
-	}
-	return d1
-}
diff --git a/runtimes/google/lib/follow/util_test.go b/runtimes/google/lib/follow/util_test.go
deleted file mode 100644
index 653dacd..0000000
--- a/runtimes/google/lib/follow/util_test.go
+++ /dev/null
@@ -1,57 +0,0 @@
-package follow
-
-import (
-	"errors"
-	"strings"
-	"testing"
-)
-
-// TestComposeErrors tests composeErrors() with combinations of nil and non-nil inputs
-func TestComposeErrors(t *testing.T) {
-	// no errors compose to a nil error.
-	if err := composeErrors(); err != nil {
-		t.Fatalf("Expected composeErrors() to return nil, not: %v", err)
-	}
-	// a single nil error composes to a nil error.
-	if err := composeErrors(nil); err != nil {
-		t.Fatalf("Expected composeErrors(nil) to return nil, not: %v", err)
-	}
-	// multiple nil errors compose to a nil error.
-	if err := composeErrors(nil, nil); err != nil {
-		t.Fatalf("Expected composeErrors(nil, nil) to return nil, not: %v", err)
-	}
-	// a single non-nil error composes to itself.
-	err1 := errors.New("err1")
-	if err := composeErrors(err1); err != err1 {
-		t.Fatalf("Expected composeErrors(err) to return %v, not: %v", err1, err)
-	}
-	if err := composeErrors(nil, err1); err != err1 {
-		t.Fatalf("Expected composeErrors(nil, err) to return %v, not: %v", err1, err)
-	}
-	if err := composeErrors(err1, nil); err != err1 {
-		t.Fatalf("Expected composeErrors(err, nil) to return %v, not: %v", err1, err)
-	}
-	// multiple non-nil errors compose to composite error.
-	err2 := errors.New("err2")
-	err := composeErrors(err1, err2)
-	if err == nil {
-		t.Fatal("Expected composeErrors(err1, err2) to be non-nil")
-	}
-	if !strings.Contains(err.Error(), err1.Error()) {
-		t.Fatalf("Expected composeErrors(err1, err2) to contain %v, but was: %v", err1, err)
-	}
-	if !strings.Contains(err.Error(), err2.Error()) {
-		t.Fatalf("Expected composeErrors(err1, err2) to contain %v, but was: %v", err2, err)
-	}
-	// multiple non-nil errors compose to composite error without nil errors.
-	err = composeErrors(err1, err2, nil)
-	if err == nil {
-		t.Fatal("Expected composeErrors(err1, err2, nil) to be non-nil")
-	}
-	if !strings.Contains(err.Error(), err1.Error()) {
-		t.Fatalf("Expected composeErrors(err1, err2, nil) to contain %v, but was: %v", err1, err)
-	}
-	if !strings.Contains(err.Error(), err2.Error()) {
-		t.Fatalf("Expected composeErrors(err1, err2, nil) to contain %v, but was: %v", err2, err)
-	}
-}
diff --git a/runtimes/google/lib/follow/watcher.go b/runtimes/google/lib/follow/watcher.go
deleted file mode 100644
index d5ad863..0000000
--- a/runtimes/google/lib/follow/watcher.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package follow
-
-// fsWatcher is a tool for watching append-only modifications to a file.
-type fsWatcher interface {
-	// Wait blocks until the file is modified.
-	// Wait returns an io.EOF if the watcher is closed, and immediately returns
-	// any error it encounters while blocking.
-	Wait() error
-
-	// Close closes the watcher synchronously. Any ongoing or following calls
-	// to Wait return io.EOF.
-	// Close is idempotent.
-	Close() error
-}
diff --git a/runtimes/google/lib/functional/op/operations.go b/runtimes/google/lib/functional/op/operations.go
deleted file mode 100644
index 9e999a9..0000000
--- a/runtimes/google/lib/functional/op/operations.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package op
-
-import (
-	"veyron.io/veyron/veyron/runtimes/google/lib/functional"
-)
-
-// IterDifference iterates through the difference of two sets, applying function f
-// to each element that belongs to s1 but not s2. IterDifference terminates when
-// all elements have been examined, or when the function returns false.
-func IterDifference(s1, s2 functional.Set, f func(it interface{}) bool) {
-	// TODO(tilaks): if s1 and s2 use the same comparator, iterate s1 and s2
-	// by merging their iterators in O(len(s1) + len(s2)) steps. This is difficult
-	// because comparators are functions, and not comparable. It is, however,
-	// reasonable to iterate s2 and detect inversions under s1's comparator.
-	s1.Iter(func(it interface{}) bool {
-		if s2.Contains(it) {
-			return true
-		}
-		return f(it)
-	})
-}
diff --git a/runtimes/google/lib/functional/op/operations_test.go b/runtimes/google/lib/functional/op/operations_test.go
deleted file mode 100644
index 2d49c46..0000000
--- a/runtimes/google/lib/functional/op/operations_test.go
+++ /dev/null
@@ -1,58 +0,0 @@
-package op
-
-import (
-	"testing"
-
-	"veyron.io/veyron/veyron/runtimes/google/lib/functional"
-	"veyron.io/veyron/veyron/runtimes/google/lib/functional/rb"
-)
-
-func intCompare(it1, it2 interface{}) bool {
-	return it1.(int) < it2.(int)
-}
-
-func difference(s1, s2 functional.Set) functional.Set {
-	difference := rb.NewSet(intCompare)
-	IterDifference(s1, s2, func(it interface{}) bool {
-		difference = difference.Put(it)
-		return true
-	})
-	return difference
-}
-
-func TestDifferenceEmpty(t *testing.T) {
-	s1 := rb.NewSet(intCompare)
-	s2 := rb.NewSet(intCompare)
-	difference := difference(s1, s2)
-	if !difference.IsEmpty() {
-		t.Fatal("Difference is not empty")
-	}
-}
-
-func TestDifferenceDisjoint(t *testing.T) {
-	s1 := rb.NewSet(intCompare).Put(1).Put(2).Put(3)
-	s2 := rb.NewSet(intCompare).Put(4).Put(5)
-	difference := difference(s1, s2)
-	if difference.Len() != 3 {
-		t.Fatalf("Difference does not contain 3 elements ")
-	}
-	for i := 1; i <= 3; i++ {
-		if !difference.Contains(i) {
-			t.Fatalf("Difference does not contain %v", i)
-		}
-	}
-}
-
-func TestDifferenceOverlapping(t *testing.T) {
-	s1 := rb.NewSet(intCompare).Put(1).Put(2).Put(3).Put(5)
-	s2 := rb.NewSet(intCompare).Put(4).Put(5)
-	difference := difference(s1, s2)
-	if difference.Len() != 3 {
-		t.Fatalf("Difference does not contain 3 elements ")
-	}
-	for i := 1; i <= 3; i++ {
-		if !difference.Contains(i) {
-			t.Fatalf("Difference does not contain %v", i)
-		}
-	}
-}
diff --git a/runtimes/google/lib/functional/rb/rb_set.go b/runtimes/google/lib/functional/rb/rb_set.go
deleted file mode 100644
index 04d924a..0000000
--- a/runtimes/google/lib/functional/rb/rb_set.go
+++ /dev/null
@@ -1,544 +0,0 @@
-// Package rb implements functional sets using red-black trees.  This
-// implementation is based on Chris Okasaki's functional red-black trees.
-//
-//    Article: Functional Pearls
-//    Title: Red-Black Trees in a Functional Setting
-//    Author: Chris Okasaki
-//    J. Functional Programming, Jan 1993
-//    http://www.cs.tufts.edu/~nr/cs257/archive/chris-okasaki/redblack99.ps‎
-//
-// Okasaki doesn't define deletion.  This version of deletion is based on Stefan
-// Khar's untyped implementation in Haskell.
-//
-//   Title: Red-black trees with types.
-//   Author: Stefan Khars
-//   J. Functional Programming, July 2001
-//   http://www.cs.kent.ac.uk/people/staff/smk/redblack/Untyped.hs
-//
-// By "functional," we mean that functions behave like mathematical functions:
-// given the same argument, the function always returns the same value.  The
-// practical consequence is that a set is immutable and persistent.  It can't be
-// changed once it is constructed.  The operations that mutate the set (Put and
-// Remove) return a new set instead.
-//
-// Red-black trees have the following invariants.
-//    - Every node is colored either red or black.
-//    - The root is black.
-//    - RED: Red nodes have only black children.
-//    - BLACK: All paths from the root to the leaves have the same number of black nodes.
-//
-// These invariants imply that the longest path to a leaf is at most twice as
-// long as the shortest path, hence the tree is balanced.  Insertion and deletion
-// take O(log N) time, where N is the number of elements in the set.
-package rb
-
-import (
-	"veyron.io/veyron/veyron/runtimes/google/lib/functional"
-)
-
-// Node colors are RED and BLACK
-type color int
-
-const (
-	BLACK color = iota
-	RED
-)
-
-// rbSet is the red-black set.
-type rbSet struct {
-	root *node
-	cmp  functional.Comparator
-	size int
-}
-
-// The tree is constructed from Node.  Each Node has a color,
-// two children, and a label.
-type node struct {
-	color color
-	key   interface{}
-	left  *node
-	right *node
-}
-
-// iterator contains a path to a node.
-type iterator struct {
-	path []*node
-}
-
-func newNode(color color, key interface{}, left, right *node) *node {
-	return &node{color: color, key: key, left: left, right: right}
-}
-
-func isBlack(n *node) bool {
-	return n == nil || n.color == BLACK
-}
-
-func isRed(n *node) bool {
-	return n != nil && n.color == RED
-}
-
-func makeBlack(n *node) *node {
-	if isBlack(n) {
-		return n
-	}
-	return newNode(BLACK, n.key, n.left, n.right)
-}
-
-func makeRed(n *node) *node {
-	if isRed(n) {
-		panic("Node is already RED")
-	}
-	return newNode(RED, n.key, n.left, n.right)
-}
-
-// NewSet returns an empty set using the comparator.
-func NewSet(cmp functional.Comparator) functional.Set {
-	return &rbSet{cmp: cmp}
-}
-
-func (s *rbSet) newSet(root *node, size int) *rbSet {
-	return &rbSet{root: root, cmp: s.cmp, size: size}
-}
-
-func (s *rbSet) newSetWithCmp(root *node, cmp functional.Comparator, size int) *rbSet {
-	return &rbSet{root: root, cmp: cmp, size: size}
-}
-
-// IsEmpty returns true iff the set is empty.
-func (s *rbSet) IsEmpty() bool {
-	return s.root == nil
-}
-
-// Len returns the size of the tree.
-func (s *rbSet) Len() int {
-	return s.size
-}
-
-// Contains returns true iff the element is in the set.
-func (s *rbSet) Contains(key interface{}) bool {
-	for n := s.root; n != nil; {
-		if s.cmp(key, n.key) {
-			n = n.left
-		} else if s.cmp(n.key, key) {
-			n = n.right
-		} else {
-			return true
-		}
-	}
-	return false
-}
-
-// Get returns the element in the s.
-func (s *rbSet) Get(key interface{}) (interface{}, bool) {
-	for n := s.root; n != nil; {
-		if s.cmp(key, n.key) {
-			n = n.left
-		} else if s.cmp(n.key, key) {
-			n = n.right
-		} else {
-			return n.key, true
-		}
-	}
-	return nil, false
-}
-
-// Put adds an element to the set, replacing any existing element.
-func (s *rbSet) Put(key interface{}) functional.Set {
-	root, sizeChanged := insert(s.cmp, key, s.root)
-	size := s.size
-	if sizeChanged {
-		size++
-	}
-	return s.newSet(makeBlack(root), size)
-}
-
-// insert performs the actual insertion, returning the new node, and a bool
-// indicating whether the tree size has changed.
-//
-// Tree balancing is performed bottom-up; the stratgey is for black grandparents
-// to fix red-parent + red-child violations by rotating the tree and recoloring.
-func insert(cmp functional.Comparator, key interface{}, n *node) (*node, bool) {
-	switch {
-	case n == nil:
-		n = newNode(RED, key, nil, nil)
-		return n, true
-	case n.color == BLACK:
-		switch {
-		case cmp(key, n.key):
-			left, sizeChanged := insert(cmp, key, n.left)
-			if sizeChanged {
-				n = balance(n.key, left, n.right)
-			} else {
-				n = newNode(BLACK, n.key, left, n.right)
-			}
-			return n, sizeChanged
-		case cmp(n.key, key):
-			right, sizeChanged := insert(cmp, key, n.right)
-			if sizeChanged {
-				n = balance(n.key, n.left, right)
-			} else {
-				n = newNode(BLACK, n.key, n.left, right)
-			}
-			return n, sizeChanged
-		default:
-			// key and n.key are in the same equivalence class according to cmp,
-			// but we choose key as the representative.
-			n = newNode(BLACK, key, n.left, n.right)
-			return n, false
-		}
-	default: // n.color == RED
-		switch {
-		case cmp(key, n.key):
-			left, sizeChanged := insert(cmp, key, n.left)
-			n = newNode(RED, n.key, left, n.right)
-			return n, sizeChanged
-		case cmp(n.key, key):
-			right, sizeChanged := insert(cmp, key, n.right)
-			n = newNode(RED, n.key, n.left, right)
-			return n, sizeChanged
-		default:
-			// key and n.key are in the same equivalence class according to cmp,
-			// but we choose the new key as the representative.
-			n = newNode(RED, key, n.left, n.right)
-			return n, false
-		}
-	}
-}
-
-// Operations on the tree that insert and delete nodes may violate the
-// RED invariant.  The purpose of the balance function is to restore
-// the RED invariant by rotating the tree whenever one of the
-// arguments has a RED root with a RED child.  In addition, if both
-// arguments have a RED root, we migrate the RED to the root, and make
-// both subtrees BLACK.
-func balance(key interface{}, left, right *node) *node {
-	if isRed(left) {
-		switch {
-		case isRed(right):
-			// This is an optimization not in Okasaki's original algorithm, to
-			// reduce the number of reds by migrating them upward.
-			return newNode(RED, key,
-				newNode(BLACK, left.key, left.left, left.right),
-				newNode(BLACK, right.key, right.left, right.right))
-		case isRed(left.left):
-			return newNode(RED, left.key,
-				newNode(BLACK, left.left.key, left.left.left, left.left.right),
-				newNode(BLACK, key, left.right, right))
-		case isRed(left.right):
-			return newNode(RED, left.right.key,
-				newNode(BLACK, left.key, left.left, left.right.left),
-				newNode(BLACK, key, left.right.right, right))
-		}
-	}
-	if isRed(right) {
-		switch {
-		case isRed(right.left):
-			return newNode(RED, right.left.key,
-				newNode(BLACK, key, left, right.left.left),
-				newNode(BLACK, right.key, right.left.right, right.right))
-		case isRed(right.right):
-			return newNode(RED, right.key,
-				newNode(BLACK, key, left, right.left),
-				newNode(BLACK, right.right.key, right.right.left, right.right.right))
-		}
-	}
-	return newNode(BLACK, key, left, right)
-}
-
-// Removes removes an element from the set.
-func (s *rbSet) Remove(key interface{}) functional.Set {
-	root := remove(s.cmp, key, s.root)
-	if root == s.root {
-		return s // Nothing changed.
-	}
-	return s.newSet(makeBlack(root), s.size-1)
-}
-
-func remove(cmp functional.Comparator, key interface{}, n *node) *node {
-	switch {
-	case n == nil:
-		return nil
-	case cmp(key, n.key):
-		left := remove(cmp, key, n.left)
-		switch {
-		case left == n.left:
-			return n // Nothing changed.
-		case isBlack(n.left):
-			return balanceLeft(n.key, left, n.right)
-		default:
-			return newNode(RED, n.key, left, n.right)
-		}
-	case cmp(n.key, key):
-		right := remove(cmp, key, n.right)
-		switch {
-		case right == n.right:
-			return n // Nothing changed.
-		case isBlack(n.right):
-			return balanceRight(n.key, n.left, right)
-		default:
-			return newNode(RED, n.key, n.left, right)
-		}
-	default:
-		// If either of n.left or n.right is RED, the result of concat() might
-		// violate the RED invariant at the root.  This can happen only if
-		// n.color == BLACK.  If so, the recursive calls to remove in this
-		// function are followed by calls to balanceLeft or balanceRight to
-		// rebalance the tree.  See the balanceLeft comment below.
-		return concat(n.left, n.right)
-	}
-}
-
-// balanceLeft is called to balance a node after a deletion in the left branch.
-// The original node had key "key", "left" is the new left subtree after the
-// deletion was performed, and "right" is the original right child.
-//
-// REQUIRES: Before deletion, the left node was BLACK.  Since we have deleted an
-// element from the left subtree, the black depth of "left" is now one less than
-// the black depth of "right".
-//
-// ALLOWED: The left subtree may violate the RED invariant, but only at the
-// root (left might be RED and also have a RED child, but otherwise it is
-// balanced).
-//
-// To preserve the BLACK invariant, we need to subtract a BLACK from the right
-// subtree, or else rotate the tree to preserve the invariant.  In all cases, if
-// the original root node was BLACK, then the resulting tree has one less black
-// depth; if the original tree was RED, the resulting tree has the same black
-// depth.
-//
-// There are three cases.
-//
-//   1. If the new left child is RED, change the left child to BLACK and create
-//      a RED root.  If the original root node was BLACK, the total black depth
-//      is decreased by one.
-//
-//   2. Otherwise, the left child is BLACK.  If the right child is also BLACK,
-//      make the right child RED.  This may invalidate the RED invariant, so
-//      call the Balance() method to fix it.
-//
-//   3. Otherwise, left is BLACK, right is RED, and the original root was BLACK.
-//      Since the left tree is BLACK, the right node *must* have two BLACK
-//      non-leaf children.  Pick the left one, and rotate it into the left
-//      subtree.
-func balanceLeft(key interface{}, left, right *node) *node {
-	switch {
-	case isRed(left):
-		return newNode(RED, key, newNode(BLACK, left.key, left.left, left.right), right)
-	case isBlack(right):
-		return balance(key, left, makeRed(right))
-	default: // isRed(right) && isBlack(right.left)
-		return newNode(RED, right.left.key,
-			newNode(BLACK, key, left, right.left.left),
-			balance(right.key, right.left.right, makeRed(right.right)))
-	}
-}
-
-func balanceRight(key interface{}, left, right *node) *node {
-	switch {
-	case isRed(right):
-		return newNode(RED, key, left, newNode(BLACK, right.key, right.left, right.right))
-	case isBlack(left):
-		return balance(key, makeRed(left), right)
-	default: // isRed(left) && isBlack(left.right)
-		return newNode(RED, left.right.key,
-			balance(left.key, makeRed(left.left), left.right.left),
-			newNode(BLACK, key, left.right.right, right))
-	}
-}
-
-// Append the left and right trees.  The max of the left is smaller than the min
-// of the right, and the two trees have the same black depth.
-//
-// The BLACK invariant holds for the resulting tree, and it has the same black
-// depth as the input trees.
-//
-// If both arguments have BLACK roots, the RED invariant will hold for the
-// resulting tree.  However, if either argument has a RED root, the RED
-// invariant may not hold for the result, which may be violated at the root
-// (only).  In this case, the caller will need to rebalance the tree.  See the
-// comments for the recursive calls below.
-func concat(left, right *node) *node {
-	switch {
-	case left == nil:
-		return right
-	case right == nil:
-		return left
-	case left.color == BLACK && right.color == BLACK:
-		// middle has the same black depth as left.right and right.left.
-		middle := concat(left.right, right.left)
-		if isRed(middle) {
-			// middle may have a RED violation at the root, but if it does, the
-			// subtrees are balanced, so we can balance the result by giving
-			// them BLACK parents.
-			return newNode(RED, middle.key,
-				newNode(BLACK, left.key, left.left, middle.left),
-				newNode(BLACK, right.key, middle.right, right.right))
-		} else {
-			// left.left, middle, and right.right all have the same black depth,
-			// middle is BLACK, and we're adding a new BLACK node.  Use
-			// balanceLeft to restore the BLACK invariant.
-			return balanceLeft(left.key, left.left,
-				newNode(BLACK, right.key, middle, right.right))
-		}
-	case left.color == RED && right.color == RED:
-		// middle has the same black depth as left.right and right.left.
-		middle := concat(left.right, right.left)
-		if isRed(middle) {
-			// All parts, left.left, middle.left, middle.right, and right.right,
-			// have the same black depth, and they are all BLACK.  To preserve
-			// the black depth, use only RED modes, violating the RED invariant.
-			return newNode(RED, middle.key,
-				newNode(RED, left.key, left.left, middle.left),
-				newNode(RED, right.key, middle.right, right.right))
-		} else {
-			// left.left, middle, and right.right all have the same black depth
-			// and all are BLACK.  To preserve the black depth, use only RED
-			// modes, violating the RED invariant.
-			return newNode(RED, left.key, left.left,
-				newNode(RED, right.key, middle, right.right))
-		}
-	case left.color == RED: // right.color == BLACK
-		// left.left, left.right, and right have the same black depth.  To preserve
-		// the black depth, return a RED node, possibly violating the RED invariant.
-		return newNode(RED, left.key, left.left, concat(left.right, right))
-	default: // left.color == BLACK && right.color == RED
-		// left, right.left, and right.right have the same black depth.  To
-		// preserve the black depth, return a RED node, possibly violating the
-		// RED invariant.
-		return newNode(RED, right.key, concat(left, right.left), right.right)
-	}
-}
-
-// Iter applies a function to each element of the set in order.  The iteration
-// terminates if the function returns false.
-func (s *rbSet) Iter(f func(it interface{}) bool) {
-	if s.root != nil {
-		s.root.iter(f)
-	}
-}
-
-func (n *node) iter(f func(it interface{}) bool) {
-	if n.left != nil {
-		n.left.iter(f)
-	}
-	f(n.key)
-	if n.right != nil {
-		n.right.iter(f)
-	}
-}
-
-// Map applies a function to each element of the set in order, replacing the
-// elements value.  The ordering of the elements must be preserved.
-//
-//    { e1, e2, ..., eN }.Map(f) = { f(e1), f(e2), ..., f(eN) }
-//
-// Typically, this is use in dictionaries to update the value part of a
-// key/value pair, keeping the key unchanged, so preserving the order.
-func (s *rbSet) Map(f func(it interface{}) interface{}, cmp functional.Comparator) functional.Set {
-	if s.root == nil {
-		return s
-	}
-	return s.newSetWithCmp(s.root.fmap(f), cmp, s.size)
-}
-
-func (n *node) fmap(f func(it interface{}) interface{}) *node {
-	left := n.left
-	if left != nil {
-		left = left.fmap(f)
-	}
-	key := f(n.key)
-	right := n.right
-	if right != nil {
-		right = right.fmap(f)
-	}
-	return newNode(n.color, key, left, right)
-}
-
-// Fold applies a function to the elements of the set in order, accumulating the
-// results.
-//
-//     { e1, e2, ..., eN }.Fold(f, x) = f(eN, ... f(e2, f(e1, x)))
-//
-// For example, a sum could be computed as follows.
-//
-//     s.Fold(func (it, accum interface{}) interface{} {
-//        return it.(int) + accum.(int)
-//     })
-//
-func (s *rbSet) Fold(f func(it, x interface{}) interface{}, x interface{}) interface{} {
-	if s.root == nil {
-		return x
-	}
-	return s.root.fold(f, x)
-}
-
-func (n *node) fold(f func(it, x interface{}) interface{}, x interface{}) interface{} {
-	if n.left != nil {
-		x = n.left.fold(f, x)
-	}
-	x = f(n.key, x)
-	if n.right != nil {
-		x = n.right.fold(f, x)
-	}
-	return x
-}
-
-// iteration.
-func (s *rbSet) Iterator() functional.Iterator {
-	if s.root == nil {
-		return &iterator{}
-	}
-	var path []*node
-	for node := s.root; node != nil; node = node.left {
-		path = append(path, node)
-	}
-	return &iterator{path: path}
-}
-
-// IsValid returns true iff the iterator refers to an element.
-func (it *iterator) IsValid() bool {
-	return len(it.path) != 0
-}
-
-// Get returns the current element.
-func (it *iterator) Get() interface{} {
-	i := len(it.path)
-	if i == 0 {
-		return nil
-	}
-	return it.path[i-1].key
-}
-
-// Next advances to the next element.
-func (it *iterator) Next() {
-	path := it.path
-	i := len(path)
-	if i == 0 {
-		return
-	}
-	current := path[i-1]
-
-	// If there is a right child, descend to leftmost leaf.
-	if current.right != nil {
-		for node := current.right; node != nil; node = node.left {
-			path = append(path, node)
-		}
-		it.path = path
-		return
-	}
-
-	// If there is no right child, ascend to the nearest ancestor for which the
-	// path branches left.  That's the next in-order element.
-	for j := i - 2; j >= 0; j-- {
-		parent := path[j]
-		if current == parent.left {
-			// Found a left branch.
-			it.path = path[:j+1]
-			return
-		}
-		current = parent
-	}
-
-	// This was the rightmost path; we're done.
-	it.path = nil
-}
diff --git a/runtimes/google/lib/functional/rb/rb_set_test.go b/runtimes/google/lib/functional/rb/rb_set_test.go
deleted file mode 100644
index 45eee44..0000000
--- a/runtimes/google/lib/functional/rb/rb_set_test.go
+++ /dev/null
@@ -1,426 +0,0 @@
-package rb
-
-import (
-	"fmt"
-	"log"
-	"testing"
-
-	"veyron.io/veyron/veyron/lib/testutil"
-	"veyron.io/veyron/veyron/runtimes/google/lib/functional"
-)
-
-func init() { testutil.Init() }
-
-const (
-	// Number of elements to check
-	kMaxElement = 100
-
-	// Number of times to loop during the random test
-	kLoopCount = 10000
-)
-
-// Invariant checking.
-func checkInvariants(t *testing.T, s functional.Set) {
-	set := s.(*rbSet)
-	b := checkRedInvariant(t, set.root) &&
-		checkRootInvariant(t, set.root) &&
-		checkBlackInvariant(t, set.root)
-	if !b {
-		drawTree("", set.root)
-	}
-}
-
-func checkRedInvariant(t *testing.T, node *node) bool {
-	if node == nil {
-		return true
-	}
-	if node.color == RED && (node.left != nil && node.left.color == RED ||
-		node.right != nil && node.right.color == RED) {
-		t.Errorf("RedBlackSet: RED invariant violation")
-		return false
-	}
-	return checkRedInvariant(t, node.left) && checkRedInvariant(t, node.right)
-}
-
-func checkRootInvariant(t *testing.T, root *node) bool {
-	if root != nil && root.color != BLACK {
-		t.Errorf("RedBlackSet: Root is not BLACK")
-		return false
-	}
-	return true
-}
-
-func checkBlackInvariant(t *testing.T, root *node) bool {
-	depth := 0
-	for node := root; node != nil; node = node.left {
-		if node.color == BLACK {
-			depth++
-		}
-	}
-	b := checkBlackPathInvariant(depth, root)
-	if !b {
-		t.Error("Not all paths have the same number of black nodes")
-	}
-	return b
-}
-
-func checkBlackPathInvariant(expected int, node *node) bool {
-	if node == nil {
-		return expected == 0
-	}
-	if node.color == BLACK {
-		expected--
-	}
-	return checkBlackPathInvariant(expected, node.left) && checkBlackPathInvariant(expected, node.right)
-}
-
-func (set *rbSet) printTree() {
-	drawTree("x", set.root)
-}
-
-func drawTree(prefix string, node *node) {
-	if node != nil {
-		var color string
-		if node.color == RED {
-			color = "R"
-		} else {
-			color = "B"
-		}
-		log.Printf("%s %s %d", prefix, color, node.key)
-		drawTree(prefix+"l", node.left)
-		drawTree(prefix+"r", node.right)
-	}
-}
-
-func intCompare(it1, it2 interface{}) bool {
-	return it1.(int) < it2.(int)
-}
-
-func checkMembership(t *testing.T, s functional.Set, elements map[int]struct{}) {
-	checkInvariants(t, s)
-
-	s.Iter(func(it interface{}) bool {
-		i := it.(int)
-		if _, ok := elements[i]; !ok {
-			t.Errorf("Extra element: %d", i)
-		}
-		return true
-	})
-	itElements := make(map[int]struct{})
-	for it := s.Iterator(); it.IsValid(); it.Next() {
-		i := it.Get().(int)
-		if _, ok := elements[i]; !ok {
-			t.Errorf("Extra element: %d", i)
-		}
-		itElements[i] = struct{}{}
-	}
-	for i, _ := range elements {
-		if !s.Contains(i) {
-			t.Errorf("Missing element: %d", i)
-		}
-		if j, ok := s.Get(i); !ok || j != i {
-			t.Errorf("Expected %d, got %d", i, j)
-		}
-		if _, ok := itElements[i]; !ok {
-			t.Errorf("Missing iterator element: %d", i)
-		}
-	}
-
-	if s.Len() != len(elements) {
-		t.Errorf("Expected size %d, actual size %d", len(elements), s.Len())
-	}
-}
-
-// Sequential add and remove elements.
-func TestAddRemove(t *testing.T) {
-	s := NewSet(intCompare)
-	if !s.IsEmpty() {
-		t.Errorf("set should be empty: %v", s)
-	}
-	if s.Len() != 0 {
-		t.Errorf("set should have size zero: %d", s.Len())
-	}
-
-	// Add some elements
-	elements := make(map[int]struct{})
-	for i := 0; i != kMaxElement; i++ {
-		s = s.Put(i)
-		elements[i] = struct{}{}
-		checkMembership(t, s, elements)
-	}
-
-	// Remove some elements
-	for i := kMaxElement - 1; i > 0; i-- {
-		s = s.Remove(i)
-		delete(elements, i)
-		checkMembership(t, s, elements)
-	}
-}
-
-// Randomized add and remove.
-func TestRandom(t *testing.T) {
-	s := NewSet(intCompare)
-	elements := make(map[int]struct{})
-	for i := 0; i != kLoopCount; i++ {
-		switch testutil.Rand.Intn(2) {
-		case 0:
-			// Insertion
-			x := testutil.Rand.Intn(kMaxElement)
-			elements[x] = struct{}{}
-			s = s.Put(x)
-		case 1:
-			// Deletion
-			x := testutil.Rand.Intn(kMaxElement)
-			delete(elements, x)
-			s = s.Remove(x)
-		}
-		checkMembership(t, s, elements)
-	}
-}
-
-// Map test.
-type entry struct {
-	key, value int
-}
-
-func entryLessThan(e1, e2 interface{}) bool {
-	return e1.(*entry).key < e2.(*entry).key
-}
-
-func entryKeyFn(it interface{}) int {
-	return it.(*entry).key
-}
-
-func entryValueFn(it interface{}) interface{} {
-	return it.(*entry).value
-}
-
-func entryEntryFn(key int) interface{} {
-	return &entry{key: key}
-}
-
-type entry2 struct {
-	key   int
-	value string
-}
-
-func entry2LessThan(e1, e2 interface{}) bool {
-	return e1.(*entry2).key < e2.(*entry2).key
-}
-
-func entry2KeyFn(it interface{}) int {
-	return it.(*entry2).key
-}
-
-func entry2ValueFn(it interface{}) interface{} {
-	return it.(*entry2).value
-}
-
-func entry2EntryFn(key int) interface{} {
-	return &entry2{key: key}
-}
-
-func checkMaps(t *testing.T, s functional.Set, elements map[int]interface{},
-	keyFn func(interface{}) int,
-	valueFn func(interface{}) interface{},
-	entryFn func(int) interface{}) {
-	checkInvariants(t, s)
-
-	s.Iter(func(it interface{}) bool {
-		key := keyFn(it)
-		value := valueFn(it)
-		if j, ok := elements[key]; !ok || j != value {
-			t.Errorf("Expected %d, got %d", value, j)
-		}
-		return true
-	})
-	for i, x := range elements {
-		if !s.Contains(entryFn(i)) {
-			t.Errorf("Missing element: %d", i)
-		}
-		v, ok := s.Get(entryFn(i))
-		if !ok {
-			t.Errorf("Missing element: %d", i)
-		} else {
-			key := keyFn(v)
-			value := valueFn(v)
-			if key != i || value != x {
-				t.Errorf("Expected (%d, %d), got (%v)", i, x, v)
-			}
-		}
-	}
-
-	if s.Len() != len(elements) {
-		t.Errorf("Expected size %d, actual size %d", len(elements), s.Len())
-	}
-}
-
-func TestSequentialMap(t *testing.T) {
-	s := NewSet(entryLessThan)
-	elements := make(map[int]interface{})
-	for i := 0; i != kMaxElement; i++ {
-		elements[i] = i + 1
-		s = s.Put(&entry{key: i, value: i + 1})
-		checkMaps(t, s, elements, entryKeyFn, entryValueFn, entryEntryFn)
-	}
-
-	for i := kMaxElement; i >= 0; i-- {
-		delete(elements, i)
-		s = s.Remove(&entry{key: i})
-		checkMaps(t, s, elements, entryKeyFn, entryValueFn, entryEntryFn)
-	}
-}
-
-func TestRandomMap(t *testing.T) {
-	s := NewSet(entryLessThan)
-	elements := make(map[int]interface{})
-	for i := 0; i != kLoopCount; i++ {
-		switch testutil.Rand.Intn(2) {
-		case 0:
-			// Insertion
-			k := testutil.Rand.Intn(kMaxElement)
-			v := testutil.Rand.Int()
-			elements[k] = v
-			s = s.Put(&entry{key: k, value: v})
-		case 1:
-			// Deletion
-			k := testutil.Rand.Intn(kMaxElement)
-			delete(elements, k)
-			s = s.Remove(&entry{key: k})
-		}
-		checkMaps(t, s, elements, entryKeyFn, entryValueFn, entryEntryFn)
-	}
-}
-
-func TestMapMap(t *testing.T) {
-	s := NewSet(entryLessThan)
-	elements := make(map[int]interface{})
-	for i := 0; i != kMaxElement; i++ {
-		elements[i] = i + 1
-		s = s.Put(&entry{key: i, value: i + 1})
-		checkMaps(t, s, elements, entryKeyFn, entryValueFn, entryEntryFn)
-	}
-
-	s2 := s.Map(func(it interface{}) interface{} {
-		e := *it.(*entry)
-		e.value++
-		return &e
-	}, entryLessThan)
-	elements2 := make(map[int]interface{})
-	for k, v := range elements {
-		elements2[k] = v.(int) + 1
-	}
-	checkMaps(t, s2, elements2, entryKeyFn, entryValueFn, entryEntryFn)
-}
-
-func TestMapFold(t *testing.T) {
-	s := NewSet(entryLessThan)
-	elements := make(map[int]interface{})
-	for i := 0; i != kMaxElement; i++ {
-		elements[i] = i + 1
-		s = s.Put(&entry{key: i, value: i + 1})
-		checkMaps(t, s, elements, entryKeyFn, entryValueFn, entryEntryFn)
-	}
-
-	l := s.Fold(func(it, x interface{}) interface{} {
-		l := x.([]entry)
-		return append(l, *it.(*entry))
-	}, ([]entry)(nil))
-
-	s2 := NewSet(entryLessThan)
-	for i, e := range l.([]entry) {
-		e2 := e // Copy the entry.
-		if e2.key != i || e2.value != i+1 {
-			t.Errorf("Unexpected entry: %v", e2)
-		}
-		s2 = s2.Put(&e2)
-	}
-	checkMaps(t, s2, elements, entryKeyFn, entryValueFn, entryEntryFn)
-}
-
-func TestMapToNewType(t *testing.T) {
-	s := NewSet(entryLessThan)
-	elements := make(map[int]interface{})
-	for i := 0; i != kMaxElement; i++ {
-		elements[i] = i + 1
-		s = s.Put(&entry{key: i, value: i + 1})
-	}
-	s2 := s.Map(func(it interface{}) interface{} {
-		e := *it.(*entry)
-		return &entry2{
-			key:   e.key,
-			value: fmt.Sprintf("s%v", e.value),
-		}
-	}, entry2LessThan)
-	elements2 := make(map[int]interface{})
-	for k, v := range elements {
-		elements2[k] = fmt.Sprintf("s%v", v)
-	}
-	checkMaps(t, s2, elements2, entry2KeyFn, entry2ValueFn, entry2EntryFn)
-}
-
-////////////////////////////////////////////////////////////////////////
-// Simple random benchmark
-
-// Number of elements to check
-var kMaxElementBench int = 1000
-
-// Table of random ops
-type opname int
-
-const (
-	CONTAINS opname = iota
-	PUT
-	REMOVE
-	ITERATE
-)
-
-type operation struct {
-	op    opname
-	count int
-}
-
-var optable = [...]operation{
-	operation{CONTAINS, 40},
-	operation{PUT, 4},
-	operation{REMOVE, 4},
-	operation{ITERATE, 1}}
-
-func makeOperations() []opname {
-	totalsize := 0
-	for i := 0; i != len(optable); i++ {
-		totalsize += optable[i].count
-	}
-
-	operations := make([]opname, totalsize)
-	index := 0
-	for i := 0; i != len(optable); i++ {
-		op := optable[i]
-		for j := 0; j != op.count; j++ {
-			operations[index] = op.op
-			index++
-		}
-	}
-	return operations
-}
-
-func BenchmarkRandom(b *testing.B) {
-	operations := makeOperations()
-	s := NewSet(intCompare)
-
-	for i := 0; i != b.N; i++ {
-		switch operations[testutil.Rand.Intn(len(operations))] {
-		case CONTAINS:
-			s.Contains(testutil.Rand.Intn(kMaxElement))
-
-		case PUT:
-			s = s.Put(testutil.Rand.Intn(kMaxElement))
-
-		case REMOVE:
-			s = s.Remove(testutil.Rand.Intn(kMaxElement))
-
-		case ITERATE:
-			s.Iter(func(it interface{}) bool { return true })
-		}
-	}
-}
diff --git a/runtimes/google/lib/functional/set.go b/runtimes/google/lib/functional/set.go
deleted file mode 100644
index 1684c09..0000000
--- a/runtimes/google/lib/functional/set.go
+++ /dev/null
@@ -1,85 +0,0 @@
-package functional
-
-// Set is a collection of elements that supports operations for adding and
-// removing elements, testing for membership, and enumerating the elements by
-// iteration.
-//
-// By "functional," we mean that all methods act like mathematical functions,
-// meaning that they return the same value on the same argument.  That's one way
-// to put it, but the real consequence is that the set is immutable.  Instead of
-// altering a set in-place, methods that perform alterations return a new set
-// with the changes.  The argument set is unaffected.
-type Set interface {
-	// Contains returns true iff the element "x" is in the set.
-	Contains(x interface{}) bool
-
-	// Get returns the actual entry associated with an element.
-	Get(x interface{}) (interface{}, bool)
-
-	// Put adds the element "x" to the set.
-	Put(x interface{}) Set
-
-	// Remove deletes the element "x" from the set.
-	Remove(x interface{}) Set
-
-	// IsEmpty returns true iff the set has no elements.
-	IsEmpty() bool
-
-	// Len returns the number of elements in the set.
-	Len() int
-
-	// Iterator returns an iterator referring to the first element in the set,
-	// if there is one.  If the set is empty, the iterator's IsValid method
-	// returns false.  Note that the set is immutable, so the values returned
-	// from iteration are fixed at the time the Iterator is created and there
-	// are no concurrency issues.
-	Iterator() Iterator
-
-	// Iter iterates through the set, applying the function f to each element.
-	// Iteration terminates when all elements have been examined, or when the
-	// function returns false.  Iter is similar to Iterator, but it is included
-	// to support standard functional idioms, similar to Map and Fold.
-	Iter(f func(it interface{}) bool)
-
-	// Map applies a function to each element of the set in order, replacing the
-	// elements value. The ordering of the elements must be preserved under the
-	// new comparator.
-	//
-	//    { e1, e2, ..., eN }.Map(f, cmp) = { f(e1), f(e2), ..., f(eN) }
-	//
-	// Typically, this is use in dictionaries to update the value part of a
-	// key/value pair, keeping the key unchanged, so preserving the order.
-	Map(f func(it interface{}) interface{}, cmp Comparator) Set
-
-	// Fold applies a function to the elements of the set in order, accumulating the
-	// results.
-	//
-	//     { e1, e2, ..., eN }.Fold(f, x) = f(eN, ... f(e2, f(e1, x)))
-	//
-	// For example, a sum could be computed as follows.
-	//
-	//     s.Fold(func (it, accum interface{}) interface{} {
-	//        return it.(int) + accum.(int)
-	//     })
-	Fold(f func(it, x interface{}) interface{}, x interface{}) interface{}
-}
-
-// Comparator is the type of ordering relations.  The function returns true iff
-// the first argument is less than the second.
-//
-// The relation must be a strict weak order, which means that 1) it is a partial
-// order, and 2) equality is transitive (a == b iff !(a < b) && !(b < a)).
-type Comparator func(it1, it2 interface{}) bool
-
-// Iterator is the type of iterators over set elements.
-type Iterator interface {
-	// IsValid returns true iff the iterator refers to a valid set element.
-	IsValid() bool
-
-	// Get returns the element that the iterator refers to.  Undefined if
-	// IsValid is false.
-	Get() interface{}
-
-	// Next advances the iterator to the next element in the set.
-	Next()
-}
diff --git a/runtimes/google/rt/rt_test.go b/runtimes/google/rt/rt_test.go
index e391f1f..84085db 100644
--- a/runtimes/google/rt/rt_test.go
+++ b/runtimes/google/rt/rt_test.go
@@ -10,7 +10,6 @@
 	"testing"
 	"time"
 
-	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/options"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/security"
@@ -23,23 +22,6 @@
 	vsecurity "veyron.io/veyron/veyron/security"
 )
 
-type context struct {
-	local security.Principal
-}
-
-func (*context) Timestamp() (t time.Time)                  { return t }
-func (*context) Method() string                            { return "" }
-func (*context) MethodTags() []interface{}                 { return nil }
-func (*context) Name() string                              { return "" }
-func (*context) Suffix() string                            { return "" }
-func (*context) Label() (l security.Label)                 { return }
-func (*context) Discharges() map[string]security.Discharge { return nil }
-func (c *context) LocalPrincipal() security.Principal      { return c.local }
-func (*context) LocalBlessings() security.Blessings        { return nil }
-func (*context) RemoteBlessings() security.Blessings       { return nil }
-func (*context) LocalEndpoint() naming.Endpoint            { return nil }
-func (*context) RemoteEndpoint() naming.Endpoint           { return nil }
-
 func init() {
 	testutil.Init()
 	modules.RegisterChild("child", "", child)
@@ -120,7 +102,8 @@
 		return fmt.Errorf("rt.Principal().BlessingStore().Default() returned nil")
 
 	}
-	if n := len(blessings.ForContext(&context{local: p})); n != 1 {
+	ctx := security.NewContext(&security.ContextParams{LocalPrincipal: p})
+	if n := len(blessings.ForContext(ctx)); n != 1 {
 		fmt.Errorf("rt.Principal().BlessingStore().Default() returned Blessing %v with %d recognized blessings, want exactly one recognized blessing", blessings, n)
 	}
 	return nil
diff --git a/runtimes/google/rt/security.go b/runtimes/google/rt/security.go
index 67814f1..86223d1 100644
--- a/runtimes/google/rt/security.go
+++ b/runtimes/google/rt/security.go
@@ -6,6 +6,7 @@
 	"os/user"
 	"strconv"
 
+	"veyron.io/veyron/veyron/lib/stats"
 	vsecurity "veyron.io/veyron/veyron/security"
 	"veyron.io/veyron/veyron/security/agent"
 
@@ -18,6 +19,16 @@
 }
 
 func (rt *vrt) initSecurity(credentials string) error {
+	if err := rt.setupPrincipal(credentials); err != nil {
+		return err
+	}
+	stats.NewString("security/principal/key").Set(rt.principal.PublicKey().String())
+	stats.NewStringFunc("security/principal/blessingstore", rt.principal.BlessingStore().DebugString)
+	stats.NewStringFunc("security/principal/blessingroots", rt.principal.Roots().DebugString)
+	return nil
+}
+
+func (rt *vrt) setupPrincipal(credentials string) error {
 	if rt.principal != nil {
 		return nil
 	}
diff --git a/security/acl_authorizer_test.go b/security/acl_authorizer_test.go
index f8785fa..98b0e2a 100644
--- a/security/acl_authorizer_test.go
+++ b/security/acl_authorizer_test.go
@@ -5,33 +5,10 @@
 	"os"
 	"runtime"
 	"testing"
-	"time"
 
-	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/security"
 )
 
-// context implements security.Context.
-type context struct {
-	localPrincipal                  security.Principal
-	localBlessings, remoteBlessings security.Blessings
-	method                          string
-	label                           security.Label
-}
-
-func (c *context) Timestamp() (t time.Time)                  { return t }
-func (c *context) Method() string                            { return c.method }
-func (c *context) MethodTags() []interface{}                 { return nil }
-func (c *context) Name() string                              { return "" }
-func (c *context) Suffix() string                            { return "" }
-func (c *context) Label() security.Label                     { return c.label }
-func (c *context) Discharges() map[string]security.Discharge { return nil }
-func (c *context) LocalPrincipal() security.Principal        { return c.localPrincipal }
-func (c *context) LocalBlessings() security.Blessings        { return c.localBlessings }
-func (c *context) RemoteBlessings() security.Blessings       { return c.remoteBlessings }
-func (c *context) LocalEndpoint() naming.Endpoint            { return nil }
-func (c *context) RemoteEndpoint() naming.Endpoint           { return nil }
-
 func saveACLToTempFile(acl security.ACL) string {
 	f, err := ioutil.TempFile("", "saved_acl")
 	if err != nil {
@@ -62,31 +39,25 @@
 		pserver, server = newPrincipal("server")
 		_, imposter     = newPrincipal("server")
 		palice, alice   = newPrincipal("alice")
+		aliceServer     = bless(palice, pserver, alice, "server")
 
-		serverAlice = bless(pserver, palice, server, "alice")
-		aliceServer = bless(palice, pserver, alice, "server")
-
-		ctx = &context{
-			localPrincipal: pserver,
-			localBlessings: server,
-		}
-
+		ctxp  = &security.ContextParams{LocalPrincipal: pserver, LocalBlessings: server}
 		tests = []struct {
 			remote       security.Blessings
 			isAuthorized bool
 		}{
 			{server, true},
 			{imposter, false},
-			{serverAlice, 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 {
-		ctx.remoteBlessings = test.remote
+		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(&context{local: %v, remote: %v}) returned error: %v, want error: %v", file, line, authorizer, ctx.localBlessings, ctx.remoteBlessings, got, !want)
+			t.Errorf("%s:%d: %+v.Authorize(%v) returned error: %v, want error: %v", file, line, authorizer, ctx, got, !want)
 		}
 	}
 }
@@ -119,13 +90,23 @@
 	// valid or invalid label.
 	for _, u := range users {
 		for _, l := range security.ValidLabels {
-			ctx := &context{localPrincipal: pserver, localBlessings: server, remoteBlessings: u, label: l}
+			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 := &context{localPrincipal: pserver, localBlessings: server, remoteBlessings: u, label: invalidLabel}
+		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)
 		}
@@ -164,9 +145,14 @@
 			_, file, line, _ := runtime.Caller(1)
 			for user, labels := range expectations {
 				for _, l := range security.ValidLabels {
-					ctx := &context{remoteBlessings: user, localBlessings: server, localPrincipal: pserver, label: l}
+					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(&context{remoteBlessings: %v, label: %v}) returned error: %v, want error: %v", file, line, authorizer, user, l, got, !want)
+						t.Errorf("%s:%d: %+v.Authorize(%v) returned error: %v, want error: %v", file, line, authorizer, ctx, got, !want)
 					}
 				}
 			}
diff --git a/security/blessingroots.go b/security/blessingroots.go
index 5f314d8..9883122 100644
--- a/security/blessingroots.go
+++ b/security/blessingroots.go
@@ -11,17 +11,12 @@
 	"veyron.io/veyron/veyron2/security"
 )
 
-const (
-	blessingRootsDataFile = "blessingroots.data"
-	blessingRootsSigFile  = "blessingroots.sig"
-)
-
 // blessingRoots implements security.BlessingRoots.
 type blessingRoots struct {
-	dir    string
-	signer serialization.Signer
-	mu     sync.RWMutex
-	store  map[string][]security.BlessingPattern // GUARDED_BY(mu)
+	persistedData SerializerReaderWriter
+	signer        serialization.Signer
+	mu            sync.RWMutex
+	store         map[string][]security.BlessingPattern // GUARDED_BY(mu)
 }
 
 func storeMapKey(root security.PublicKey) (string, error) {
@@ -93,10 +88,14 @@
 }
 
 func (br *blessingRoots) save() error {
-	if (br.signer == nil) && (br.dir == "") {
+	if (br.signer == nil) && (br.persistedData == nil) {
 		return nil
 	}
-	return encodeAndStore(br.store, br.dir, blessingRootsDataFile, blessingRootsSigFile, br.signer)
+	data, signature, err := br.persistedData.Writers()
+	if err != nil {
+		return err
+	}
+	return encodeAndStore(br.store, data, signature, br.signer)
 }
 
 // newInMemoryBlessingRoots returns an in-memory security.BlessingRoots.
@@ -108,27 +107,26 @@
 	}
 }
 
-// newPersistingBlessingRoots returns a security.BlessingRoots that signs
-// and persists all updates to the provided directory. Signing is carried
-// out using the provided signer.
-//
-// The returned BlessingRoots is initialized from the existing data present
-// in the directory. The data is verified to have been written by a persisting
-// BlessingRoots object constructed from the same signer.
-//
-// Any errors obtained in reading or verifying the data are returned.
-func newPersistingBlessingRoots(directory string, signer serialization.Signer) (security.BlessingRoots, error) {
-	if directory == "" || signer == nil {
-		return nil, errors.New("directory or signer is not specified")
+// newPersistingBlessingRoots returns a security.BlessingRoots for a principal
+// that is initialized with the persisted data. The returned security.BlessingRoots
+// also persists any updates to its state.
+func newPersistingBlessingRoots(persistedData SerializerReaderWriter, signer serialization.Signer) (security.BlessingRoots, error) {
+	if persistedData == nil || signer == nil {
+		return nil, errors.New("persisted data or signer is not specified")
 	}
 	br := &blessingRoots{
-		store:  make(map[string][]security.BlessingPattern),
-		dir:    directory,
-		signer: signer,
+		store:         make(map[string][]security.BlessingPattern),
+		persistedData: persistedData,
+		signer:        signer,
 	}
-
-	if err := decodeFromStorage(&br.store, br.dir, blessingRootsDataFile, blessingRootsSigFile, br.signer.PublicKey()); err != nil {
+	data, signature, err := br.persistedData.Readers()
+	if err != nil {
 		return nil, err
 	}
+	if (data != nil) && (signature != nil) {
+		if err := decodeFromStorage(&br.store, data, signature, br.signer.PublicKey()); err != nil {
+			return nil, err
+		}
+	}
 	return br, nil
 }
diff --git a/security/blessingstore.go b/security/blessingstore.go
index b135580..2a03456 100644
--- a/security/blessingstore.go
+++ b/security/blessingstore.go
@@ -13,11 +13,6 @@
 	"veyron.io/veyron/veyron2/vlog"
 )
 
-const (
-	blessingStoreDataFile = "blessingstore.data"
-	blessingStoreSigFile  = "blessingstore.sig"
-)
-
 var errStoreAddMismatch = errors.New("blessing's public key does not match store's public key")
 
 type persistentState struct {
@@ -33,45 +28,45 @@
 
 // blessingStore implements security.BlessingStore.
 type blessingStore struct {
-	publicKey security.PublicKey
-	dir       string
-	signer    serialization.Signer
-	mu        sync.RWMutex
-	state     persistentState // GUARDED_BY(mu)
+	publicKey     security.PublicKey
+	persistedData SerializerReaderWriter
+	signer        serialization.Signer
+	mu            sync.RWMutex
+	state         persistentState // GUARDED_BY(mu)
 }
 
-func (s *blessingStore) Set(blessings security.Blessings, forPeers security.BlessingPattern) (security.Blessings, error) {
+func (bs *blessingStore) Set(blessings security.Blessings, forPeers security.BlessingPattern) (security.Blessings, error) {
 	if !forPeers.IsValid() {
 		return nil, fmt.Errorf("%q is an invalid BlessingPattern", forPeers)
 	}
-	if blessings != nil && !reflect.DeepEqual(blessings.PublicKey(), s.publicKey) {
+	if blessings != nil && !reflect.DeepEqual(blessings.PublicKey(), bs.publicKey) {
 		return nil, errStoreAddMismatch
 	}
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	old, hadold := s.state.Store[forPeers]
+	bs.mu.Lock()
+	defer bs.mu.Unlock()
+	old, hadold := bs.state.Store[forPeers]
 	if blessings != nil {
-		s.state.Store[forPeers] = blessings
+		bs.state.Store[forPeers] = blessings
 	} else {
-		delete(s.state.Store, forPeers)
+		delete(bs.state.Store, forPeers)
 	}
-	if err := s.save(); err != nil {
+	if err := bs.save(); err != nil {
 		if hadold {
-			s.state.Store[forPeers] = old
+			bs.state.Store[forPeers] = old
 		} else {
-			delete(s.state.Store, forPeers)
+			delete(bs.state.Store, forPeers)
 		}
 		return nil, err
 	}
 	return old, nil
 }
 
-func (s *blessingStore) ForPeer(peerBlessings ...string) security.Blessings {
-	s.mu.RLock()
-	defer s.mu.RUnlock()
+func (bs *blessingStore) ForPeer(peerBlessings ...string) security.Blessings {
+	bs.mu.RLock()
+	defer bs.mu.RUnlock()
 
 	var ret security.Blessings
-	for pattern, blessings := range s.state.Store {
+	for pattern, blessings := range bs.state.Store {
 		if pattern.MatchedBy(peerBlessings...) {
 			if union, err := security.UnionOfBlessings(ret, blessings); err != nil {
 				vlog.Errorf("UnionOfBlessings(%v, %v) failed: %v, dropping the latter from BlessingStore.ForPeers(%v)", ret, blessings, err, peerBlessings)
@@ -83,35 +78,35 @@
 	return ret
 }
 
-func (s *blessingStore) Default() security.Blessings {
-	s.mu.RLock()
-	defer s.mu.RUnlock()
-	if s.state.Default != nil {
-		return s.state.Default
+func (bs *blessingStore) Default() security.Blessings {
+	bs.mu.RLock()
+	defer bs.mu.RUnlock()
+	if bs.state.Default != nil {
+		return bs.state.Default
 	}
-	return s.ForPeer()
+	return bs.ForPeer()
 }
 
-func (s *blessingStore) SetDefault(blessings security.Blessings) error {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	if !reflect.DeepEqual(blessings.PublicKey(), s.publicKey) {
+func (bs *blessingStore) SetDefault(blessings security.Blessings) error {
+	bs.mu.Lock()
+	defer bs.mu.Unlock()
+	if !reflect.DeepEqual(blessings.PublicKey(), bs.publicKey) {
 		return errStoreAddMismatch
 	}
-	oldDefault := s.state.Default
-	s.state.Default = blessings
-	if err := s.save(); err != nil {
-		s.state.Default = oldDefault
+	oldDefault := bs.state.Default
+	bs.state.Default = blessings
+	if err := bs.save(); err != nil {
+		bs.state.Default = oldDefault
 	}
 	return nil
 }
 
-func (s *blessingStore) PublicKey() security.PublicKey {
-	return s.publicKey
+func (bs *blessingStore) PublicKey() security.PublicKey {
+	return bs.publicKey
 }
 
-func (s *blessingStore) String() string {
-	return fmt.Sprintf("{state: %v, publicKey: %v, dir: %v}", s.state, s.publicKey, s.dir)
+func (bs *blessingStore) String() string {
+	return fmt.Sprintf("{state: %v, publicKey: %v}", bs.state, bs.publicKey)
 }
 
 // DebugString return a human-readable string encoding of the store
@@ -122,22 +117,26 @@
 // <pattern>    : <blessings>
 // ...
 // <pattern>    : <blessings>
-func (br *blessingStore) DebugString() string {
+func (bs *blessingStore) DebugString() string {
 	const format = "%-30s : %s\n"
-	b := bytes.NewBufferString(fmt.Sprintf("Default blessings: %v\n", br.state.Default))
+	b := bytes.NewBufferString(fmt.Sprintf("Default blessings: %v\n", bs.state.Default))
 
 	b.WriteString(fmt.Sprintf(format, "Peer pattern", "Blessings"))
-	for pattern, blessings := range br.state.Store {
+	for pattern, blessings := range bs.state.Store {
 		b.WriteString(fmt.Sprintf(format, pattern, blessings))
 	}
 	return b.String()
 }
 
-func (s *blessingStore) save() error {
-	if (s.signer == nil) && (s.dir == "") {
+func (bs *blessingStore) save() error {
+	if (bs.signer == nil) && (bs.persistedData == nil) {
 		return nil
 	}
-	return encodeAndStore(s.state, s.dir, blessingStoreDataFile, blessingStoreSigFile, s.signer)
+	data, signature, err := bs.persistedData.Writers()
+	if err != nil {
+		return err
+	}
+	return encodeAndStore(bs.state, data, signature, bs.signer)
 }
 
 // newInMemoryBlessingStore returns an in-memory security.BlessingStore for a
@@ -152,33 +151,31 @@
 }
 
 // newPersistingBlessingStore returns a security.BlessingStore for a principal
-// that persists all updates to the specified directory and uses the provided
-// signer to ensure integrity of data read from the filesystem.
-//
-// The returned BlessingStore is initialized from the existing data present in
-// the directory. The data is verified to have been written by a persisting
-// BlessingStore object constructed from the same signer.
-//
-// Any errors obtained in reading or verifying the data are returned.
-func newPersistingBlessingStore(directory string, signer serialization.Signer) (security.BlessingStore, error) {
-	if directory == "" || signer == nil {
-		return nil, errors.New("directory or signer is not specified")
+// that is initialized with the persisted data. The returned security.BlessingStore
+// also persists any updates to its state.
+func newPersistingBlessingStore(persistedData SerializerReaderWriter, signer serialization.Signer) (security.BlessingStore, error) {
+	if persistedData == nil || signer == nil {
+		return nil, errors.New("persisted data or signer is not specified")
 	}
-	s := &blessingStore{
-		publicKey: signer.PublicKey(),
-		state:     persistentState{Store: make(map[security.BlessingPattern]security.Blessings)},
-		dir:       directory,
-		signer:    signer,
+	bs := &blessingStore{
+		publicKey:     signer.PublicKey(),
+		state:         persistentState{Store: make(map[security.BlessingPattern]security.Blessings)},
+		persistedData: persistedData,
+		signer:        signer,
 	}
-
-	if err := decodeFromStorage(&s.state, s.dir, blessingStoreDataFile, blessingStoreSigFile, s.signer.PublicKey()); err != nil {
+	data, signature, err := bs.persistedData.Readers()
+	if err != nil {
 		return nil, err
 	}
-
-	for _, b := range s.state.Store {
-		if !reflect.DeepEqual(b.PublicKey(), s.publicKey) {
-			return nil, fmt.Errorf("directory contains Blessings: %v that are not for the provided PublicKey: %v", b, s.publicKey)
+	if data != nil && signature != nil {
+		if err := decodeFromStorage(&bs.state, data, signature, bs.signer.PublicKey()); err != nil {
+			return nil, err
 		}
 	}
-	return s, nil
+	for _, b := range bs.state.Store {
+		if !reflect.DeepEqual(b.PublicKey(), bs.publicKey) {
+			return nil, fmt.Errorf("directory contains Blessings: %v that are not for the provided PublicKey: %v", b, bs.publicKey)
+		}
+	}
+	return bs, nil
 }
diff --git a/security/principal.go b/security/principal.go
index f0dba02..7247434 100644
--- a/security/principal.go
+++ b/security/principal.go
@@ -9,7 +9,15 @@
 	"veyron.io/veyron/veyron2/security"
 )
 
-const privateKeyFile = "privatekey.pem"
+const (
+	blessingStoreDataFile = "blessingstore.data"
+	blessingStoreSigFile  = "blessingstore.sig"
+
+	blessingRootsDataFile = "blessingroots.data"
+	blessingRootsSigFile  = "blessingroots.sig"
+
+	privateKeyFile = "privatekey.pem"
+)
 
 // NewPrincipal mints a new private key and generates a principal based on
 // this key, storing its BlessingRoots and BlessingStore in memory.
@@ -27,7 +35,7 @@
 	return security.CreatePrincipal(signer, newInMemoryBlessingStore(signer.PublicKey()), newInMemoryBlessingRoots())
 }
 
-// NewPersistentPrincipalForSigner creates a new principal using the provided Signer and a
+// NewPersistentPrincipalFromSigner creates a new principal using the provided Signer and a
 // partial state (i.e., BlessingRoots, BlessingStore) that is read from the provided directory 'dir'.
 // Changes to the partial state are persisted and commited to the same directory; the provided
 // signer isn't persisted: the caller is expected to persist it separately or use the
@@ -100,11 +108,22 @@
 	if err != nil {
 		return nil, fmt.Errorf("failed to create serialization.Signer: %v", err)
 	}
-	roots, err := newPersistingBlessingRoots(dir, serializationSigner)
+	dataFile := path.Join(dir, blessingRootsDataFile)
+	signatureFile := path.Join(dir, blessingRootsSigFile)
+	fs, err := NewFileSerializer(dataFile, signatureFile)
+	if err != nil {
+		return nil, err
+	}
+	roots, err := newPersistingBlessingRoots(fs, serializationSigner)
 	if err != nil {
 		return nil, fmt.Errorf("failed to load BlessingRoots from %q: %v", dir, err)
 	}
-	store, err := newPersistingBlessingStore(dir, serializationSigner)
+	dataFile = path.Join(dir, blessingStoreDataFile)
+	signatureFile = path.Join(dir, blessingStoreSigFile)
+	if fs, err = NewFileSerializer(dataFile, signatureFile); err != nil {
+		return nil, err
+	}
+	store, err := newPersistingBlessingStore(fs, serializationSigner)
 	if err != nil {
 		return nil, fmt.Errorf("failed to load BlessingStore from %q: %v", dir, err)
 	}
diff --git a/security/serializer_reader_writer.go b/security/serializer_reader_writer.go
index 55248e4..633456d 100644
--- a/security/serializer_reader_writer.go
+++ b/security/serializer_reader_writer.go
@@ -2,6 +2,7 @@
 
 import (
 	"io"
+	"os"
 )
 
 // SerializerReaderWriter is a factory for managing the readers and writers used for
@@ -14,3 +15,51 @@
 	// integrity signature.
 	Writers() (data io.WriteCloser, signature io.WriteCloser, err error)
 }
+
+// FileSerializer implements SerializerReaderWriter that persists state to files.
+type FileSerializer struct {
+	data      *os.File
+	signature *os.File
+
+	dataFilePath      string
+	signatureFilePath string
+}
+
+// NewFileSerializer creates a FileSerializer with the given data and signature files.
+func NewFileSerializer(dataFilePath, signatureFilePath string) (*FileSerializer, error) {
+	data, err := os.Open(dataFilePath)
+	if err != nil && !os.IsNotExist(err) {
+		return nil, err
+	}
+	signature, err := os.Open(signatureFilePath)
+	if err != nil && !os.IsNotExist(err) {
+		return nil, err
+	}
+	return &FileSerializer{
+		data:              data,
+		signature:         signature,
+		dataFilePath:      dataFilePath,
+		signatureFilePath: signatureFilePath,
+	}, nil
+}
+
+func (fs *FileSerializer) Readers() (io.ReadCloser, io.ReadCloser, error) {
+	if fs.data == nil || fs.signature == nil {
+		return nil, nil, nil
+	}
+	return fs.data, fs.signature, nil
+}
+
+func (fs *FileSerializer) Writers() (io.WriteCloser, io.WriteCloser, error) {
+	// Remove previous version of the files
+	os.Remove(fs.dataFilePath)
+	os.Remove(fs.signatureFilePath)
+	var err error
+	if fs.data, err = os.Create(fs.dataFilePath); err != nil {
+		return nil, nil, err
+	}
+	if fs.signature, err = os.Create(fs.signatureFilePath); err != nil {
+		return nil, nil, err
+	}
+	return fs.data, fs.signature, nil
+}
diff --git a/security/storage.go b/security/storage.go
index 0dd755b..2fdd8cd 100644
--- a/security/storage.go
+++ b/security/storage.go
@@ -1,32 +1,19 @@
 package security
 
 import (
-	"io/ioutil"
-	"os"
-	"path"
+	"fmt"
+	"io"
 
 	"veyron.io/veyron/veyron/security/serialization"
-
 	"veyron.io/veyron/veyron2/security"
 	"veyron.io/veyron/veyron2/vom"
 )
 
-func encodeAndStore(obj interface{}, dir, dataFile, sigFile string, signer serialization.Signer) error {
-	// Save the object to temporary data and signature files, and then move
-	// those files to the actual data and signature file. This reduces the
-	// risk of loosing all saved data on disk in the event of a Write failure.
-	data, err := ioutil.TempFile(dir, "data")
-	if err != nil {
-		return err
+func encodeAndStore(obj interface{}, data, signature io.WriteCloser, signer serialization.Signer) error {
+	if data == nil || signature == nil {
+		return fmt.Errorf("invalid data/signature handles data:%v sig:%v", data, signature)
 	}
-	defer os.Remove(data.Name())
-	sig, err := ioutil.TempFile(dir, "sig")
-	if err != nil {
-		return err
-	}
-	defer os.Remove(sig.Name())
-
-	swc, err := serialization.NewSigningWriteCloser(data, sig, signer, nil)
+	swc, err := serialization.NewSigningWriteCloser(data, signature, signer, nil)
 	if err != nil {
 		return err
 	}
@@ -34,32 +21,16 @@
 		swc.Close()
 		return err
 	}
-	if err := swc.Close(); err != nil {
-		return err
-	}
-
-	if err := os.Rename(data.Name(), path.Join(dir, dataFile)); err != nil {
-		return err
-	}
-	return os.Rename(sig.Name(), path.Join(dir, sigFile))
+	return swc.Close()
 }
 
-func decodeFromStorage(obj interface{}, dir, dataFile, sigFile string, publicKey security.PublicKey) error {
-	data, dataErr := os.Open(path.Join(dir, dataFile))
-	defer data.Close()
-	sig, sigErr := os.Open(path.Join(dir, sigFile))
-	defer sig.Close()
-
-	switch {
-	case os.IsNotExist(dataErr) && os.IsNotExist(sigErr):
-		return nil
-	case dataErr != nil:
-		return dataErr
-	case sigErr != nil:
-		return sigErr
+func decodeFromStorage(obj interface{}, data, signature io.ReadCloser, publicKey security.PublicKey) error {
+	if data == nil || signature == nil {
+		return fmt.Errorf("invalid data/signature handles data:%v sig:%v", data, signature)
 	}
-
-	vr, err := serialization.NewVerifyingReader(data, sig, publicKey)
+	defer data.Close()
+	defer signature.Close()
+	vr, err := serialization.NewVerifyingReader(data, signature, publicKey)
 	if err != nil {
 		return err
 	}
diff --git a/services/GO.PACKAGE b/services/GO.PACKAGE
index c423766..7a09896 100644
--- a/services/GO.PACKAGE
+++ b/services/GO.PACKAGE
@@ -2,9 +2,11 @@
 	"dependencies": {
 		"incoming": [
 			{"allow": "veyron.io/veyron/veyron/services/..."},
+			{"allow": "veyron.io/veyron/veyron/lib/...", "comment":"temporarily allowing dependency from lib"},
+			{"allow": "veyron.io/veyron/veyron/profiles/...", "comment":"temporarily allowing dependency from profiles"},
 			{"allow": "veyron.io/veyron/veyron/tools/...", "comment":"temporarily allowing dependency from veyron/tools"},
 			{"allow": "veyron.io/veyron/veyron/runtimes/google/...", "comment":"temporarily allowing dependency from veyron/runtimes/google"},
-			{"allow": "veyron.io/veyron/veyron/lib/...", "comment":"temporarily allowing dependency from lib"},
+			{"allow": "veyron.io/jni/veyron/runtimes/google/...", "comment":"temporarily allowing dependency from veyron/runtimes/google"},
 			{"deny": "..."}
 		]
 	}
diff --git a/services/mgmt/binary/binaryd/test.sh b/services/mgmt/binary/binaryd/test.sh
index 2fd1661..51b7201 100755
--- a/services/mgmt/binary/binaryd/test.sh
+++ b/services/mgmt/binary/binaryd/test.sh
@@ -23,7 +23,7 @@
 
   # Start the binary repository daemon.
   local -r REPO="binaryd-test-repo"
-  shell_test::start_server "${BINARYD_BIN}" --name="${REPO}" --veyron.tcp.address=127.0.0.1:0 \
+  shell_test::start_server "${BINARYD_BIN}" --name="${REPO}" --veyron.tcp.address=127.0.0.1:0 --http=127.0.0.1:0 \
     || shell_test::fail "line ${LINENO} failed to start binaryd"
   local -r HTTP_ADDR=$(grep 'HTTP server at: "' "${START_SERVER_LOG_FILE}" | sed -e 's/^.*HTTP server at: "//' | sed -e 's/"$//')
 
diff --git a/services/mgmt/node/impl/app_invoker.go b/services/mgmt/node/impl/app_invoker.go
index 47104a5..f048999 100644
--- a/services/mgmt/node/impl/app_invoker.go
+++ b/services/mgmt/node/impl/app_invoker.go
@@ -9,6 +9,12 @@
 // <config.Root>/
 //   app-<hash 1>/                  - the application dir is named using a hash of the application title
 //     installation-<id 1>/         - installations are labelled with ids
+//       acls/
+//         data                     - the ACL data for this
+//                                    installation. Controls acces to
+//                                    Start, Uinstall, Update, UpdateTo
+//                                    and Revert.
+//         signature                -  the  signature for the ACLs in data
 //       <status>                   - one of the values for installationState enum
 //       origin                     - object name for application envelope
 //       <version 1 timestamp>/     - timestamp of when the version was downloaded
@@ -25,6 +31,12 @@
 //           logs/                  - stderr/stdout and log files generated by instance
 //           info                   - metadata for the instance (such as app cycle manager name and process id)
 //           version                - symbolic link to installation version for the instance
+//           acls/
+//             data                 - the ACLs for this instance. These
+//                                    ACLs control access to Refresh,
+//                                    Restart, Resume, Stop and
+//                                    Suspend.
+//             signature            - the signature for  these ACLs.
 //           <status>               - one of the values for instanceState enum
 //           systemname             - the system name used to execute this instance
 //         instance-<id b>
@@ -97,6 +109,7 @@
 	"os"
 	"os/exec"
 	"os/user"
+	"path"
 	"path/filepath"
 	"reflect"
 	"strings"
@@ -165,6 +178,9 @@
 	// instance.
 	suffix []string
 	uat    BlessingSystemAssociationStore
+	locks  aclLocks
+	// Reference to the nodemanager top-level ACL list.
+	nodeACL security.ACL
 }
 
 func saveEnvelope(dir string, envelope *application.Envelope) error {
@@ -304,7 +320,30 @@
 	return versionDir, updateLink(versionDir, filepath.Join(installationDir, "current"))
 }
 
-func (i *appInvoker) Install(_ ipc.ServerContext, applicationVON string) (string, error) {
+// 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)
+	}
+	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")
+	return writeACLs(aclData, aclSig, aclDir, acl)
+}
+
+func (i *appInvoker) Install(call ipc.ServerContext, applicationVON string) (string, error) {
 	if len(i.suffix) > 0 {
 		return "", errInvalidSuffix
 	}
@@ -333,6 +372,10 @@
 	if err := initializeInstallation(installationDir, active); err != nil {
 		return "", err
 	}
+
+	if err := initializeInstallationACLs(installationDir, call.RemoteBlessings().ForContext(call), i.nodeACL); err != nil {
+		return "", err
+	}
 	deferrer = nil
 	return naming.Join(envelope.Title, installationID), nil
 }
@@ -357,17 +400,12 @@
 	return file, nil
 }
 
-// installationDir returns the path to the directory containing the app
-// installation referred to by the invoker's suffix.  Returns an error if the
-// suffix does not name an installation or if the named installation does not
-// exist.
-func (i *appInvoker) installationDir() (string, error) {
-	components := i.suffix
+func installationDirCore(components []string, root string) (string, error) {
 	if nComponents := len(components); nComponents != 2 {
 		return "", errInvalidSuffix
 	}
 	app, installation := components[0], components[1]
-	installationDir := filepath.Join(i.config.Root, applicationDirName(app), installationDirName(installation))
+	installationDir := filepath.Join(root, applicationDirName(app), installationDirName(installation))
 	if _, err := os.Stat(installationDir); err != nil {
 		if os.IsNotExist(err) {
 			return "", errNotExist
@@ -469,6 +507,34 @@
 	return nil
 }
 
+// installationDir returns the path to the directory containing the app
+// installation referred to by the invoker's suffix.  Returns an error if the
+// suffix does not name an installation or if the named installation does not
+// exist.
+func (i *appInvoker) installationDir() (string, error) {
+	return installationDirCore(i.suffix, i.config.Root)
+}
+
+func initializeInstanceACLs(key, installationDir, 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)
+	}
+
+	labels := security.AllLabels
+	for _, name := range blessings {
+		// TODO(rjkroege): Use custom labels.
+		acl.In[security.BlessingPattern(name)] = labels
+	}
+
+	aclDir := path.Join(instanceDir, "acls")
+	aclData := path.Join(aclDir, "data")
+	aclSig := path.Join(aclDir, "signature")
+
+	return writeACLs(aclData, aclSig, aclDir, acl)
+}
+
 // newInstance sets up the directory for a new application instance.
 func (i *appInvoker) newInstance(call ipc.ServerContext) (string, string, error) {
 	installationDir, err := i.installationDir()
@@ -504,6 +570,10 @@
 	if err := initializeInstance(instanceDir, suspended); err != nil {
 		return instanceDir, instanceID, err
 	}
+
+	if err := initializeInstanceACLs(installationDir, installationDir, instanceDir, call.RemoteBlessings().ForContext(call), i.nodeACL); err != nil {
+		return instanceDir, instanceID, err
+	}
 	return instanceDir, instanceID, nil
 }
 
@@ -676,6 +746,7 @@
 func (i *appInvoker) Start(call ipc.ServerContext) ([]string, error) {
 	helper := i.config.Helper
 	instanceDir, instanceID, err := i.newInstance(call)
+
 	if err != nil {
 		cleanupDir(instanceDir, helper)
 		return nil, err
@@ -1071,3 +1142,41 @@
 		return
 	}
 }
+
+// TODO(rjkroege): Refactor to eliminate redundancy with newAppSpecificAuthorizer.
+func dirFromSuffix(suffix []string, root string) (string, error) {
+	if len(suffix) == 2 {
+		p, err := installationDirCore(suffix, root)
+		if err != nil {
+			vlog.Errorf("dirFromSuffix failed: %v", err)
+			return "", err
+		}
+		return p, nil
+	} else if len(suffix) > 2 {
+		p, err := instanceDir(root, suffix[0:3])
+		if err != nil {
+			vlog.Errorf("dirFromSuffix failed: %v", err)
+			return "", err
+		}
+		return p, nil
+	}
+	return "", errInvalidSuffix
+}
+
+// TODO(rjkroege): Consider maintaining an in-memory ACL cache.
+// TODO(rjkroege): Excise the idea of the key. Use the dir instead.
+func (i *appInvoker) SetACL(_ ipc.ServerContext, acl security.ACL, etag string) error {
+	dir, err := dirFromSuffix(i.suffix, i.config.Root)
+	if err != nil {
+		return err
+	}
+	return setAppACL(i.locks, dir, dir, acl, etag)
+}
+
+func (i *appInvoker) GetACL(_ ipc.ServerContext) (acl security.ACL, etag string, err error) {
+	dir, err := dirFromSuffix(i.suffix, i.config.Root)
+	if err != nil {
+		return security.ACL{}, "", err
+	}
+	return getAppACL(i.locks, dir, dir)
+}
diff --git a/services/mgmt/node/impl/dispatcher.go b/services/mgmt/node/impl/dispatcher.go
index f41df15..b29347f 100644
--- a/services/mgmt/node/impl/dispatcher.go
+++ b/services/mgmt/node/impl/dispatcher.go
@@ -7,6 +7,7 @@
 	"fmt"
 	"io/ioutil"
 	"os"
+	"path"
 	"path/filepath"
 	"strings"
 	"sync"
@@ -37,6 +38,9 @@
 	updating *updatingState
 }
 
+// aclLocks provides a mutex lock for each acl file path.
+type aclLocks map[string]*sync.Mutex
+
 // dispatcher holds the state of the node manager dispatcher.
 type dispatcher struct {
 	// acl/auth hold the acl and authorizer used to authorize access to the
@@ -54,6 +58,8 @@
 	// dispatcher methods.
 	mu  sync.RWMutex
 	uat BlessingSystemAssociationStore
+	// TODO(rjkroege): Eliminate need for locks.
+	locks aclLocks
 }
 
 var _ ipc.Dispatcher = (*dispatcher)(nil)
@@ -93,6 +99,7 @@
 		},
 		config: config,
 		uat:    uat,
+		locks:  make(aclLocks),
 	}
 	// If there exists a signed ACL from a previous instance we prefer that.
 	aclFile, sigFile, _ := d.getACLFilePaths()
@@ -138,6 +145,7 @@
 
 func (d *dispatcher) claimNodeManager(names []string, proof security.Blessings) error {
 	// TODO(gauthamt): Should we start trusting these identity providers?
+	// 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
@@ -154,62 +162,158 @@
 		vlog.Errorf("Failed to getACL:%v", err)
 		return errOperationFailed
 	}
-	return d.setACL(acl, etag, true /* store ACL on disk */)
+	if err := d.setACL(acl, etag, true /* store ACL on disk */); err != nil {
+		vlog.Errorf("Failed to setACL:%v", err)
+		return errOperationFailed
+	}
+	return nil
+}
+
+// TODO(rjkroege): Further refactor ACL-setting code.
+func setAppACL(locks aclLocks, key, dir string, acl security.ACL, etag string) error {
+	aclpath := path.Join(dir, "acls", "data")
+	sigpath := path.Join(dir, "acls", "signature")
+
+	// Acquire lock. Locks are per path to an acls file.
+	lck, contains := locks[key]
+	if !contains {
+		lck = new(sync.Mutex)
+		locks[key] = lck
+	}
+	lck.Lock()
+	defer lck.Unlock()
+
+	f, err := os.Open(aclpath)
+	if err != nil {
+		vlog.Errorf("LoadACL(%s) failed: %v", aclpath, err)
+		return err
+	}
+	defer f.Close()
+
+	curACL, err := vsecurity.LoadACL(f)
+	if err != nil {
+		vlog.Errorf("LoadACL(%s) failed: %v", aclpath, err)
+		return err
+	}
+	curEtag, err := computeEtag(curACL)
+	if err != nil {
+		vlog.Errorf("computeEtag failed: %v", err)
+		return err
+	}
+
+	if len(etag) > 0 && etag != curEtag {
+		return verror.Make(access.ErrBadEtag, fmt.Sprintf("etag mismatch in:%s vers:%s", etag, curEtag))
+	}
+
+	return writeACLs(aclpath, sigpath, dir, acl)
+}
+
+// TODO(rjkroege): Use the dir as the key.
+func getAppACL(locks aclLocks, key, dir string) (security.ACL, string, error) {
+	aclpath := path.Join(dir, "acls", "data")
+
+	// Acquire lock. Locks are per path to an acls file.
+	lck, contains := locks[key]
+	if !contains {
+		lck = new(sync.Mutex)
+		locks[key] = lck
+	}
+	lck.Lock()
+	defer lck.Unlock()
+
+	f, err := os.Open(aclpath)
+	if err != nil {
+		vlog.Errorf("LoadACL(%s) failed: %v", aclpath, err)
+		return security.ACL{}, "", err
+	}
+	defer f.Close()
+
+	acl, err := vsecurity.LoadACL(f)
+	if err != nil {
+		vlog.Errorf("LoadACL(%s) failed: %v", aclpath, err)
+		return security.ACL{}, "", err
+	}
+	curEtag, err := computeEtag(acl)
+	if err != nil {
+		return security.ACL{}, "", err
+	}
+
+	if err != nil {
+		return security.ACL{}, "", err
+	}
+	return acl, curEtag, nil
+}
+
+func computeEtag(acl security.ACL) (string, error) {
+	b := new(bytes.Buffer)
+	if err := vsecurity.SaveACL(b, acl); err != nil {
+		vlog.Errorf("Failed to save ACL:%v", err)
+		return "", err
+	}
+	// Update the acl/etag/authorizer for this dispatcher
+	md5hash := md5.Sum(b.Bytes())
+	etag := hex.EncodeToString(md5hash[:])
+	return etag, nil
+}
+
+func writeACLs(aclFile, sigFile, dir string, acl security.ACL) error {
+	// Create dir directory if it does not exist
+	os.MkdirAll(dir, os.FileMode(0700))
+	// Save the object to temporary data and signature files, and then move
+	// those files to the actual data and signature file.
+	data, err := ioutil.TempFile(dir, "data")
+	if err != nil {
+		vlog.Errorf("Failed to open tmpfile data:%v", err)
+		return errOperationFailed
+	}
+	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
+	}
+	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
+	}
+	if err = vsecurity.SaveACL(writer, acl); err != nil {
+		vlog.Errorf("Failed to SaveACL:%v", err)
+		return errOperationFailed
+	}
+	if err = writer.Close(); err != nil {
+		vlog.Errorf("Failed to Close() SigningWriteCloser:%v", err)
+		return errOperationFailed
+	}
+	if err := os.Rename(data.Name(), aclFile); err != nil {
+		return err
+	}
+	if err := os.Rename(sig.Name(), sigFile); err != nil {
+		return err
+	}
+	return nil
 }
 
 func (d *dispatcher) setACL(acl security.ACL, etag string, writeToFile bool) error {
 	d.mu.Lock()
 	defer d.mu.Unlock()
+	aclFile, sigFile, nodedata := d.getACLFilePaths()
+
 	if len(etag) > 0 && etag != d.etag {
 		return verror.Make(access.ErrBadEtag, fmt.Sprintf("etag mismatch in:%s vers:%s", etag, d.etag))
 	}
 	if writeToFile {
-		// Create nodedata directory if it does not exist
-		aclFile, sigFile, nodedata := d.getACLFilePaths()
-		os.MkdirAll(nodedata, os.FileMode(0700))
-		// Save the object to temporary data and signature files, and then move
-		// those files to the actual data and signature file.
-		data, err := ioutil.TempFile(nodedata, "data")
-		if err != nil {
-			vlog.Errorf("Failed to open tmpfile data:%v", err)
-			return errOperationFailed
-		}
-		defer os.Remove(data.Name())
-		sig, err := ioutil.TempFile(nodedata, "sig")
-		if err != nil {
-			vlog.Errorf("Failed to open tmpfile sig:%v", err)
-			return errOperationFailed
-		}
-		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
-		}
-		if err = vsecurity.SaveACL(writer, acl); err != nil {
-			vlog.Errorf("Failed to SaveACL:%v", err)
-			return errOperationFailed
-		}
-		if err = writer.Close(); err != nil {
-			vlog.Errorf("Failed to Close() SigningWriteCloser:%v", err)
-			return errOperationFailed
-		}
-		if err := os.Rename(data.Name(), aclFile); err != nil {
-			return err
-		}
-		if err := os.Rename(sig.Name(), sigFile); err != nil {
+		if err := writeACLs(aclFile, sigFile, nodedata, acl); err != nil {
 			return err
 		}
 	}
-	// update the etag for the ACL
-	var b bytes.Buffer
-	if err := vsecurity.SaveACL(&b, acl); err != nil {
-		vlog.Errorf("Failed to save ACL:%v", err)
-		return errOperationFailed
+
+	etag, err := computeEtag(acl)
+	if err != nil {
+		return err
 	}
-	// Update the acl/etag/authorizer for this dispatcher
-	md5hash := md5.Sum(b.Bytes())
-	d.acl, d.etag, d.auth = acl, hex.EncodeToString(md5hash[:]), vsecurity.NewACLAuthorizer(acl)
+	d.acl, d.etag, d.auth = acl, etag, vsecurity.NewACLAuthorizer(acl)
 	return nil
 }
 
@@ -220,7 +324,6 @@
 }
 
 // DISPATCHER INTERFACE IMPLEMENTATION
-
 func (d *dispatcher) Lookup(suffix, method string) (interface{}, security.Authorizer, error) {
 	components := strings.Split(suffix, "/")
 	for i := 0; i < len(components); i++ {
@@ -287,16 +390,23 @@
 				return &proxyInvoker{remote, label, sigStub}, d.auth, nil
 			}
 		}
+		nodeACLs, _, err := d.getACL()
+		if err != nil {
+			return nil, nil, err
+		}
 		receiver := node.ApplicationServer(&appInvoker{
 			callback: d.internal.callback,
 			config:   d.config,
 			suffix:   components[1:],
 			uat:      d.uat,
+			locks:    d.locks,
+			nodeACL:  nodeACLs,
 		})
-		// TODO(caprita,rjkroege): Once we implement per-object ACLs
-		// (i.e. each installation and instance), replace d.auth with
-		// per-object authorizer.
-		return ipc.ReflectInvoker(receiver), d.auth, nil
+		appSpecificAuthorizer, err := newAppSpecificAuthorizer(d.auth, d.config, components[1:])
+		if err != nil {
+			return nil, nil, err
+		}
+		return ipc.ReflectInvoker(receiver), appSpecificAuthorizer, nil
 	case configSuffix:
 		if len(components) != 2 {
 			return nil, nil, errInvalidSuffix
@@ -317,3 +427,32 @@
 		return nil, nil, errInvalidSuffix
 	}
 }
+
+func newAppSpecificAuthorizer(sec security.Authorizer, config *config.State, suffix []string) (security.Authorizer, error) {
+	// TODO(rjkroege): This does not support <appname>.Start() to start all instances. Correct this.
+
+	// If we are attempting a method invocation against "apps/", we use the node-manager wide ACL.
+	if len(suffix) == 0 || len(suffix) == 1 {
+		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 {
+		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 nil, errInvalidSuffix
+}
diff --git a/services/mgmt/node/impl/impl_test.go b/services/mgmt/node/impl/impl_test.go
index 8367a64..9185c2f 100644
--- a/services/mgmt/node/impl/impl_test.go
+++ b/services/mgmt/node/impl/impl_test.go
@@ -1,5 +1,6 @@
 // TODO(caprita): This file is becoming unmanageable; split into several test
 // files.
+// TODO(rjkroege): Add a more extensive unit test case to exercise ACL logic.
 
 package impl_test
 
@@ -1285,7 +1286,7 @@
 	vlog.VI(2).Infof("other attempting to run an app without access. Should fail.")
 	startAppExpectError(t, appID, verror.NoAccess, otherRT)
 
-	// Self will now let other also run apps.
+	// Self will now let other also install apps.
 	if err := nodeStub.AssociateAccount(selfRT.NewContext(), []string{"root/other"}, testUserName); err != nil {
 		t.Fatalf("AssociateAccount failed %v", err)
 	}
@@ -1294,11 +1295,28 @@
 	if err != nil {
 		t.Fatalf("GetACL failed %v", err)
 	}
-	newACL.In["root/other/..."] = security.AllLabels
+	newACL.In["root/other/..."] = security.LabelSet(security.WriteLabel)
 	if err := nodeStub.SetACL(selfRT.NewContext(), newACL, ""); err != nil {
 		t.Fatalf("SetACL failed %v", err)
 	}
 
+	// With the introduction of per installation and per instance ACLs, while other now
+	// has administrator permissions on the node manager, other doesn't have execution
+	// permissions for the app. So this will fail.
+	vlog.VI(2).Infof("other attempting to run an app still without access. Should fail.")
+	startAppExpectError(t, appID, verror.NoAccess, otherRT)
+
+	// But self can give other permissions  to start applications.
+	vlog.VI(2).Infof("self attempting to give other permission to start %s", appID)
+	newACL, _, err = appStub(appID).GetACL(selfRT.NewContext())
+	if err != nil {
+		t.Fatalf("GetACL on appID: %v failed %v", appID, err)
+	}
+	newACL.In["root/other/..."] = security.LabelSet(security.ReadLabel)
+	if err = appStub(appID).SetACL(selfRT.NewContext(), newACL, ""); err != nil {
+		t.Fatalf("SetACL on appID: %v failed: %v", appID, err)
+	}
+
 	vlog.VI(2).Infof("other attempting to run an app with access. Should succeed.")
 	instance2ID := startApp(t, appID, otherRT)
 	verifyHelperArgs(t, pingCh, testUserName) // Wait until the app pings us that it's ready.
@@ -1309,6 +1327,16 @@
 	verifyHelperArgs(t, pingCh, testUserName) // Wait until the app pings us that it's ready.
 	suspendApp(t, appID, instance2ID, otherRT)
 
+	vlog.VI(2).Infof("Verify that other can install and run applications.")
+	otherAppID := installApp(t, otherRT)
+
+	vlog.VI(2).Infof("other attempting to run an app that other installed. Should succeed.")
+	instance4ID := startApp(t, otherAppID, otherRT)
+	verifyHelperArgs(t, pingCh, testUserName) // Wait until the app pings us that it's ready.
+
+	// Clean up.
+	stopApp(t, otherAppID, instance4ID, otherRT)
+
 	// Change the associated system name.
 	if err := nodeStub.AssociateAccount(selfRT.NewContext(), []string{"root/other"}, anotherTestUserName); err != nil {
 		t.Fatalf("AssociateAccount failed %v", err)
diff --git a/tools/debug/test.sh b/tools/debug/test.sh
index b3078b0..8c38207 100755
--- a/tools/debug/test.sh
+++ b/tools/debug/test.sh
@@ -62,7 +62,7 @@
   shell_test::assert_eq "${GOT}" "${WANT}" "${LINENO}"
 
   # Test stats read.
-  GOT=$("${DEBUG_BIN}" stats read "${EP}/__debug/stats/ipc/server/*/ReadLog/latency-ms" 2> "${DBGLOG}" | wc -l) \
+  GOT=$("${DEBUG_BIN}" 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}"
 
@@ -70,7 +70,7 @@
   local TMP=$(shell::tmp_file)
   touch "${TMP}"
   local -r DEBUG_PID=$(shell::run_server "${shell_test_DEFAULT_SERVER_TIMEOUT}" "${TMP}" "${DBGLOG}" \
-    "${DEBUG_BIN}" stats watch -raw "${EP}/__debug/stats/ipc/server/*/ReadLog/latency-ms")
+    "${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")
diff --git a/tools/mgmt/node/impl.go b/tools/mgmt/node/impl.go
index b538977..9758d72 100644
--- a/tools/mgmt/node/impl.go
+++ b/tools/mgmt/node/impl.go
@@ -45,6 +45,7 @@
 	ArgsLong: `
 <application installation> is the veyron object name of the
 application installation from which to start an instance.
+
 <grant extension> is used to extend the default blessing of the
 current principal when blessing the app instance.`,
 }
@@ -74,6 +75,31 @@
 	return nil
 }
 
+var cmdClaim = &cmdline.Command{
+	Run:      runClaim,
+	Name:     "claim",
+	Short:    "Claim the node.",
+	Long:     "Claim the node.",
+	ArgsName: "<node> <grant extension>",
+	ArgsLong: `
+<node> is the veyron object name of the node manager's app service.
+
+<grant extension> is used to extend the default blessing of the
+current principal when blessing the app instance.`,
+}
+
+func runClaim(cmd *cmdline.Command, args []string) error {
+	if expected, got := 2, len(args); expected != got {
+		return cmd.UsageErrorf("claim: incorrect number of arguments, expected %d, got %d", expected, got)
+	}
+	nodeName, grant := args[0], args[1]
+	if err := node.NodeClient(nodeName).Claim(rt.R().NewContext(), &granter{p: rt.R().Principal(), extension: grant}); err != nil {
+		return fmt.Errorf("Claim failed: %v", err)
+	}
+	fmt.Fprintln(cmd.Stdout(), "Successfully claimed.")
+	return nil
+}
+
 func root() *cmdline.Command {
 	return &cmdline.Command{
 		Name:  "node",
@@ -81,6 +107,6 @@
 		Long: `
 The node tool facilitates interaction with the veyron node manager.
 `,
-		Children: []*cmdline.Command{cmdInstall, cmdStart},
+		Children: []*cmdline.Command{cmdInstall, cmdStart, cmdClaim},
 	}
 }