veyron2/security,veyron/runtimes/google/ipc: Provide context to a discharger.

(Originally done by andreser@, I took over the change since he's left after
completing his internship)

This commit adds the interfaces and plumbing to:
(a) Allow ThirdPartyCaveats to specify what information should be reported
    to the third-party issuing discharges
(b) Sending that information and making it available to the Discharger
    RPC service so that implementations can make decisions on whether or
    not to discharge and to bind the discharge to a specific use.

Consider the following use-case:
- I provide a blessing to my child's device that allows the device to
  watch movies from my content provider.
  This blessing includes a ThirdPartyCaveat that requires a discharge
  from me (i.e., a Discharger service running on my device)
- When my child tries to view a movie, the context pops up on my device
  asking for permission. Based on the context (which movie is being
  requested for example), I issue a discharge with caveats, for example:
  (a) Discharge is valid for any G rated movie
  (b) Discharge is valid only for a specific movie otherwise.

Without this additional context, I had no useful information other than
the fact that a "discharge is being requested" in order to guide my
decision on whether or not to issue a discharge and what caveats to put
on it.

Change-Id: I079fba0d3848b4f630bccde719f50047e81d9008
diff --git a/runtimes/google/ipc/client.go b/runtimes/google/ipc/client.go
index 27bc6f7..2b982c4 100644
--- a/runtimes/google/ipc/client.go
+++ b/runtimes/google/ipc/client.go
@@ -155,7 +155,7 @@
 			continue
 		}
 
-		discharges := c.prepareDischarges(ctx, flow.LocalID(), flow.RemoteID(), method, opts)
+		discharges := c.prepareDischarges(ctx, flow.LocalID(), flow.RemoteID(), method, args, opts)
 
 		lastErr = nil
 		fc := newFlowClient(flow, &c.dischargeCache, discharges)
diff --git a/runtimes/google/ipc/discharges.go b/runtimes/google/ipc/discharges.go
index 4f2a665..e8504cb 100644
--- a/runtimes/google/ipc/discharges.go
+++ b/runtimes/google/ipc/discharges.go
@@ -15,8 +15,7 @@
 // options, or requested from the discharge issuer indicated on the caveat.
 // Note that requesting a discharge is an ipc call, so one copy of this
 // function must be able to successfully terminate while another is blocked.
-func (c *client) prepareDischarges(ctx context.T, blessing, server security.PublicID,
-	method string, opts []ipc.CallOpt) (ret []security.ThirdPartyDischarge) {
+func (c *client) prepareDischarges(ctx context.T, blessing, server security.PublicID, method string, args []interface{}, opts []ipc.CallOpt) (ret []security.ThirdPartyDischarge) {
 	// TODO(andreser,ataly): figure out whether this should return an error and how that should be handled
 	// Missing discharges do not necessarily mean the blessing is invalid (e.g., SetID)
 	if blessing == nil {
@@ -37,7 +36,7 @@
 	dischargesFromOpts(caveats, opts, discharges)
 	c.dischargeCache.Discharges(caveats, discharges)
 	if shouldFetchDischarges(opts) {
-		c.fetchDischarges(ctx, caveats, opts, discharges)
+		c.fetchDischarges(ctx, caveats, server, method, args, opts, discharges)
 	}
 	for _, d := range discharges {
 		if d != nil {
@@ -112,7 +111,7 @@
 // caveats, fetchDischarges keeps retrying until either all discharges can be
 // fetched or no new discharges are fetched.
 // REQUIRES: len(caveats) == len(out)
-func (c *client) fetchDischarges(ctx context.T, caveats []security.ThirdPartyCaveat, opts []ipc.CallOpt, out []security.ThirdPartyDischarge) {
+func (c *client) fetchDischarges(ctx context.T, caveats []security.ThirdPartyCaveat, server security.PublicID, method string, args []interface{}, opts []ipc.CallOpt, out []security.ThirdPartyDischarge) {
 	opts = append([]ipc.CallOpt{dontFetchDischarges{}}, opts...)
 	var wg sync.WaitGroup
 	for {
@@ -128,8 +127,8 @@
 			wg.Add(1)
 			go func(i int, cav security.ThirdPartyCaveat) {
 				defer wg.Done()
-				vlog.VI(3).Infof("Fetching discharge for %T from %v", cav, cav.Location())
-				call, err := c.StartCall(ctx, cav.Location(), "Discharge", []interface{}{cav}, opts...)
+				vlog.VI(3).Infof("Fetching discharge for %T from %v (%+v)", cav, cav.Location(), cav.Requirements())
+				call, err := c.StartCall(ctx, cav.Location(), "Discharge", []interface{}{cav, impetus(cav.Requirements(), server, method, args)}, opts...)
 				if err != nil {
 					vlog.VI(3).Infof("Discharge fetch for caveat %T from %v failed: %v", cav, cav.Location(), err)
 					return
@@ -163,7 +162,23 @@
 	}
 }
 
-// dontFetchDischares is an ipc.CallOpt that indicates that no extre ipc-s
+func impetus(r security.ThirdPartyRequirements, server security.PublicID, method string, args []interface{}) (impetus security.DischargeImpetus) {
+	if r.ReportServer {
+		impetus.Server = server
+	}
+	if r.ReportMethod {
+		impetus.Method = method
+	}
+	if r.ReportArguments {
+		impetus.Arguments = make([]vdlutil.Any, len(args))
+		for i, a := range args {
+			impetus.Arguments[i] = vdlutil.Any(a)
+		}
+	}
+	return
+}
+
+// dontFetchDischares is an ipc.CallOpt that indicates that no extra ipc-s
 // should be done to fetch discharges for the call with this opt.
 // Discharges in the cache and in the call options are still used.
 type dontFetchDischarges struct{}
diff --git a/runtimes/google/ipc/full_test.go b/runtimes/google/ipc/full_test.go
index c626c57..d62f1cc 100644
--- a/runtimes/google/ipc/full_test.go
+++ b/runtimes/google/ipc/full_test.go
@@ -129,7 +129,7 @@
 
 type dischargeServer struct{}
 
-func (*dischargeServer) Discharge(ctx ipc.ServerCall, caveat vdlutil.Any) (vdlutil.Any, error) {
+func (*dischargeServer) Discharge(ctx ipc.ServerCall, caveat vdlutil.Any, _ security.DischargeImpetus) (vdlutil.Any, error) {
 	c, ok := caveat.(security.ThirdPartyCaveat)
 	if !ok {
 		return nil, fmt.Errorf("discharger: unknown caveat(%T)", caveat)
@@ -637,13 +637,93 @@
 }
 
 func mkThirdPartyCaveat(discharger security.PublicID, location string, c security.Caveat) security.ThirdPartyCaveat {
-	tpc, err := caveat.NewPublicKeyCaveat(c, discharger, location)
+	tpc, err := caveat.NewPublicKeyCaveat(c, discharger, location, security.ThirdPartyRequirements{})
 	if err != nil {
 		panic(err)
 	}
 	return tpc
 }
 
+type dischargeImpetusTester struct {
+	LastDischargeImpetus security.DischargeImpetus
+}
+
+// Implements ipc.Dispatcher
+func (s *dischargeImpetusTester) Lookup(_, _ string) (ipc.Invoker, security.Authorizer, error) {
+	return ipc.ReflectInvoker(s), nil, nil
+}
+
+// Implements the discharge service: Always fails to issue a discharge, but records the impetus
+func (s *dischargeImpetusTester) Discharge(ctx ipc.ServerCall, cav vdlutil.Any, impetus security.DischargeImpetus) (vdlutil.Any, error) {
+	s.LastDischargeImpetus = impetus
+	return nil, fmt.Errorf("discharges not issued")
+}
+
+func TestDischargeImpetus(t *testing.T) {
+	var (
+		// The Discharge service can be run by anyone, but in these tests it is the same as the server.
+		dischargerID = serverID.PublicID()
+
+		mkClientID = func(req security.ThirdPartyRequirements) security.PrivateID {
+			tpc, err := caveat.NewPublicKeyCaveat(alwaysValidCaveat{}, dischargerID, "mountpoint/discharger", req)
+			if err != nil {
+				t.Fatalf("Failed to create ThirdPartyCaveat: %v", err)
+			}
+			caveat := security.UniversalCaveat(tpc)
+			return deriveForThirdPartyCaveats(serverID, "client", caveat)
+		}
+	)
+	sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
+	ns := newNamespace()
+	server, err := InternalNewServer(InternalNewContext(), sm, ns, vc.FixedLocalID(serverID))
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer server.Stop()
+	if _, err := server.Listen("tcp", "127.0.0.1:0"); err != nil {
+		t.Fatal(err)
+	}
+
+	var tester dischargeImpetusTester
+	if err := server.Serve("mountpoint", &tester); err != nil {
+		t.Fatal(err)
+	}
+
+	tests := []struct {
+		Requirements security.ThirdPartyRequirements
+		Impetus      security.DischargeImpetus
+	}{
+		{ // No requirements, no impetus
+			Requirements: security.ThirdPartyRequirements{},
+			Impetus:      security.DischargeImpetus{},
+		},
+		{ // Require everything
+			Requirements: security.ThirdPartyRequirements{ReportServer: true, ReportMethod: true, ReportArguments: true},
+			Impetus:      security.DischargeImpetus{Server: vdlutil.Any(serverID.PublicID()), Method: "Method", Arguments: []vdlutil.Any{vdlutil.Any("argument")}},
+		},
+		{ // Require only the method name
+			Requirements: security.ThirdPartyRequirements{ReportMethod: true},
+			Impetus:      security.DischargeImpetus{Method: "Method"},
+		},
+	}
+
+	for _, test := range tests {
+		client, err := InternalNewClient(sm, ns, vc.FixedLocalID(mkClientID(test.Requirements)))
+		if err != nil {
+			t.Fatalf("InternalNewClient(%+v) failed: %v", test.Requirements, err)
+		}
+		defer client.Close()
+		// StartCall should fetch the discharge, do not worry about finishing the RPC - do not care about that for this test.
+		if _, err := client.StartCall(InternalNewContext(), "mountpoint/object", "Method", []interface{}{"argument"}); err != nil {
+			t.Errorf("StartCall(%+v) failed: %v", test.Requirements, err)
+			continue
+		}
+		if got, want := tester.LastDischargeImpetus, test.Impetus; !reflect.DeepEqual(got, want) {
+			t.Errorf("Got [%v] want [%v] for test %+v", got, want, test.Requirements)
+		}
+	}
+}
+
 func TestRPCAuthorization(t *testing.T) {
 	var (
 		now = time.Now()
diff --git a/runtimes/google/security/identity_test.go b/runtimes/google/security/identity_test.go
index 0ea92dc..065f351 100644
--- a/runtimes/google/security/identity_test.go
+++ b/runtimes/google/security/identity_test.go
@@ -411,7 +411,7 @@
 
 func TestThirdPartyCaveatMinting(t *testing.T) {
 	minter := newChain("minter")
-	cav, err := caveat.NewPublicKeyCaveat(proximityCaveat{}, minter.PublicID(), "location")
+	cav, err := caveat.NewPublicKeyCaveat(proximityCaveat{}, minter.PublicID(), "location", security.ThirdPartyRequirements{})
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -443,7 +443,7 @@
 		return derive(bless(id.PublicID(), googleChain, name, nil), id)
 	}
 	mkcaveat := func(id security.PrivateID) []security.ServiceCaveat {
-		c, err := caveat.NewPublicKeyCaveat(alwaysValidCaveat{}, id.PublicID(), fmt.Sprintf("%v location", id.PublicID()))
+		c, err := caveat.NewPublicKeyCaveat(alwaysValidCaveat{}, id.PublicID(), fmt.Sprintf("%v location", id.PublicID()), security.ThirdPartyRequirements{})
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -564,7 +564,7 @@
 
 func TestThirdPartyCaveatAccessors(t *testing.T) {
 	mkTPCaveat := func(id security.PublicID) security.ThirdPartyCaveat {
-		tpCav, err := caveat.NewPublicKeyCaveat(alwaysValidCaveat{}, id, "someLocation")
+		tpCav, err := caveat.NewPublicKeyCaveat(alwaysValidCaveat{}, id, "someLocation", security.ThirdPartyRequirements{})
 		if err != nil {
 			t.Fatalf("NewPublicKeyCaveat(%q, ...) failed: %v", id, err)
 		}
diff --git a/security/audit/id_test.go b/security/audit/id_test.go
index ed626bf..bf1c04c 100644
--- a/security/audit/id_test.go
+++ b/security/audit/id_test.go
@@ -242,6 +242,9 @@
 func (thirdPartyCaveat) Validate(security.Context) error { return nil }
 func (thirdPartyCaveat) ID() security.ThirdPartyCaveatID { return "thirdPartyCaveatID" }
 func (thirdPartyCaveat) Location() string                { return "thirdPartyCaveatLocation" }
+func (thirdPartyCaveat) Requirements() security.ThirdPartyRequirements {
+	return security.ThirdPartyRequirements{}
+}
 
 // context implements security.Context
 type context struct{}
diff --git a/security/caveat/public_key_caveat.go b/security/caveat/public_key_caveat.go
index 975cbc4..636d89b 100644
--- a/security/caveat/public_key_caveat.go
+++ b/security/caveat/public_key_caveat.go
@@ -36,18 +36,17 @@
 	// RandNonce specifies a cryptographically random nonce (of fixed length) that
 	// uniquely identifies the caveat.
 	RandNonce []uint8
-
 	// DischargeMintingCaveat specifies the caveat that has to be validated
 	// before minting a discharge for a publicKeyCaveat. A byte slice containing
 	// VOM-encoded security.Caveat is used to enable a publicKeyCaveat to be
 	// validated by devices that cannot decode the discharge minting caveats.
 	DischargeMintingCaveat []byte
-
 	// ValidationKey specifies the public key of the discharging-party.
 	ValidationKey wire.PublicKey
-
-	// ThirdPartyLocation specifies the global Object name of the discharging-party.
+	// ThirdPartyLocation specifies the object name of the discharging-party.
 	ThirdPartyLocation string
+	// Information wanted in order to issue a discharge.
+	ThirdPartyRequirements security.ThirdPartyRequirements
 }
 
 // ID returns a unique 32bytes long identity for the caveat based on the random nonce
@@ -68,6 +67,10 @@
 	return fmt.Sprintf("publicKeyCaveat{DischargeMintingCaveat: (%v bytes), ThirdPartyLocation: %q}", len(c.DischargeMintingCaveat), c.ThirdPartyLocation)
 }
 
+func (c *publicKeyCaveat) Requirements() security.ThirdPartyRequirements {
+	return c.ThirdPartyRequirements
+}
+
 // Validate verifies whether the caveat validates for the provided context.
 func (c *publicKeyCaveat) Validate(ctx security.Context) error {
 	// Check whether the context has a dicharge matching the caveat's ID.
@@ -146,7 +149,7 @@
 
 // NewPublicKeyCaveat returns a new third-party caveat from the provided restriction,
 // third-party identity, and third-party location.
-func NewPublicKeyCaveat(dischargeMintingCaveat security.Caveat, thirdParty security.PublicID, location string) (security.ThirdPartyCaveat, error) {
+func NewPublicKeyCaveat(dischargeMintingCaveat security.Caveat, thirdParty security.PublicID, location string, requirements security.ThirdPartyRequirements) (security.ThirdPartyCaveat, error) {
 	nonce := make([]uint8, nonceLength)
 	if _, err := rand.Read(nonce); err != nil {
 		return nil, err
@@ -164,6 +167,7 @@
 		DischargeMintingCaveat: mintingCaveatEncoded.Bytes(),
 		ValidationKey:          validationKey,
 		ThirdPartyLocation:     location,
+		ThirdPartyRequirements: requirements,
 	}, nil
 }
 
diff --git a/services/security/discharger.vdl b/services/security/discharger.vdl
index 138e9bb..95202d1 100644
--- a/services/security/discharger.vdl
+++ b/services/security/discharger.vdl
@@ -2,14 +2,15 @@
 
 import "veyron2/security"
 
-// DischargeIssuer service issues caveat discharges when requested.
+// Discharger is the interface for obtaining discharges for ThirdPartyCaveats.
 type Discharger interface {
   // Discharge is called by a principal that holds a blessing with a third
   // party caveat and seeks to get a discharge that proves the fulfillment of
   // this caveat.
+  //
   // Caveat and Discharge are of type ThirdPartyCaveat and ThirdPartyDischarge
   // respectively. (not enforced here because vdl does not know these types)
   // TODO(ataly,ashankar): Figure out a VDL representation for ThirdPartyCaveat
   // and Discharge and use those here?
-  Discharge(Caveat any) (Discharge any, err error) {security.ReadLabel}
+  Discharge(Caveat any, Impetus security.DischargeImpetus) (Discharge any, err error) {security.ReadLabel}
 }
diff --git a/services/security/discharger.vdl.go b/services/security/discharger.vdl.go
index 9d0adaf..7782caf 100644
--- a/services/security/discharger.vdl.go
+++ b/services/security/discharger.vdl.go
@@ -19,7 +19,7 @@
 // It corrects a bug where _gen_wiretype is unused in VDL pacakges where only bootstrap types are used on interfaces.
 const _ = _gen_wiretype.TypeIDInvalid
 
-// DischargeIssuer service issues caveat discharges when requested.
+// Discharger is the interface for obtaining discharges for ThirdPartyCaveats.
 // Discharger is the interface the client binds and uses.
 // Discharger_ExcludingUniversal is the interface without internal framework-added methods
 // to enable embedding without method collisions.  Not to be used directly by clients.
@@ -27,11 +27,12 @@
 	// Discharge is called by a principal that holds a blessing with a third
 	// party caveat and seeks to get a discharge that proves the fulfillment of
 	// this caveat.
+	//
 	// Caveat and Discharge are of type ThirdPartyCaveat and ThirdPartyDischarge
 	// respectively. (not enforced here because vdl does not know these types)
 	// TODO(ataly,ashankar): Figure out a VDL representation for ThirdPartyCaveat
 	// and Discharge and use those here?
-	Discharge(ctx _gen_context.T, Caveat _gen_vdlutil.Any, opts ..._gen_ipc.CallOpt) (reply _gen_vdlutil.Any, err error)
+	Discharge(ctx _gen_context.T, Caveat _gen_vdlutil.Any, Impetus security.DischargeImpetus, opts ..._gen_ipc.CallOpt) (reply _gen_vdlutil.Any, err error)
 }
 type Discharger interface {
 	_gen_ipc.UniversalServiceMethods
@@ -44,11 +45,12 @@
 	// Discharge is called by a principal that holds a blessing with a third
 	// party caveat and seeks to get a discharge that proves the fulfillment of
 	// this caveat.
+	//
 	// Caveat and Discharge are of type ThirdPartyCaveat and ThirdPartyDischarge
 	// respectively. (not enforced here because vdl does not know these types)
 	// TODO(ataly,ashankar): Figure out a VDL representation for ThirdPartyCaveat
 	// and Discharge and use those here?
-	Discharge(context _gen_ipc.ServerContext, Caveat _gen_vdlutil.Any) (reply _gen_vdlutil.Any, err error)
+	Discharge(context _gen_ipc.ServerContext, Caveat _gen_vdlutil.Any, Impetus security.DischargeImpetus) (reply _gen_vdlutil.Any, err error)
 }
 
 // BindDischarger returns the client stub implementing the Discharger
@@ -92,9 +94,9 @@
 	name   string
 }
 
-func (__gen_c *clientStubDischarger) Discharge(ctx _gen_context.T, Caveat _gen_vdlutil.Any, opts ..._gen_ipc.CallOpt) (reply _gen_vdlutil.Any, err error) {
+func (__gen_c *clientStubDischarger) Discharge(ctx _gen_context.T, Caveat _gen_vdlutil.Any, Impetus security.DischargeImpetus, opts ..._gen_ipc.CallOpt) (reply _gen_vdlutil.Any, err error) {
 	var call _gen_ipc.Call
-	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "Discharge", []interface{}{Caveat}, opts...); err != nil {
+	if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "Discharge", []interface{}{Caveat, Impetus}, opts...); err != nil {
 		return
 	}
 	if ierr := call.Finish(&reply, &err); ierr != nil {
@@ -160,15 +162,23 @@
 	result.Methods["Discharge"] = _gen_ipc.MethodSignature{
 		InArgs: []_gen_ipc.MethodArgument{
 			{Name: "Caveat", Type: 65},
+			{Name: "Impetus", Type: 67},
 		},
 		OutArgs: []_gen_ipc.MethodArgument{
 			{Name: "Discharge", Type: 65},
-			{Name: "err", Type: 66},
+			{Name: "err", Type: 68},
 		},
 	}
 
 	result.TypeDefs = []_gen_vdlutil.Any{
-		_gen_wiretype.NamedPrimitiveType{Type: 0x1, Name: "anydata", Tags: []string(nil)}, _gen_wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
+		_gen_wiretype.NamedPrimitiveType{Type: 0x1, Name: "anydata", Tags: []string(nil)}, _gen_wiretype.SliceType{Elem: 0x41, Name: "", Tags: []string(nil)}, _gen_wiretype.StructType{
+			[]_gen_wiretype.FieldType{
+				_gen_wiretype.FieldType{Type: 0x41, Name: "Server"},
+				_gen_wiretype.FieldType{Type: 0x3, Name: "Method"},
+				_gen_wiretype.FieldType{Type: 0x42, Name: "Arguments"},
+			},
+			"veyron2/security.DischargeImpetus", []string(nil)},
+		_gen_wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
 
 	return result, nil
 }
@@ -191,7 +201,7 @@
 	return
 }
 
-func (__gen_s *ServerStubDischarger) Discharge(call _gen_ipc.ServerCall, Caveat _gen_vdlutil.Any) (reply _gen_vdlutil.Any, err error) {
-	reply, err = __gen_s.service.Discharge(call, Caveat)
+func (__gen_s *ServerStubDischarger) Discharge(call _gen_ipc.ServerCall, Caveat _gen_vdlutil.Any, Impetus security.DischargeImpetus) (reply _gen_vdlutil.Any, err error) {
+	reply, err = __gen_s.service.Discharge(call, Caveat, Impetus)
 	return
 }
diff --git a/services/security/discharger/discharger.go b/services/security/discharger/discharger.go
index 47aaf6f..d9a0c5b 100644
--- a/services/security/discharger/discharger.go
+++ b/services/security/discharger/discharger.go
@@ -3,7 +3,8 @@
 import (
 	"fmt"
 	"time"
-	ssecurity "veyron/services/security"
+
+	services "veyron/services/security"
 	"veyron2/ipc"
 	"veyron2/security"
 	"veyron2/vdl/vdlutil"
@@ -17,7 +18,7 @@
 
 // TODO(andreser,ataly): make it easier for third party public key caveats to specify the caveats on their discharges
 
-func (d dischargerd) Discharge(ctx ipc.ServerContext, caveatAny vdlutil.Any) (vdlutil.Any, error) {
+func (d dischargerd) Discharge(ctx ipc.ServerContext, caveatAny vdlutil.Any, _ security.DischargeImpetus) (vdlutil.Any, error) {
 	caveat, ok := caveatAny.(security.ThirdPartyCaveat)
 	if !ok {
 		return nil, fmt.Errorf("type %T does not implement security.ThirdPartyCaveat", caveatAny)
@@ -26,6 +27,6 @@
 }
 
 // NewDischarger returns a discharger service implementation that grants discharges using id.MintDischarge.
-func NewDischarger(id security.PrivateID) ssecurity.DischargerService {
+func NewDischarger(id security.PrivateID) services.DischargerService {
 	return dischargerd{id}
 }
diff --git a/services/security/discharger/revoker.go b/services/security/discharger/revoker.go
index 7f325ed..524e688 100644
--- a/services/security/discharger/revoker.go
+++ b/services/security/discharger/revoker.go
@@ -70,7 +70,7 @@
 		return revocation, nil, err
 	}
 	restriction := revocationCaveat(sha256.Sum256(revocation[:]))
-	cav, err := caveat.NewPublicKeyCaveat(restriction, dischargerID, dischargerLocation)
+	cav, err := caveat.NewPublicKeyCaveat(restriction, dischargerID, dischargerLocation, security.ThirdPartyRequirements{})
 	return revocation, cav, err
 }
 
diff --git a/services/security/discharger/revoker_test.go b/services/security/discharger/revoker_test.go
index fe0f938..035f56d 100644
--- a/services/security/discharger/revoker_test.go
+++ b/services/security/discharger/revoker_test.go
@@ -4,7 +4,7 @@
 	"os"
 	"path/filepath"
 	"testing"
-	ssecurity "veyron/services/security"
+	services "veyron/services/security"
 	"veyron2"
 	"veyron2/ipc"
 	"veyron2/naming"
@@ -28,7 +28,7 @@
 	if err != nil {
 		t.Fatalf("NewRevoker failed: $v", err)
 	}
-	revokerServiceStub := ssecurity.NewServerRevoker(revokerService)
+	revokerServiceStub := services.NewServerRevoker(revokerService)
 	err = revokerServer.Serve("", ipc.LeafDispatcher(revokerServiceStub, nil))
 	if err != nil {
 		t.Fatalf("revokerServer.Serve discharger: %s", err)
@@ -42,7 +42,7 @@
 	if err != nil {
 		t.Fatalf("revokerServer.Listen failed: %v", err)
 	}
-	dischargerServiceStub := ssecurity.NewServerDischarger(NewDischarger(r.Identity()))
+	dischargerServiceStub := services.NewServerDischarger(NewDischarger(r.Identity()))
 	if err := dischargerServer.Serve("", ipc.LeafDispatcher(dischargerServiceStub, nil)); err != nil {
 		t.Fatalf("revokerServer.Serve revoker: %s", err)
 	}
@@ -60,11 +60,11 @@
 func TestDischargeRevokeDischargeRevokeDischarge(t *testing.T) {
 	dcID, dc, rv, closeFunc, r := revokerSetup(t)
 	defer closeFunc()
-	revoker, err := ssecurity.BindRevoker(rv)
+	revoker, err := services.BindRevoker(rv)
 	if err != nil {
 		t.Fatalf("error binding to server: ", err)
 	}
-	discharger, err := ssecurity.BindDischarger(dc)
+	discharger, err := services.BindDischarger(dc)
 	if err != nil {
 		t.Fatalf("error binding to server: ", err)
 	}
@@ -73,19 +73,22 @@
 	if err != nil {
 		t.Fatalf("failed to create public key caveat: %s", err)
 	}
-	if _, err = discharger.Discharge(r.NewContext(), cav); err != nil {
+
+	var impetus security.DischargeImpetus
+
+	if _, err = discharger.Discharge(r.NewContext(), cav, impetus); err != nil {
 		t.Fatalf("failed to get discharge: %s", err)
 	}
 	if err = revoker.Revoke(r.NewContext(), preimage); err != nil {
 		t.Fatalf("failed to revoke: %s", err)
 	}
-	if discharge, err := discharger.Discharge(r.NewContext(), cav); err == nil || discharge != nil {
+	if discharge, err := discharger.Discharge(r.NewContext(), cav, impetus); err == nil || discharge != nil {
 		t.Fatalf("got a discharge for a revoked caveat: %s", err)
 	}
 	if err = revoker.Revoke(r.NewContext(), preimage); err != nil {
 		t.Fatalf("failed to revoke again: %s", err)
 	}
-	if discharge, err := discharger.Discharge(r.NewContext(), cav); err == nil || discharge != nil {
+	if discharge, err := discharger.Discharge(r.NewContext(), cav, impetus); err == nil || discharge != nil {
 		t.Fatalf("got a discharge for a doubly revoked caveat: %s", err)
 	}
 }