Make the expected blessings a slice rather than a string

This is from a comment in a previous CL, that allowing the
app to specify a set of acceptable blessings will make the
system more flexible.

MultiPart: 1/4
Change-Id: I118a0c4ba47b2fb856bed33f880002df4986c314
diff --git a/services/syncbase/.api b/services/syncbase/.api
index 4429f21..d05ca3b 100644
--- a/services/syncbase/.api
+++ b/services/syncbase/.api
@@ -621,7 +621,7 @@
 pkg syncbase, type DatabaseClientMethods interface, GetSchemaMetadata(*context.T, ...rpc.CallOpt) (SchemaMetadata, error)
 pkg syncbase, type DatabaseClientMethods interface, GetSyncgroupMembers(*context.T, Id, ...rpc.CallOpt) (map[string]SyncgroupMemberInfo, error)
 pkg syncbase, type DatabaseClientMethods interface, GetSyncgroupSpec(*context.T, Id, ...rpc.CallOpt) (SyncgroupSpec, string, error)
-pkg syncbase, type DatabaseClientMethods interface, JoinSyncgroup(*context.T, string, string, Id, SyncgroupMemberInfo, ...rpc.CallOpt) (SyncgroupSpec, error)
+pkg syncbase, type DatabaseClientMethods interface, JoinSyncgroup(*context.T, string, []string, Id, SyncgroupMemberInfo, ...rpc.CallOpt) (SyncgroupSpec, error)
 pkg syncbase, type DatabaseClientMethods interface, KeepBlob(*context.T, BlobRef, uint64, ...rpc.CallOpt) error
 pkg syncbase, type DatabaseClientMethods interface, LeaveSyncgroup(*context.T, Id, ...rpc.CallOpt) error
 pkg syncbase, type DatabaseClientMethods interface, ListCollections(*context.T, BatchHandle, ...rpc.CallOpt) ([]Id, error)
@@ -655,7 +655,7 @@
 pkg syncbase, type DatabaseClientStub interface, GetSchemaMetadata(*context.T, ...rpc.CallOpt) (SchemaMetadata, error)
 pkg syncbase, type DatabaseClientStub interface, GetSyncgroupMembers(*context.T, Id, ...rpc.CallOpt) (map[string]SyncgroupMemberInfo, error)
 pkg syncbase, type DatabaseClientStub interface, GetSyncgroupSpec(*context.T, Id, ...rpc.CallOpt) (SyncgroupSpec, string, error)
-pkg syncbase, type DatabaseClientStub interface, JoinSyncgroup(*context.T, string, string, Id, SyncgroupMemberInfo, ...rpc.CallOpt) (SyncgroupSpec, error)
+pkg syncbase, type DatabaseClientStub interface, JoinSyncgroup(*context.T, string, []string, Id, SyncgroupMemberInfo, ...rpc.CallOpt) (SyncgroupSpec, error)
 pkg syncbase, type DatabaseClientStub interface, KeepBlob(*context.T, BlobRef, uint64, ...rpc.CallOpt) error
 pkg syncbase, type DatabaseClientStub interface, LeaveSyncgroup(*context.T, Id, ...rpc.CallOpt) error
 pkg syncbase, type DatabaseClientStub interface, ListCollections(*context.T, BatchHandle, ...rpc.CallOpt) ([]Id, error)
@@ -700,7 +700,7 @@
 pkg syncbase, type DatabaseServerMethods interface, GetSchemaMetadata(*context.T, rpc.ServerCall) (SchemaMetadata, error)
 pkg syncbase, type DatabaseServerMethods interface, GetSyncgroupMembers(*context.T, rpc.ServerCall, Id) (map[string]SyncgroupMemberInfo, error)
 pkg syncbase, type DatabaseServerMethods interface, GetSyncgroupSpec(*context.T, rpc.ServerCall, Id) (SyncgroupSpec, string, error)
-pkg syncbase, type DatabaseServerMethods interface, JoinSyncgroup(*context.T, rpc.ServerCall, string, string, Id, SyncgroupMemberInfo) (SyncgroupSpec, error)
+pkg syncbase, type DatabaseServerMethods interface, JoinSyncgroup(*context.T, rpc.ServerCall, string, []string, Id, SyncgroupMemberInfo) (SyncgroupSpec, error)
 pkg syncbase, type DatabaseServerMethods interface, KeepBlob(*context.T, rpc.ServerCall, BlobRef, uint64) error
 pkg syncbase, type DatabaseServerMethods interface, LeaveSyncgroup(*context.T, rpc.ServerCall, Id) error
 pkg syncbase, type DatabaseServerMethods interface, ListCollections(*context.T, rpc.ServerCall, BatchHandle) ([]Id, error)
@@ -911,7 +911,7 @@
 pkg syncbase, type SyncgroupManagerClientMethods interface, EjectFromSyncgroup(*context.T, Id, string, ...rpc.CallOpt) error
 pkg syncbase, type SyncgroupManagerClientMethods interface, GetSyncgroupMembers(*context.T, Id, ...rpc.CallOpt) (map[string]SyncgroupMemberInfo, error)
 pkg syncbase, type SyncgroupManagerClientMethods interface, GetSyncgroupSpec(*context.T, Id, ...rpc.CallOpt) (SyncgroupSpec, string, error)
-pkg syncbase, type SyncgroupManagerClientMethods interface, JoinSyncgroup(*context.T, string, string, Id, SyncgroupMemberInfo, ...rpc.CallOpt) (SyncgroupSpec, error)
+pkg syncbase, type SyncgroupManagerClientMethods interface, JoinSyncgroup(*context.T, string, []string, Id, SyncgroupMemberInfo, ...rpc.CallOpt) (SyncgroupSpec, error)
 pkg syncbase, type SyncgroupManagerClientMethods interface, LeaveSyncgroup(*context.T, Id, ...rpc.CallOpt) error
 pkg syncbase, type SyncgroupManagerClientMethods interface, ListSyncgroups(*context.T, ...rpc.CallOpt) ([]Id, error)
 pkg syncbase, type SyncgroupManagerClientMethods interface, SetSyncgroupSpec(*context.T, Id, SyncgroupSpec, string, ...rpc.CallOpt) error
@@ -920,7 +920,7 @@
 pkg syncbase, type SyncgroupManagerClientStub interface, EjectFromSyncgroup(*context.T, Id, string, ...rpc.CallOpt) error
 pkg syncbase, type SyncgroupManagerClientStub interface, GetSyncgroupMembers(*context.T, Id, ...rpc.CallOpt) (map[string]SyncgroupMemberInfo, error)
 pkg syncbase, type SyncgroupManagerClientStub interface, GetSyncgroupSpec(*context.T, Id, ...rpc.CallOpt) (SyncgroupSpec, string, error)
-pkg syncbase, type SyncgroupManagerClientStub interface, JoinSyncgroup(*context.T, string, string, Id, SyncgroupMemberInfo, ...rpc.CallOpt) (SyncgroupSpec, error)
+pkg syncbase, type SyncgroupManagerClientStub interface, JoinSyncgroup(*context.T, string, []string, Id, SyncgroupMemberInfo, ...rpc.CallOpt) (SyncgroupSpec, error)
 pkg syncbase, type SyncgroupManagerClientStub interface, LeaveSyncgroup(*context.T, Id, ...rpc.CallOpt) error
 pkg syncbase, type SyncgroupManagerClientStub interface, ListSyncgroups(*context.T, ...rpc.CallOpt) ([]Id, error)
 pkg syncbase, type SyncgroupManagerClientStub interface, SetSyncgroupSpec(*context.T, Id, SyncgroupSpec, string, ...rpc.CallOpt) error
@@ -931,7 +931,7 @@
 pkg syncbase, type SyncgroupManagerServerMethods interface, EjectFromSyncgroup(*context.T, rpc.ServerCall, Id, string) error
 pkg syncbase, type SyncgroupManagerServerMethods interface, GetSyncgroupMembers(*context.T, rpc.ServerCall, Id) (map[string]SyncgroupMemberInfo, error)
 pkg syncbase, type SyncgroupManagerServerMethods interface, GetSyncgroupSpec(*context.T, rpc.ServerCall, Id) (SyncgroupSpec, string, error)
-pkg syncbase, type SyncgroupManagerServerMethods interface, JoinSyncgroup(*context.T, rpc.ServerCall, string, string, Id, SyncgroupMemberInfo) (SyncgroupSpec, error)
+pkg syncbase, type SyncgroupManagerServerMethods interface, JoinSyncgroup(*context.T, rpc.ServerCall, string, []string, Id, SyncgroupMemberInfo) (SyncgroupSpec, error)
 pkg syncbase, type SyncgroupManagerServerMethods interface, LeaveSyncgroup(*context.T, rpc.ServerCall, Id) error
 pkg syncbase, type SyncgroupManagerServerMethods interface, ListSyncgroups(*context.T, rpc.ServerCall) ([]Id, error)
 pkg syncbase, type SyncgroupManagerServerMethods interface, SetSyncgroupSpec(*context.T, rpc.ServerCall, Id, SyncgroupSpec, string) error
diff --git a/services/syncbase/service.vdl b/services/syncbase/service.vdl
index 4907728..de40df8 100644
--- a/services/syncbase/service.vdl
+++ b/services/syncbase/service.vdl
@@ -201,7 +201,7 @@
 	//
 	// Requires: Client must have at least Read access on the Database and on the
 	// syncgroup ACL.
-	JoinSyncgroup(remoteSyncbaseName string, expectedSyncbaseBlessing string, sgId Id, myInfo SyncgroupMemberInfo) (spec SyncgroupSpec | error) {access.Read}
+	JoinSyncgroup(remoteSyncbaseName string, expectedSyncbaseBlessings []string, sgId Id, myInfo SyncgroupMemberInfo) (spec SyncgroupSpec | error) {access.Read}
 
 	// LeaveSyncgroup leaves the syncgroup. Previously synced data will continue
 	// to be available.
diff --git a/services/syncbase/syncbase.vdl.go b/services/syncbase/syncbase.vdl.go
index c3ec1bf..0ef2e7f 100644
--- a/services/syncbase/syncbase.vdl.go
+++ b/services/syncbase/syncbase.vdl.go
@@ -6870,7 +6870,7 @@
 	//
 	// Requires: Client must have at least Read access on the Database and on the
 	// syncgroup ACL.
-	JoinSyncgroup(_ *context.T, remoteSyncbaseName string, expectedSyncbaseBlessing string, sgId Id, myInfo SyncgroupMemberInfo, _ ...rpc.CallOpt) (spec SyncgroupSpec, _ error)
+	JoinSyncgroup(_ *context.T, remoteSyncbaseName string, expectedSyncbaseBlessings []string, sgId Id, myInfo SyncgroupMemberInfo, _ ...rpc.CallOpt) (spec SyncgroupSpec, _ error)
 	// LeaveSyncgroup leaves the syncgroup. Previously synced data will continue
 	// to be available.
 	//
@@ -6934,7 +6934,7 @@
 	return
 }
 
-func (c implSyncgroupManagerClientStub) JoinSyncgroup(ctx *context.T, i0 string, i1 string, i2 Id, i3 SyncgroupMemberInfo, opts ...rpc.CallOpt) (o0 SyncgroupSpec, err error) {
+func (c implSyncgroupManagerClientStub) JoinSyncgroup(ctx *context.T, i0 string, i1 []string, i2 Id, i3 SyncgroupMemberInfo, opts ...rpc.CallOpt) (o0 SyncgroupSpec, err error) {
 	err = v23.GetClient(ctx).Call(ctx, c.name, "JoinSyncgroup", []interface{}{i0, i1, i2, i3}, []interface{}{&o0}, opts...)
 	return
 }
@@ -6988,7 +6988,7 @@
 	//
 	// Requires: Client must have at least Read access on the Database and on the
 	// syncgroup ACL.
-	JoinSyncgroup(_ *context.T, _ rpc.ServerCall, remoteSyncbaseName string, expectedSyncbaseBlessing string, sgId Id, myInfo SyncgroupMemberInfo) (spec SyncgroupSpec, _ error)
+	JoinSyncgroup(_ *context.T, _ rpc.ServerCall, remoteSyncbaseName string, expectedSyncbaseBlessings []string, sgId Id, myInfo SyncgroupMemberInfo) (spec SyncgroupSpec, _ error)
 	// LeaveSyncgroup leaves the syncgroup. Previously synced data will continue
 	// to be available.
 	//
@@ -7070,7 +7070,7 @@
 	return s.impl.CreateSyncgroup(ctx, call, i0, i1, i2)
 }
 
-func (s implSyncgroupManagerServerStub) JoinSyncgroup(ctx *context.T, call rpc.ServerCall, i0 string, i1 string, i2 Id, i3 SyncgroupMemberInfo) (SyncgroupSpec, error) {
+func (s implSyncgroupManagerServerStub) JoinSyncgroup(ctx *context.T, call rpc.ServerCall, i0 string, i1 []string, i2 Id, i3 SyncgroupMemberInfo) (SyncgroupSpec, error) {
 	return s.impl.JoinSyncgroup(ctx, call, i0, i1, i2, i3)
 }
 
@@ -7137,10 +7137,10 @@
 			Name: "JoinSyncgroup",
 			Doc:  "// JoinSyncgroup joins the syncgroup.\n//\n// Requires: Client must have at least Read access on the Database and on the\n// syncgroup ACL.",
 			InArgs: []rpc.ArgDesc{
-				{"remoteSyncbaseName", ``},       // string
-				{"expectedSyncbaseBlessing", ``}, // string
-				{"sgId", ``},                     // Id
-				{"myInfo", ``},                   // SyncgroupMemberInfo
+				{"remoteSyncbaseName", ``},        // string
+				{"expectedSyncbaseBlessings", ``}, // []string
+				{"sgId", ``},                      // Id
+				{"myInfo", ``},                    // SyncgroupMemberInfo
 			},
 			OutArgs: []rpc.ArgDesc{
 				{"spec", ``}, // SyncgroupSpec
diff --git a/syncbase/.api b/syncbase/.api
index 91c3597..a39c4cd 100644
--- a/syncbase/.api
+++ b/syncbase/.api
@@ -258,7 +258,7 @@
 pkg syncbase, type Syncgroup interface, GetMembers(*context.T) (map[string]wire.SyncgroupMemberInfo, error)
 pkg syncbase, type Syncgroup interface, GetSpec(*context.T) (wire.SyncgroupSpec, string, error)
 pkg syncbase, type Syncgroup interface, Id() wire.Id
-pkg syncbase, type Syncgroup interface, Join(*context.T, string, string, wire.SyncgroupMemberInfo) (wire.SyncgroupSpec, error)
+pkg syncbase, type Syncgroup interface, Join(*context.T, string, []string, wire.SyncgroupMemberInfo) (wire.SyncgroupSpec, error)
 pkg syncbase, type Syncgroup interface, Leave(*context.T) error
 pkg syncbase, type Syncgroup interface, SetSpec(*context.T, wire.SyncgroupSpec, string) error
 pkg syncbase, type Value struct
diff --git a/syncbase/featuretests/test_util_test.go b/syncbase/featuretests/test_util_test.go
index c5576db..b1148b0 100644
--- a/syncbase/featuretests/test_util_test.go
+++ b/syncbase/featuretests/test_util_test.go
@@ -257,7 +257,7 @@
 	d := syncbase.NewService(sbNameLocal).DatabaseForId(testDb, nil)
 	sg := d.SyncgroupForId(sgId)
 	info := wire.SyncgroupMemberInfo{SyncPriority: 10}
-	if _, err := sg.Join(ctx, sbNameRemote, "", info); err != nil {
+	if _, err := sg.Join(ctx, sbNameRemote, nil, info); err != nil {
 		return fmt.Errorf("{%q, %q} sg.Join() failed: %v", sbNameRemote, sgId, err)
 	}
 	return nil
diff --git a/syncbase/model.go b/syncbase/model.go
index b8c0724..86e7b79 100644
--- a/syncbase/model.go
+++ b/syncbase/model.go
@@ -451,7 +451,7 @@
 	//
 	// Requires: Client must have at least Read access on the Database and on the
 	// syncgroup ACL.
-	Join(ctx *context.T, syncbaseName string, expectedSyncbaseBlessings string, myInfo wire.SyncgroupMemberInfo) (wire.SyncgroupSpec, error)
+	Join(ctx *context.T, syncbaseName string, expectedSyncbaseBlessings []string, myInfo wire.SyncgroupMemberInfo) (wire.SyncgroupSpec, error)
 
 	// Leave leaves the syncgroup. Previously synced data will continue
 	// to be available.
diff --git a/syncbase/syncgroup.go b/syncbase/syncgroup.go
index 6cb7285..0d1dcaf 100644
--- a/syncbase/syncgroup.go
+++ b/syncbase/syncgroup.go
@@ -31,8 +31,8 @@
 }
 
 // Join implements Syncgroup.Join.
-func (sg *syncgroup) Join(ctx *context.T, remoteSyncbaseName, expectedSyncbaseBlessing string, myInfo wire.SyncgroupMemberInfo) (wire.SyncgroupSpec, error) {
-	return sg.c.JoinSyncgroup(ctx, remoteSyncbaseName, expectedSyncbaseBlessing, sg.id, myInfo)
+func (sg *syncgroup) Join(ctx *context.T, remoteSyncbaseName string, expectedSyncbaseBlessings []string, myInfo wire.SyncgroupMemberInfo) (wire.SyncgroupSpec, error) {
+	return sg.c.JoinSyncgroup(ctx, remoteSyncbaseName, expectedSyncbaseBlessings, sg.id, myInfo)
 }
 
 // Leave implements Syncgroup.Leave.
diff --git a/syncbase/syncgroup_test.go b/syncbase/syncgroup_test.go
index b591b4f..b71c378 100644
--- a/syncbase/syncgroup_test.go
+++ b/syncbase/syncgroup_test.go
@@ -198,7 +198,7 @@
 func joinSyncgroup(t *testing.T, ctx *context.T, d syncbase.Database, sbName string, sgId wire.Id, wantErr verror.ID) syncbase.Syncgroup {
 	sg := d.SyncgroupForId(sgId)
 	info := wire.SyncgroupMemberInfo{SyncPriority: 10}
-	if _, err := sg.Join(ctx, sbName, "", info); verror.ErrorID(err) != wantErr {
+	if _, err := sg.Join(ctx, sbName, nil, info); verror.ErrorID(err) != wantErr {
 		tu.Fatalf(t, "Join SG %v failed: %v", sgId, err)
 	}
 	return sg
diff --git a/syncbase/syncgroup_v23_test.go b/syncbase/syncgroup_v23_test.go
index 7554077..72cac81 100644
--- a/syncbase/syncgroup_v23_test.go
+++ b/syncbase/syncgroup_v23_test.go
@@ -608,7 +608,7 @@
 	d := dbHandle(sbNameLocal)
 	sg := d.SyncgroupForId(wire.Id{Name: sgName, Blessing: "blessing"})
 	info := wire.SyncgroupMemberInfo{SyncPriority: 10}
-	if _, err := sg.Join(ctx, sbNameRemote, "", info); err != nil {
+	if _, err := sg.Join(ctx, sbNameRemote, nil, info); err != nil {
 		return fmt.Errorf("Join SG %q, %q failed: %v\n", sbNameRemote, sgName, err)
 	}
 	return nil
@@ -1158,7 +1158,7 @@
 			sgName := fmt.Sprintf("%s_%s", appName, dbName)
 			sg := d.SyncgroupForId(wire.Id{Name: sgName, Blessing: "blessing"})
 			info := wire.SyncgroupMemberInfo{SyncPriority: 10}
-			if _, err := sg.Join(ctx, sbNameRemote, "", info); err != nil {
+			if _, err := sg.Join(ctx, sbNameRemote, nil, info); err != nil {
 				return fmt.Errorf("Join SG Multi %q failed: %v\n", sgName, err)
 			}
 		}