diff --git a/frontend/src/api_proto/common_pb.js b/frontend/src/api_proto/common_pb.js
new file mode 100644
index 0000000..6bc5cd4
--- /dev/null
+++ b/frontend/src/api_proto/common_pb.js
@@ -0,0 +1,250 @@
+// source: api_proto/common.proto
+/**
+ * @fileoverview
+ * @enhanceable
+ * @suppress {missingRequire} reports error on implicit type usages.
+ * @suppress {messageConventions} JS Compiler reports an error if a variable or
+ *     field starts with 'MSG_' and isn't a translatable message.
+ * @public
+ */
+// GENERATED CODE -- DO NOT EDIT!
+/* eslint-disable */
+// @ts-nocheck
+
+var jspb = require('google-protobuf');
+var goog = jspb;
+var global = Function('return this')();
+
+goog.exportSymbol('proto.Environment', null, global);
+goog.exportSymbol('proto.Environment.Browser', null, global);
+goog.exportSymbol('proto.Environment.VersionChannel', null, global);
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.Environment = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.Environment, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.Environment.displayName = 'proto.Environment';
+}
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.Environment.prototype.toObject = function(opt_includeInstance) {
+  return proto.Environment.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.Environment} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.Environment.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    browser: jspb.Message.getFieldWithDefault(msg, 1, 0),
+    version: jspb.Message.getFieldWithDefault(msg, 2, ""),
+    versionChannel: jspb.Message.getFieldWithDefault(msg, 3, 0)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.Environment}
+ */
+proto.Environment.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.Environment;
+  return proto.Environment.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.Environment} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.Environment}
+ */
+proto.Environment.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {!proto.Environment.Browser} */ (reader.readEnum());
+      msg.setBrowser(value);
+      break;
+    case 2:
+      var value = /** @type {string} */ (reader.readString());
+      msg.setVersion(value);
+      break;
+    case 3:
+      var value = /** @type {!proto.Environment.VersionChannel} */ (reader.readEnum());
+      msg.setVersionChannel(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.Environment.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.Environment.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.Environment} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.Environment.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getBrowser();
+  if (f !== 0.0) {
+    writer.writeEnum(
+      1,
+      f
+    );
+  }
+  f = message.getVersion();
+  if (f.length > 0) {
+    writer.writeString(
+      2,
+      f
+    );
+  }
+  f = message.getVersionChannel();
+  if (f !== 0.0) {
+    writer.writeEnum(
+      3,
+      f
+    );
+  }
+};
+
+
+/**
+ * @enum {number}
+ */
+proto.Environment.Browser = {
+  BROWSER_UNKNOWN: 0,
+  BROWSER_CHROMIUM: 1,
+  BROWSER_GECKO: 2
+};
+
+/**
+ * @enum {number}
+ */
+proto.Environment.VersionChannel = {
+  CHANNEL_UNKNOWN: 0,
+  CHANNEL_STABLE: 1,
+  CHANNEL_BETA: 2
+};
+
+/**
+ * optional Browser browser = 1;
+ * @return {!proto.Environment.Browser}
+ */
+proto.Environment.prototype.getBrowser = function() {
+  return /** @type {!proto.Environment.Browser} */ (jspb.Message.getFieldWithDefault(this, 1, 0));
+};
+
+
+/**
+ * @param {!proto.Environment.Browser} value
+ * @return {!proto.Environment} returns this
+ */
+proto.Environment.prototype.setBrowser = function(value) {
+  return jspb.Message.setProto3EnumField(this, 1, value);
+};
+
+
+/**
+ * optional string version = 2;
+ * @return {string}
+ */
+proto.Environment.prototype.getVersion = function() {
+  return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, ""));
+};
+
+
+/**
+ * @param {string} value
+ * @return {!proto.Environment} returns this
+ */
+proto.Environment.prototype.setVersion = function(value) {
+  return jspb.Message.setProto3StringField(this, 2, value);
+};
+
+
+/**
+ * optional VersionChannel version_channel = 3;
+ * @return {!proto.Environment.VersionChannel}
+ */
+proto.Environment.prototype.getVersionChannel = function() {
+  return /** @type {!proto.Environment.VersionChannel} */ (jspb.Message.getFieldWithDefault(this, 3, 0));
+};
+
+
+/**
+ * @param {!proto.Environment.VersionChannel} value
+ * @return {!proto.Environment} returns this
+ */
+proto.Environment.prototype.setVersionChannel = function(value) {
+  return jspb.Message.setProto3EnumField(this, 3, value);
+};
+
+
+goog.object.extend(exports, proto);
diff --git a/frontend/src/api_proto/kill_switch_grpc_web_pb.js b/frontend/src/api_proto/kill_switch_grpc_web_pb.js
new file mode 100644
index 0000000..0c5f28a
--- /dev/null
+++ b/frontend/src/api_proto/kill_switch_grpc_web_pb.js
@@ -0,0 +1,877 @@
+/**
+ * @fileoverview gRPC-Web generated client stub for 
+ * @enhanceable
+ * @public
+ */
+
+// GENERATED CODE -- DO NOT EDIT!
+
+
+/* eslint-disable */
+// @ts-nocheck
+
+
+
+const grpc = {};
+grpc.web = require('grpc-web');
+
+
+var api_proto_common_pb = require('../api_proto/common_pb.js')
+
+var api_proto_kill_switch_objects_pb = require('../api_proto/kill_switch_objects_pb.js')
+const proto = require('./kill_switch_pb.js');
+
+/**
+ * @param {string} hostname
+ * @param {?Object} credentials
+ * @param {?Object} options
+ * @constructor
+ * @struct
+ * @final
+ */
+proto.KillSwitchServiceClient =
+    function(hostname, credentials, options) {
+  if (!options) options = {};
+  options['format'] = 'text';
+
+  /**
+   * @private @const {!grpc.web.GrpcWebClientBase} The client
+   */
+  this.client_ = new grpc.web.GrpcWebClientBase(options);
+
+  /**
+   * @private @const {string} The hostname
+   */
+  this.hostname_ = hostname;
+
+};
+
+
+/**
+ * @param {string} hostname
+ * @param {?Object} credentials
+ * @param {?Object} options
+ * @constructor
+ * @struct
+ * @final
+ */
+proto.KillSwitchServicePromiseClient =
+    function(hostname, credentials, options) {
+  if (!options) options = {};
+  options['format'] = 'text';
+
+  /**
+   * @private @const {!grpc.web.GrpcWebClientBase} The client
+   */
+  this.client_ = new grpc.web.GrpcWebClientBase(options);
+
+  /**
+   * @private @const {string} The hostname
+   */
+  this.hostname_ = hostname;
+
+};
+
+
+/**
+ * @const
+ * @type {!grpc.web.MethodDescriptor<
+ *   !proto.GetKillSwitchStatusRequest,
+ *   !proto.GetKillSwitchStatusResponse>}
+ */
+const methodDescriptor_KillSwitchService_GetKillSwitchStatus = new grpc.web.MethodDescriptor(
+  '/KillSwitchService/GetKillSwitchStatus',
+  grpc.web.MethodType.UNARY,
+  proto.GetKillSwitchStatusRequest,
+  proto.GetKillSwitchStatusResponse,
+  /**
+   * @param {!proto.GetKillSwitchStatusRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.GetKillSwitchStatusResponse.deserializeBinary
+);
+
+
+/**
+ * @const
+ * @type {!grpc.web.AbstractClientBase.MethodInfo<
+ *   !proto.GetKillSwitchStatusRequest,
+ *   !proto.GetKillSwitchStatusResponse>}
+ */
+const methodInfo_KillSwitchService_GetKillSwitchStatus = new grpc.web.AbstractClientBase.MethodInfo(
+  proto.GetKillSwitchStatusResponse,
+  /**
+   * @param {!proto.GetKillSwitchStatusRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.GetKillSwitchStatusResponse.deserializeBinary
+);
+
+
+/**
+ * @param {!proto.GetKillSwitchStatusRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @param {function(?grpc.web.Error, ?proto.GetKillSwitchStatusResponse)}
+ *     callback The callback function(error, response)
+ * @return {!grpc.web.ClientReadableStream<!proto.GetKillSwitchStatusResponse>|undefined}
+ *     The XHR Node Readable Stream
+ */
+proto.KillSwitchServiceClient.prototype.getKillSwitchStatus =
+    function(request, metadata, callback) {
+  return this.client_.rpcCall(this.hostname_ +
+      '/KillSwitchService/GetKillSwitchStatus',
+      request,
+      metadata || {},
+      methodDescriptor_KillSwitchService_GetKillSwitchStatus,
+      callback);
+};
+
+
+/**
+ * @param {!proto.GetKillSwitchStatusRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @return {!Promise<!proto.GetKillSwitchStatusResponse>}
+ *     Promise that resolves to the response
+ */
+proto.KillSwitchServicePromiseClient.prototype.getKillSwitchStatus =
+    function(request, metadata) {
+  return this.client_.unaryCall(this.hostname_ +
+      '/KillSwitchService/GetKillSwitchStatus',
+      request,
+      metadata || {},
+      methodDescriptor_KillSwitchService_GetKillSwitchStatus);
+};
+
+
+/**
+ * @const
+ * @type {!grpc.web.MethodDescriptor<
+ *   !proto.GetKillSwitchOverviewRequest,
+ *   !proto.GetKillSwitchOverviewResponse>}
+ */
+const methodDescriptor_KillSwitchService_GetKillSwitchOverview = new grpc.web.MethodDescriptor(
+  '/KillSwitchService/GetKillSwitchOverview',
+  grpc.web.MethodType.UNARY,
+  proto.GetKillSwitchOverviewRequest,
+  proto.GetKillSwitchOverviewResponse,
+  /**
+   * @param {!proto.GetKillSwitchOverviewRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.GetKillSwitchOverviewResponse.deserializeBinary
+);
+
+
+/**
+ * @const
+ * @type {!grpc.web.AbstractClientBase.MethodInfo<
+ *   !proto.GetKillSwitchOverviewRequest,
+ *   !proto.GetKillSwitchOverviewResponse>}
+ */
+const methodInfo_KillSwitchService_GetKillSwitchOverview = new grpc.web.AbstractClientBase.MethodInfo(
+  proto.GetKillSwitchOverviewResponse,
+  /**
+   * @param {!proto.GetKillSwitchOverviewRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.GetKillSwitchOverviewResponse.deserializeBinary
+);
+
+
+/**
+ * @param {!proto.GetKillSwitchOverviewRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @param {function(?grpc.web.Error, ?proto.GetKillSwitchOverviewResponse)}
+ *     callback The callback function(error, response)
+ * @return {!grpc.web.ClientReadableStream<!proto.GetKillSwitchOverviewResponse>|undefined}
+ *     The XHR Node Readable Stream
+ */
+proto.KillSwitchServiceClient.prototype.getKillSwitchOverview =
+    function(request, metadata, callback) {
+  return this.client_.rpcCall(this.hostname_ +
+      '/KillSwitchService/GetKillSwitchOverview',
+      request,
+      metadata || {},
+      methodDescriptor_KillSwitchService_GetKillSwitchOverview,
+      callback);
+};
+
+
+/**
+ * @param {!proto.GetKillSwitchOverviewRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @return {!Promise<!proto.GetKillSwitchOverviewResponse>}
+ *     Promise that resolves to the response
+ */
+proto.KillSwitchServicePromiseClient.prototype.getKillSwitchOverview =
+    function(request, metadata) {
+  return this.client_.unaryCall(this.hostname_ +
+      '/KillSwitchService/GetKillSwitchOverview',
+      request,
+      metadata || {},
+      methodDescriptor_KillSwitchService_GetKillSwitchOverview);
+};
+
+
+/**
+ * @const
+ * @type {!grpc.web.MethodDescriptor<
+ *   !proto.ListFeaturesRequest,
+ *   !proto.ListFeaturesResponse>}
+ */
+const methodDescriptor_KillSwitchService_ListFeatures = new grpc.web.MethodDescriptor(
+  '/KillSwitchService/ListFeatures',
+  grpc.web.MethodType.UNARY,
+  proto.ListFeaturesRequest,
+  proto.ListFeaturesResponse,
+  /**
+   * @param {!proto.ListFeaturesRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.ListFeaturesResponse.deserializeBinary
+);
+
+
+/**
+ * @const
+ * @type {!grpc.web.AbstractClientBase.MethodInfo<
+ *   !proto.ListFeaturesRequest,
+ *   !proto.ListFeaturesResponse>}
+ */
+const methodInfo_KillSwitchService_ListFeatures = new grpc.web.AbstractClientBase.MethodInfo(
+  proto.ListFeaturesResponse,
+  /**
+   * @param {!proto.ListFeaturesRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.ListFeaturesResponse.deserializeBinary
+);
+
+
+/**
+ * @param {!proto.ListFeaturesRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @param {function(?grpc.web.Error, ?proto.ListFeaturesResponse)}
+ *     callback The callback function(error, response)
+ * @return {!grpc.web.ClientReadableStream<!proto.ListFeaturesResponse>|undefined}
+ *     The XHR Node Readable Stream
+ */
+proto.KillSwitchServiceClient.prototype.listFeatures =
+    function(request, metadata, callback) {
+  return this.client_.rpcCall(this.hostname_ +
+      '/KillSwitchService/ListFeatures',
+      request,
+      metadata || {},
+      methodDescriptor_KillSwitchService_ListFeatures,
+      callback);
+};
+
+
+/**
+ * @param {!proto.ListFeaturesRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @return {!Promise<!proto.ListFeaturesResponse>}
+ *     Promise that resolves to the response
+ */
+proto.KillSwitchServicePromiseClient.prototype.listFeatures =
+    function(request, metadata) {
+  return this.client_.unaryCall(this.hostname_ +
+      '/KillSwitchService/ListFeatures',
+      request,
+      metadata || {},
+      methodDescriptor_KillSwitchService_ListFeatures);
+};
+
+
+/**
+ * @const
+ * @type {!grpc.web.MethodDescriptor<
+ *   !proto.SyncFeaturesRequest,
+ *   !proto.SyncFeaturesResponse>}
+ */
+const methodDescriptor_KillSwitchService_SyncFeatures = new grpc.web.MethodDescriptor(
+  '/KillSwitchService/SyncFeatures',
+  grpc.web.MethodType.UNARY,
+  proto.SyncFeaturesRequest,
+  proto.SyncFeaturesResponse,
+  /**
+   * @param {!proto.SyncFeaturesRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.SyncFeaturesResponse.deserializeBinary
+);
+
+
+/**
+ * @const
+ * @type {!grpc.web.AbstractClientBase.MethodInfo<
+ *   !proto.SyncFeaturesRequest,
+ *   !proto.SyncFeaturesResponse>}
+ */
+const methodInfo_KillSwitchService_SyncFeatures = new grpc.web.AbstractClientBase.MethodInfo(
+  proto.SyncFeaturesResponse,
+  /**
+   * @param {!proto.SyncFeaturesRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.SyncFeaturesResponse.deserializeBinary
+);
+
+
+/**
+ * @param {!proto.SyncFeaturesRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @param {function(?grpc.web.Error, ?proto.SyncFeaturesResponse)}
+ *     callback The callback function(error, response)
+ * @return {!grpc.web.ClientReadableStream<!proto.SyncFeaturesResponse>|undefined}
+ *     The XHR Node Readable Stream
+ */
+proto.KillSwitchServiceClient.prototype.syncFeatures =
+    function(request, metadata, callback) {
+  return this.client_.rpcCall(this.hostname_ +
+      '/KillSwitchService/SyncFeatures',
+      request,
+      metadata || {},
+      methodDescriptor_KillSwitchService_SyncFeatures,
+      callback);
+};
+
+
+/**
+ * @param {!proto.SyncFeaturesRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @return {!Promise<!proto.SyncFeaturesResponse>}
+ *     Promise that resolves to the response
+ */
+proto.KillSwitchServicePromiseClient.prototype.syncFeatures =
+    function(request, metadata) {
+  return this.client_.unaryCall(this.hostname_ +
+      '/KillSwitchService/SyncFeatures',
+      request,
+      metadata || {},
+      methodDescriptor_KillSwitchService_SyncFeatures);
+};
+
+
+/**
+ * @const
+ * @type {!grpc.web.MethodDescriptor<
+ *   !proto.EnableKillSwitchRequest,
+ *   !proto.EnableKillSwitchResponse>}
+ */
+const methodDescriptor_KillSwitchService_EnableKillSwitch = new grpc.web.MethodDescriptor(
+  '/KillSwitchService/EnableKillSwitch',
+  grpc.web.MethodType.UNARY,
+  proto.EnableKillSwitchRequest,
+  proto.EnableKillSwitchResponse,
+  /**
+   * @param {!proto.EnableKillSwitchRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.EnableKillSwitchResponse.deserializeBinary
+);
+
+
+/**
+ * @const
+ * @type {!grpc.web.AbstractClientBase.MethodInfo<
+ *   !proto.EnableKillSwitchRequest,
+ *   !proto.EnableKillSwitchResponse>}
+ */
+const methodInfo_KillSwitchService_EnableKillSwitch = new grpc.web.AbstractClientBase.MethodInfo(
+  proto.EnableKillSwitchResponse,
+  /**
+   * @param {!proto.EnableKillSwitchRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.EnableKillSwitchResponse.deserializeBinary
+);
+
+
+/**
+ * @param {!proto.EnableKillSwitchRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @param {function(?grpc.web.Error, ?proto.EnableKillSwitchResponse)}
+ *     callback The callback function(error, response)
+ * @return {!grpc.web.ClientReadableStream<!proto.EnableKillSwitchResponse>|undefined}
+ *     The XHR Node Readable Stream
+ */
+proto.KillSwitchServiceClient.prototype.enableKillSwitch =
+    function(request, metadata, callback) {
+  return this.client_.rpcCall(this.hostname_ +
+      '/KillSwitchService/EnableKillSwitch',
+      request,
+      metadata || {},
+      methodDescriptor_KillSwitchService_EnableKillSwitch,
+      callback);
+};
+
+
+/**
+ * @param {!proto.EnableKillSwitchRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @return {!Promise<!proto.EnableKillSwitchResponse>}
+ *     Promise that resolves to the response
+ */
+proto.KillSwitchServicePromiseClient.prototype.enableKillSwitch =
+    function(request, metadata) {
+  return this.client_.unaryCall(this.hostname_ +
+      '/KillSwitchService/EnableKillSwitch',
+      request,
+      metadata || {},
+      methodDescriptor_KillSwitchService_EnableKillSwitch);
+};
+
+
+/**
+ * @const
+ * @type {!grpc.web.MethodDescriptor<
+ *   !proto.DisableKillSwitchRequest,
+ *   !proto.DisableKillSwitchResponse>}
+ */
+const methodDescriptor_KillSwitchService_DisableKillSwitch = new grpc.web.MethodDescriptor(
+  '/KillSwitchService/DisableKillSwitch',
+  grpc.web.MethodType.UNARY,
+  proto.DisableKillSwitchRequest,
+  proto.DisableKillSwitchResponse,
+  /**
+   * @param {!proto.DisableKillSwitchRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.DisableKillSwitchResponse.deserializeBinary
+);
+
+
+/**
+ * @const
+ * @type {!grpc.web.AbstractClientBase.MethodInfo<
+ *   !proto.DisableKillSwitchRequest,
+ *   !proto.DisableKillSwitchResponse>}
+ */
+const methodInfo_KillSwitchService_DisableKillSwitch = new grpc.web.AbstractClientBase.MethodInfo(
+  proto.DisableKillSwitchResponse,
+  /**
+   * @param {!proto.DisableKillSwitchRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.DisableKillSwitchResponse.deserializeBinary
+);
+
+
+/**
+ * @param {!proto.DisableKillSwitchRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @param {function(?grpc.web.Error, ?proto.DisableKillSwitchResponse)}
+ *     callback The callback function(error, response)
+ * @return {!grpc.web.ClientReadableStream<!proto.DisableKillSwitchResponse>|undefined}
+ *     The XHR Node Readable Stream
+ */
+proto.KillSwitchServiceClient.prototype.disableKillSwitch =
+    function(request, metadata, callback) {
+  return this.client_.rpcCall(this.hostname_ +
+      '/KillSwitchService/DisableKillSwitch',
+      request,
+      metadata || {},
+      methodDescriptor_KillSwitchService_DisableKillSwitch,
+      callback);
+};
+
+
+/**
+ * @param {!proto.DisableKillSwitchRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @return {!Promise<!proto.DisableKillSwitchResponse>}
+ *     Promise that resolves to the response
+ */
+proto.KillSwitchServicePromiseClient.prototype.disableKillSwitch =
+    function(request, metadata) {
+  return this.client_.unaryCall(this.hostname_ +
+      '/KillSwitchService/DisableKillSwitch',
+      request,
+      metadata || {},
+      methodDescriptor_KillSwitchService_DisableKillSwitch);
+};
+
+
+/**
+ * @const
+ * @type {!grpc.web.MethodDescriptor<
+ *   !proto.ListAuthorizedUsersRequest,
+ *   !proto.ListAuthorizedUsersResponse>}
+ */
+const methodDescriptor_KillSwitchService_ListAuthorizedUsers = new grpc.web.MethodDescriptor(
+  '/KillSwitchService/ListAuthorizedUsers',
+  grpc.web.MethodType.UNARY,
+  proto.ListAuthorizedUsersRequest,
+  proto.ListAuthorizedUsersResponse,
+  /**
+   * @param {!proto.ListAuthorizedUsersRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.ListAuthorizedUsersResponse.deserializeBinary
+);
+
+
+/**
+ * @const
+ * @type {!grpc.web.AbstractClientBase.MethodInfo<
+ *   !proto.ListAuthorizedUsersRequest,
+ *   !proto.ListAuthorizedUsersResponse>}
+ */
+const methodInfo_KillSwitchService_ListAuthorizedUsers = new grpc.web.AbstractClientBase.MethodInfo(
+  proto.ListAuthorizedUsersResponse,
+  /**
+   * @param {!proto.ListAuthorizedUsersRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.ListAuthorizedUsersResponse.deserializeBinary
+);
+
+
+/**
+ * @param {!proto.ListAuthorizedUsersRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @param {function(?grpc.web.Error, ?proto.ListAuthorizedUsersResponse)}
+ *     callback The callback function(error, response)
+ * @return {!grpc.web.ClientReadableStream<!proto.ListAuthorizedUsersResponse>|undefined}
+ *     The XHR Node Readable Stream
+ */
+proto.KillSwitchServiceClient.prototype.listAuthorizedUsers =
+    function(request, metadata, callback) {
+  return this.client_.rpcCall(this.hostname_ +
+      '/KillSwitchService/ListAuthorizedUsers',
+      request,
+      metadata || {},
+      methodDescriptor_KillSwitchService_ListAuthorizedUsers,
+      callback);
+};
+
+
+/**
+ * @param {!proto.ListAuthorizedUsersRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @return {!Promise<!proto.ListAuthorizedUsersResponse>}
+ *     Promise that resolves to the response
+ */
+proto.KillSwitchServicePromiseClient.prototype.listAuthorizedUsers =
+    function(request, metadata) {
+  return this.client_.unaryCall(this.hostname_ +
+      '/KillSwitchService/ListAuthorizedUsers',
+      request,
+      metadata || {},
+      methodDescriptor_KillSwitchService_ListAuthorizedUsers);
+};
+
+
+/**
+ * @const
+ * @type {!grpc.web.MethodDescriptor<
+ *   !proto.AddAuthorizedUserRequest,
+ *   !proto.AddAuthorizedUserResponse>}
+ */
+const methodDescriptor_KillSwitchService_AddAuthorizedUser = new grpc.web.MethodDescriptor(
+  '/KillSwitchService/AddAuthorizedUser',
+  grpc.web.MethodType.UNARY,
+  proto.AddAuthorizedUserRequest,
+  proto.AddAuthorizedUserResponse,
+  /**
+   * @param {!proto.AddAuthorizedUserRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.AddAuthorizedUserResponse.deserializeBinary
+);
+
+
+/**
+ * @const
+ * @type {!grpc.web.AbstractClientBase.MethodInfo<
+ *   !proto.AddAuthorizedUserRequest,
+ *   !proto.AddAuthorizedUserResponse>}
+ */
+const methodInfo_KillSwitchService_AddAuthorizedUser = new grpc.web.AbstractClientBase.MethodInfo(
+  proto.AddAuthorizedUserResponse,
+  /**
+   * @param {!proto.AddAuthorizedUserRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.AddAuthorizedUserResponse.deserializeBinary
+);
+
+
+/**
+ * @param {!proto.AddAuthorizedUserRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @param {function(?grpc.web.Error, ?proto.AddAuthorizedUserResponse)}
+ *     callback The callback function(error, response)
+ * @return {!grpc.web.ClientReadableStream<!proto.AddAuthorizedUserResponse>|undefined}
+ *     The XHR Node Readable Stream
+ */
+proto.KillSwitchServiceClient.prototype.addAuthorizedUser =
+    function(request, metadata, callback) {
+  return this.client_.rpcCall(this.hostname_ +
+      '/KillSwitchService/AddAuthorizedUser',
+      request,
+      metadata || {},
+      methodDescriptor_KillSwitchService_AddAuthorizedUser,
+      callback);
+};
+
+
+/**
+ * @param {!proto.AddAuthorizedUserRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @return {!Promise<!proto.AddAuthorizedUserResponse>}
+ *     Promise that resolves to the response
+ */
+proto.KillSwitchServicePromiseClient.prototype.addAuthorizedUser =
+    function(request, metadata) {
+  return this.client_.unaryCall(this.hostname_ +
+      '/KillSwitchService/AddAuthorizedUser',
+      request,
+      metadata || {},
+      methodDescriptor_KillSwitchService_AddAuthorizedUser);
+};
+
+
+/**
+ * @const
+ * @type {!grpc.web.MethodDescriptor<
+ *   !proto.UpdateAuthorizedUserRequest,
+ *   !proto.UpdateAuthorizedUserResponse>}
+ */
+const methodDescriptor_KillSwitchService_UpdateAuthorizedUser = new grpc.web.MethodDescriptor(
+  '/KillSwitchService/UpdateAuthorizedUser',
+  grpc.web.MethodType.UNARY,
+  proto.UpdateAuthorizedUserRequest,
+  proto.UpdateAuthorizedUserResponse,
+  /**
+   * @param {!proto.UpdateAuthorizedUserRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.UpdateAuthorizedUserResponse.deserializeBinary
+);
+
+
+/**
+ * @const
+ * @type {!grpc.web.AbstractClientBase.MethodInfo<
+ *   !proto.UpdateAuthorizedUserRequest,
+ *   !proto.UpdateAuthorizedUserResponse>}
+ */
+const methodInfo_KillSwitchService_UpdateAuthorizedUser = new grpc.web.AbstractClientBase.MethodInfo(
+  proto.UpdateAuthorizedUserResponse,
+  /**
+   * @param {!proto.UpdateAuthorizedUserRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.UpdateAuthorizedUserResponse.deserializeBinary
+);
+
+
+/**
+ * @param {!proto.UpdateAuthorizedUserRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @param {function(?grpc.web.Error, ?proto.UpdateAuthorizedUserResponse)}
+ *     callback The callback function(error, response)
+ * @return {!grpc.web.ClientReadableStream<!proto.UpdateAuthorizedUserResponse>|undefined}
+ *     The XHR Node Readable Stream
+ */
+proto.KillSwitchServiceClient.prototype.updateAuthorizedUser =
+    function(request, metadata, callback) {
+  return this.client_.rpcCall(this.hostname_ +
+      '/KillSwitchService/UpdateAuthorizedUser',
+      request,
+      metadata || {},
+      methodDescriptor_KillSwitchService_UpdateAuthorizedUser,
+      callback);
+};
+
+
+/**
+ * @param {!proto.UpdateAuthorizedUserRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @return {!Promise<!proto.UpdateAuthorizedUserResponse>}
+ *     Promise that resolves to the response
+ */
+proto.KillSwitchServicePromiseClient.prototype.updateAuthorizedUser =
+    function(request, metadata) {
+  return this.client_.unaryCall(this.hostname_ +
+      '/KillSwitchService/UpdateAuthorizedUser',
+      request,
+      metadata || {},
+      methodDescriptor_KillSwitchService_UpdateAuthorizedUser);
+};
+
+
+/**
+ * @const
+ * @type {!grpc.web.MethodDescriptor<
+ *   !proto.DeleteAuthorizedUserRequest,
+ *   !proto.DeleteAuthorizedUserResponse>}
+ */
+const methodDescriptor_KillSwitchService_DeleteAuthorizedUser = new grpc.web.MethodDescriptor(
+  '/KillSwitchService/DeleteAuthorizedUser',
+  grpc.web.MethodType.UNARY,
+  proto.DeleteAuthorizedUserRequest,
+  proto.DeleteAuthorizedUserResponse,
+  /**
+   * @param {!proto.DeleteAuthorizedUserRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.DeleteAuthorizedUserResponse.deserializeBinary
+);
+
+
+/**
+ * @const
+ * @type {!grpc.web.AbstractClientBase.MethodInfo<
+ *   !proto.DeleteAuthorizedUserRequest,
+ *   !proto.DeleteAuthorizedUserResponse>}
+ */
+const methodInfo_KillSwitchService_DeleteAuthorizedUser = new grpc.web.AbstractClientBase.MethodInfo(
+  proto.DeleteAuthorizedUserResponse,
+  /**
+   * @param {!proto.DeleteAuthorizedUserRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.DeleteAuthorizedUserResponse.deserializeBinary
+);
+
+
+/**
+ * @param {!proto.DeleteAuthorizedUserRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @param {function(?grpc.web.Error, ?proto.DeleteAuthorizedUserResponse)}
+ *     callback The callback function(error, response)
+ * @return {!grpc.web.ClientReadableStream<!proto.DeleteAuthorizedUserResponse>|undefined}
+ *     The XHR Node Readable Stream
+ */
+proto.KillSwitchServiceClient.prototype.deleteAuthorizedUser =
+    function(request, metadata, callback) {
+  return this.client_.rpcCall(this.hostname_ +
+      '/KillSwitchService/DeleteAuthorizedUser',
+      request,
+      metadata || {},
+      methodDescriptor_KillSwitchService_DeleteAuthorizedUser,
+      callback);
+};
+
+
+/**
+ * @param {!proto.DeleteAuthorizedUserRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @return {!Promise<!proto.DeleteAuthorizedUserResponse>}
+ *     Promise that resolves to the response
+ */
+proto.KillSwitchServicePromiseClient.prototype.deleteAuthorizedUser =
+    function(request, metadata) {
+  return this.client_.unaryCall(this.hostname_ +
+      '/KillSwitchService/DeleteAuthorizedUser',
+      request,
+      metadata || {},
+      methodDescriptor_KillSwitchService_DeleteAuthorizedUser);
+};
+
+
+module.exports = proto;
+
diff --git a/frontend/src/api_proto/kill_switch_objects_pb.js b/frontend/src/api_proto/kill_switch_objects_pb.js
new file mode 100644
index 0000000..fede3a9
--- /dev/null
+++ b/frontend/src/api_proto/kill_switch_objects_pb.js
@@ -0,0 +1,2670 @@
+// source: api_proto/kill_switch_objects.proto
+/**
+ * @fileoverview
+ * @enhanceable
+ * @suppress {missingRequire} reports error on implicit type usages.
+ * @suppress {messageConventions} JS Compiler reports an error if a variable or
+ *     field starts with 'MSG_' and isn't a translatable message.
+ * @public
+ */
+// GENERATED CODE -- DO NOT EDIT!
+/* eslint-disable */
+// @ts-nocheck
+
+var jspb = require('google-protobuf');
+var goog = jspb;
+var global = Function('return this')();
+
+var api_proto_common_pb = require('../api_proto/common_pb.js');
+goog.object.extend(proto, api_proto_common_pb);
+var google_protobuf_timestamp_pb = require('google-protobuf/google/protobuf/timestamp_pb.js');
+goog.object.extend(proto, google_protobuf_timestamp_pb);
+goog.exportSymbol('proto.AuthorizedUserTransformation', null, global);
+goog.exportSymbol('proto.Feature', null, global);
+goog.exportSymbol('proto.Feature.Type', null, global);
+goog.exportSymbol('proto.KillSwitch', null, global);
+goog.exportSymbol('proto.KillSwitchAuditLogEntry', null, global);
+goog.exportSymbol('proto.KillSwitchAuditLogEntry.AuthorizedUserAdded', null, global);
+goog.exportSymbol('proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted', null, global);
+goog.exportSymbol('proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated', null, global);
+goog.exportSymbol('proto.KillSwitchAuditLogEntry.DescriptionCase', null, global);
+goog.exportSymbol('proto.KillSwitchAuditLogEntry.KillSwitchDisabled', null, global);
+goog.exportSymbol('proto.KillSwitchAuditLogEntry.KillSwitchEnabled', null, global);
+goog.exportSymbol('proto.KillSwitchAuthorizedUser', null, global);
+goog.exportSymbol('proto.KillSwitchAuthorizedUser.AccessLevel', null, global);
+goog.exportSymbol('proto.KillSwitchTransformation', null, global);
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.Feature = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.Feature, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.Feature.displayName = 'proto.Feature';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.KillSwitch = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, proto.KillSwitch.repeatedFields_, null);
+};
+goog.inherits(proto.KillSwitch, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.KillSwitch.displayName = 'proto.KillSwitch';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.KillSwitchAuthorizedUser = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.KillSwitchAuthorizedUser, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.KillSwitchAuthorizedUser.displayName = 'proto.KillSwitchAuthorizedUser';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.KillSwitchTransformation = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.KillSwitchTransformation, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.KillSwitchTransformation.displayName = 'proto.KillSwitchTransformation';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.AuthorizedUserTransformation = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.AuthorizedUserTransformation, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.AuthorizedUserTransformation.displayName = 'proto.AuthorizedUserTransformation';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.KillSwitchAuditLogEntry = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, proto.KillSwitchAuditLogEntry.oneofGroups_);
+};
+goog.inherits(proto.KillSwitchAuditLogEntry, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.KillSwitchAuditLogEntry.displayName = 'proto.KillSwitchAuditLogEntry';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.KillSwitchAuditLogEntry.KillSwitchEnabled = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.KillSwitchAuditLogEntry.KillSwitchEnabled, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.KillSwitchAuditLogEntry.KillSwitchEnabled.displayName = 'proto.KillSwitchAuditLogEntry.KillSwitchEnabled';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.KillSwitchAuditLogEntry.KillSwitchDisabled = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.KillSwitchAuditLogEntry.KillSwitchDisabled, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.KillSwitchAuditLogEntry.KillSwitchDisabled.displayName = 'proto.KillSwitchAuditLogEntry.KillSwitchDisabled';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserAdded = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.KillSwitchAuditLogEntry.AuthorizedUserAdded, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.KillSwitchAuditLogEntry.AuthorizedUserAdded.displayName = 'proto.KillSwitchAuditLogEntry.AuthorizedUserAdded';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated.displayName = 'proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted.displayName = 'proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted';
+}
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.Feature.prototype.toObject = function(opt_includeInstance) {
+  return proto.Feature.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.Feature} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.Feature.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    id: jspb.Message.getFieldWithDefault(msg, 1, 0),
+    codename: jspb.Message.getFieldWithDefault(msg, 2, ""),
+    type: jspb.Message.getFieldWithDefault(msg, 3, 0)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.Feature}
+ */
+proto.Feature.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.Feature;
+  return proto.Feature.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.Feature} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.Feature}
+ */
+proto.Feature.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {number} */ (reader.readInt32());
+      msg.setId(value);
+      break;
+    case 2:
+      var value = /** @type {string} */ (reader.readString());
+      msg.setCodename(value);
+      break;
+    case 3:
+      var value = /** @type {!proto.Feature.Type} */ (reader.readEnum());
+      msg.setType(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.Feature.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.Feature.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.Feature} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.Feature.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getId();
+  if (f !== 0) {
+    writer.writeInt32(
+      1,
+      f
+    );
+  }
+  f = message.getCodename();
+  if (f.length > 0) {
+    writer.writeString(
+      2,
+      f
+    );
+  }
+  f = message.getType();
+  if (f !== 0.0) {
+    writer.writeEnum(
+      3,
+      f
+    );
+  }
+};
+
+
+/**
+ * @enum {number}
+ */
+proto.Feature.Type = {
+  TYPE_UNKNOWN: 0,
+  TYPE_EXPERIMENT: 1,
+  TYPE_OPTION: 2,
+  TYPE_DEPRECATED: 10
+};
+
+/**
+ * optional int32 id = 1;
+ * @return {number}
+ */
+proto.Feature.prototype.getId = function() {
+  return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));
+};
+
+
+/**
+ * @param {number} value
+ * @return {!proto.Feature} returns this
+ */
+proto.Feature.prototype.setId = function(value) {
+  return jspb.Message.setProto3IntField(this, 1, value);
+};
+
+
+/**
+ * optional string codename = 2;
+ * @return {string}
+ */
+proto.Feature.prototype.getCodename = function() {
+  return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, ""));
+};
+
+
+/**
+ * @param {string} value
+ * @return {!proto.Feature} returns this
+ */
+proto.Feature.prototype.setCodename = function(value) {
+  return jspb.Message.setProto3StringField(this, 2, value);
+};
+
+
+/**
+ * optional Type type = 3;
+ * @return {!proto.Feature.Type}
+ */
+proto.Feature.prototype.getType = function() {
+  return /** @type {!proto.Feature.Type} */ (jspb.Message.getFieldWithDefault(this, 3, 0));
+};
+
+
+/**
+ * @param {!proto.Feature.Type} value
+ * @return {!proto.Feature} returns this
+ */
+proto.Feature.prototype.setType = function(value) {
+  return jspb.Message.setProto3EnumField(this, 3, value);
+};
+
+
+
+/**
+ * List of repeated fields within this message type.
+ * @private {!Array<number>}
+ * @const
+ */
+proto.KillSwitch.repeatedFields_ = [5];
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.KillSwitch.prototype.toObject = function(opt_includeInstance) {
+  return proto.KillSwitch.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.KillSwitch} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.KillSwitch.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    id: jspb.Message.getFieldWithDefault(msg, 1, 0),
+    feature: (f = msg.getFeature()) && proto.Feature.toObject(includeInstance, f),
+    minVersion: jspb.Message.getFieldWithDefault(msg, 3, ""),
+    maxVersion: jspb.Message.getFieldWithDefault(msg, 4, ""),
+    browsersList: (f = jspb.Message.getRepeatedField(msg, 5)) == null ? undefined : f,
+    active: jspb.Message.getBooleanFieldWithDefault(msg, 6, false)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.KillSwitch}
+ */
+proto.KillSwitch.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.KillSwitch;
+  return proto.KillSwitch.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.KillSwitch} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.KillSwitch}
+ */
+proto.KillSwitch.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {number} */ (reader.readInt32());
+      msg.setId(value);
+      break;
+    case 2:
+      var value = new proto.Feature;
+      reader.readMessage(value,proto.Feature.deserializeBinaryFromReader);
+      msg.setFeature(value);
+      break;
+    case 3:
+      var value = /** @type {string} */ (reader.readString());
+      msg.setMinVersion(value);
+      break;
+    case 4:
+      var value = /** @type {string} */ (reader.readString());
+      msg.setMaxVersion(value);
+      break;
+    case 5:
+      var values = /** @type {!Array<!proto.Environment.Browser>} */ (reader.isDelimited() ? reader.readPackedEnum() : [reader.readEnum()]);
+      for (var i = 0; i < values.length; i++) {
+        msg.addBrowsers(values[i]);
+      }
+      break;
+    case 6:
+      var value = /** @type {boolean} */ (reader.readBool());
+      msg.setActive(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.KillSwitch.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.KillSwitch.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.KillSwitch} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.KillSwitch.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getId();
+  if (f !== 0) {
+    writer.writeInt32(
+      1,
+      f
+    );
+  }
+  f = message.getFeature();
+  if (f != null) {
+    writer.writeMessage(
+      2,
+      f,
+      proto.Feature.serializeBinaryToWriter
+    );
+  }
+  f = message.getMinVersion();
+  if (f.length > 0) {
+    writer.writeString(
+      3,
+      f
+    );
+  }
+  f = message.getMaxVersion();
+  if (f.length > 0) {
+    writer.writeString(
+      4,
+      f
+    );
+  }
+  f = message.getBrowsersList();
+  if (f.length > 0) {
+    writer.writePackedEnum(
+      5,
+      f
+    );
+  }
+  f = message.getActive();
+  if (f) {
+    writer.writeBool(
+      6,
+      f
+    );
+  }
+};
+
+
+/**
+ * optional int32 id = 1;
+ * @return {number}
+ */
+proto.KillSwitch.prototype.getId = function() {
+  return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));
+};
+
+
+/**
+ * @param {number} value
+ * @return {!proto.KillSwitch} returns this
+ */
+proto.KillSwitch.prototype.setId = function(value) {
+  return jspb.Message.setProto3IntField(this, 1, value);
+};
+
+
+/**
+ * optional Feature feature = 2;
+ * @return {?proto.Feature}
+ */
+proto.KillSwitch.prototype.getFeature = function() {
+  return /** @type{?proto.Feature} */ (
+    jspb.Message.getWrapperField(this, proto.Feature, 2));
+};
+
+
+/**
+ * @param {?proto.Feature|undefined} value
+ * @return {!proto.KillSwitch} returns this
+*/
+proto.KillSwitch.prototype.setFeature = function(value) {
+  return jspb.Message.setWrapperField(this, 2, value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.KillSwitch} returns this
+ */
+proto.KillSwitch.prototype.clearFeature = function() {
+  return this.setFeature(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.KillSwitch.prototype.hasFeature = function() {
+  return jspb.Message.getField(this, 2) != null;
+};
+
+
+/**
+ * optional string min_version = 3;
+ * @return {string}
+ */
+proto.KillSwitch.prototype.getMinVersion = function() {
+  return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, ""));
+};
+
+
+/**
+ * @param {string} value
+ * @return {!proto.KillSwitch} returns this
+ */
+proto.KillSwitch.prototype.setMinVersion = function(value) {
+  return jspb.Message.setProto3StringField(this, 3, value);
+};
+
+
+/**
+ * optional string max_version = 4;
+ * @return {string}
+ */
+proto.KillSwitch.prototype.getMaxVersion = function() {
+  return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, ""));
+};
+
+
+/**
+ * @param {string} value
+ * @return {!proto.KillSwitch} returns this
+ */
+proto.KillSwitch.prototype.setMaxVersion = function(value) {
+  return jspb.Message.setProto3StringField(this, 4, value);
+};
+
+
+/**
+ * repeated Environment.Browser browsers = 5;
+ * @return {!Array<!proto.Environment.Browser>}
+ */
+proto.KillSwitch.prototype.getBrowsersList = function() {
+  return /** @type {!Array<!proto.Environment.Browser>} */ (jspb.Message.getRepeatedField(this, 5));
+};
+
+
+/**
+ * @param {!Array<!proto.Environment.Browser>} value
+ * @return {!proto.KillSwitch} returns this
+ */
+proto.KillSwitch.prototype.setBrowsersList = function(value) {
+  return jspb.Message.setField(this, 5, value || []);
+};
+
+
+/**
+ * @param {!proto.Environment.Browser} value
+ * @param {number=} opt_index
+ * @return {!proto.KillSwitch} returns this
+ */
+proto.KillSwitch.prototype.addBrowsers = function(value, opt_index) {
+  return jspb.Message.addToRepeatedField(this, 5, value, opt_index);
+};
+
+
+/**
+ * Clears the list making it empty but non-null.
+ * @return {!proto.KillSwitch} returns this
+ */
+proto.KillSwitch.prototype.clearBrowsersList = function() {
+  return this.setBrowsersList([]);
+};
+
+
+/**
+ * optional bool active = 6;
+ * @return {boolean}
+ */
+proto.KillSwitch.prototype.getActive = function() {
+  return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 6, false));
+};
+
+
+/**
+ * @param {boolean} value
+ * @return {!proto.KillSwitch} returns this
+ */
+proto.KillSwitch.prototype.setActive = function(value) {
+  return jspb.Message.setProto3BooleanField(this, 6, value);
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.KillSwitchAuthorizedUser.prototype.toObject = function(opt_includeInstance) {
+  return proto.KillSwitchAuthorizedUser.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.KillSwitchAuthorizedUser} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.KillSwitchAuthorizedUser.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    id: jspb.Message.getFieldWithDefault(msg, 1, 0),
+    googleUid: jspb.Message.getFieldWithDefault(msg, 2, ""),
+    email: jspb.Message.getFieldWithDefault(msg, 3, ""),
+    accessLevel: jspb.Message.getFieldWithDefault(msg, 4, 0)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.KillSwitchAuthorizedUser}
+ */
+proto.KillSwitchAuthorizedUser.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.KillSwitchAuthorizedUser;
+  return proto.KillSwitchAuthorizedUser.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.KillSwitchAuthorizedUser} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.KillSwitchAuthorizedUser}
+ */
+proto.KillSwitchAuthorizedUser.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {number} */ (reader.readInt32());
+      msg.setId(value);
+      break;
+    case 2:
+      var value = /** @type {string} */ (reader.readString());
+      msg.setGoogleUid(value);
+      break;
+    case 3:
+      var value = /** @type {string} */ (reader.readString());
+      msg.setEmail(value);
+      break;
+    case 4:
+      var value = /** @type {!proto.KillSwitchAuthorizedUser.AccessLevel} */ (reader.readEnum());
+      msg.setAccessLevel(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.KillSwitchAuthorizedUser.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.KillSwitchAuthorizedUser.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.KillSwitchAuthorizedUser} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.KillSwitchAuthorizedUser.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getId();
+  if (f !== 0) {
+    writer.writeInt32(
+      1,
+      f
+    );
+  }
+  f = message.getGoogleUid();
+  if (f.length > 0) {
+    writer.writeString(
+      2,
+      f
+    );
+  }
+  f = message.getEmail();
+  if (f.length > 0) {
+    writer.writeString(
+      3,
+      f
+    );
+  }
+  f = message.getAccessLevel();
+  if (f !== 0.0) {
+    writer.writeEnum(
+      4,
+      f
+    );
+  }
+};
+
+
+/**
+ * @enum {number}
+ */
+proto.KillSwitchAuthorizedUser.AccessLevel = {
+  ACCESS_LEVEL_NONE: 0,
+  ACCESS_LEVEL_ACTIVATOR: 5,
+  ACCESS_LEVEL_ADMIN: 10
+};
+
+/**
+ * optional int32 id = 1;
+ * @return {number}
+ */
+proto.KillSwitchAuthorizedUser.prototype.getId = function() {
+  return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));
+};
+
+
+/**
+ * @param {number} value
+ * @return {!proto.KillSwitchAuthorizedUser} returns this
+ */
+proto.KillSwitchAuthorizedUser.prototype.setId = function(value) {
+  return jspb.Message.setProto3IntField(this, 1, value);
+};
+
+
+/**
+ * optional string google_uid = 2;
+ * @return {string}
+ */
+proto.KillSwitchAuthorizedUser.prototype.getGoogleUid = function() {
+  return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, ""));
+};
+
+
+/**
+ * @param {string} value
+ * @return {!proto.KillSwitchAuthorizedUser} returns this
+ */
+proto.KillSwitchAuthorizedUser.prototype.setGoogleUid = function(value) {
+  return jspb.Message.setProto3StringField(this, 2, value);
+};
+
+
+/**
+ * optional string email = 3;
+ * @return {string}
+ */
+proto.KillSwitchAuthorizedUser.prototype.getEmail = function() {
+  return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, ""));
+};
+
+
+/**
+ * @param {string} value
+ * @return {!proto.KillSwitchAuthorizedUser} returns this
+ */
+proto.KillSwitchAuthorizedUser.prototype.setEmail = function(value) {
+  return jspb.Message.setProto3StringField(this, 3, value);
+};
+
+
+/**
+ * optional AccessLevel access_level = 4;
+ * @return {!proto.KillSwitchAuthorizedUser.AccessLevel}
+ */
+proto.KillSwitchAuthorizedUser.prototype.getAccessLevel = function() {
+  return /** @type {!proto.KillSwitchAuthorizedUser.AccessLevel} */ (jspb.Message.getFieldWithDefault(this, 4, 0));
+};
+
+
+/**
+ * @param {!proto.KillSwitchAuthorizedUser.AccessLevel} value
+ * @return {!proto.KillSwitchAuthorizedUser} returns this
+ */
+proto.KillSwitchAuthorizedUser.prototype.setAccessLevel = function(value) {
+  return jspb.Message.setProto3EnumField(this, 4, value);
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.KillSwitchTransformation.prototype.toObject = function(opt_includeInstance) {
+  return proto.KillSwitchTransformation.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.KillSwitchTransformation} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.KillSwitchTransformation.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    old: (f = msg.getOld()) && proto.KillSwitch.toObject(includeInstance, f),
+    pb_new: (f = msg.getNew()) && proto.KillSwitch.toObject(includeInstance, f)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.KillSwitchTransformation}
+ */
+proto.KillSwitchTransformation.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.KillSwitchTransformation;
+  return proto.KillSwitchTransformation.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.KillSwitchTransformation} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.KillSwitchTransformation}
+ */
+proto.KillSwitchTransformation.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = new proto.KillSwitch;
+      reader.readMessage(value,proto.KillSwitch.deserializeBinaryFromReader);
+      msg.setOld(value);
+      break;
+    case 2:
+      var value = new proto.KillSwitch;
+      reader.readMessage(value,proto.KillSwitch.deserializeBinaryFromReader);
+      msg.setNew(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.KillSwitchTransformation.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.KillSwitchTransformation.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.KillSwitchTransformation} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.KillSwitchTransformation.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getOld();
+  if (f != null) {
+    writer.writeMessage(
+      1,
+      f,
+      proto.KillSwitch.serializeBinaryToWriter
+    );
+  }
+  f = message.getNew();
+  if (f != null) {
+    writer.writeMessage(
+      2,
+      f,
+      proto.KillSwitch.serializeBinaryToWriter
+    );
+  }
+};
+
+
+/**
+ * optional KillSwitch old = 1;
+ * @return {?proto.KillSwitch}
+ */
+proto.KillSwitchTransformation.prototype.getOld = function() {
+  return /** @type{?proto.KillSwitch} */ (
+    jspb.Message.getWrapperField(this, proto.KillSwitch, 1));
+};
+
+
+/**
+ * @param {?proto.KillSwitch|undefined} value
+ * @return {!proto.KillSwitchTransformation} returns this
+*/
+proto.KillSwitchTransformation.prototype.setOld = function(value) {
+  return jspb.Message.setWrapperField(this, 1, value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.KillSwitchTransformation} returns this
+ */
+proto.KillSwitchTransformation.prototype.clearOld = function() {
+  return this.setOld(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.KillSwitchTransformation.prototype.hasOld = function() {
+  return jspb.Message.getField(this, 1) != null;
+};
+
+
+/**
+ * optional KillSwitch new = 2;
+ * @return {?proto.KillSwitch}
+ */
+proto.KillSwitchTransformation.prototype.getNew = function() {
+  return /** @type{?proto.KillSwitch} */ (
+    jspb.Message.getWrapperField(this, proto.KillSwitch, 2));
+};
+
+
+/**
+ * @param {?proto.KillSwitch|undefined} value
+ * @return {!proto.KillSwitchTransformation} returns this
+*/
+proto.KillSwitchTransformation.prototype.setNew = function(value) {
+  return jspb.Message.setWrapperField(this, 2, value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.KillSwitchTransformation} returns this
+ */
+proto.KillSwitchTransformation.prototype.clearNew = function() {
+  return this.setNew(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.KillSwitchTransformation.prototype.hasNew = function() {
+  return jspb.Message.getField(this, 2) != null;
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.AuthorizedUserTransformation.prototype.toObject = function(opt_includeInstance) {
+  return proto.AuthorizedUserTransformation.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.AuthorizedUserTransformation} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.AuthorizedUserTransformation.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    old: (f = msg.getOld()) && proto.KillSwitchAuthorizedUser.toObject(includeInstance, f),
+    pb_new: (f = msg.getNew()) && proto.KillSwitchAuthorizedUser.toObject(includeInstance, f)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.AuthorizedUserTransformation}
+ */
+proto.AuthorizedUserTransformation.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.AuthorizedUserTransformation;
+  return proto.AuthorizedUserTransformation.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.AuthorizedUserTransformation} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.AuthorizedUserTransformation}
+ */
+proto.AuthorizedUserTransformation.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = new proto.KillSwitchAuthorizedUser;
+      reader.readMessage(value,proto.KillSwitchAuthorizedUser.deserializeBinaryFromReader);
+      msg.setOld(value);
+      break;
+    case 2:
+      var value = new proto.KillSwitchAuthorizedUser;
+      reader.readMessage(value,proto.KillSwitchAuthorizedUser.deserializeBinaryFromReader);
+      msg.setNew(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.AuthorizedUserTransformation.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.AuthorizedUserTransformation.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.AuthorizedUserTransformation} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.AuthorizedUserTransformation.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getOld();
+  if (f != null) {
+    writer.writeMessage(
+      1,
+      f,
+      proto.KillSwitchAuthorizedUser.serializeBinaryToWriter
+    );
+  }
+  f = message.getNew();
+  if (f != null) {
+    writer.writeMessage(
+      2,
+      f,
+      proto.KillSwitchAuthorizedUser.serializeBinaryToWriter
+    );
+  }
+};
+
+
+/**
+ * optional KillSwitchAuthorizedUser old = 1;
+ * @return {?proto.KillSwitchAuthorizedUser}
+ */
+proto.AuthorizedUserTransformation.prototype.getOld = function() {
+  return /** @type{?proto.KillSwitchAuthorizedUser} */ (
+    jspb.Message.getWrapperField(this, proto.KillSwitchAuthorizedUser, 1));
+};
+
+
+/**
+ * @param {?proto.KillSwitchAuthorizedUser|undefined} value
+ * @return {!proto.AuthorizedUserTransformation} returns this
+*/
+proto.AuthorizedUserTransformation.prototype.setOld = function(value) {
+  return jspb.Message.setWrapperField(this, 1, value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.AuthorizedUserTransformation} returns this
+ */
+proto.AuthorizedUserTransformation.prototype.clearOld = function() {
+  return this.setOld(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.AuthorizedUserTransformation.prototype.hasOld = function() {
+  return jspb.Message.getField(this, 1) != null;
+};
+
+
+/**
+ * optional KillSwitchAuthorizedUser new = 2;
+ * @return {?proto.KillSwitchAuthorizedUser}
+ */
+proto.AuthorizedUserTransformation.prototype.getNew = function() {
+  return /** @type{?proto.KillSwitchAuthorizedUser} */ (
+    jspb.Message.getWrapperField(this, proto.KillSwitchAuthorizedUser, 2));
+};
+
+
+/**
+ * @param {?proto.KillSwitchAuthorizedUser|undefined} value
+ * @return {!proto.AuthorizedUserTransformation} returns this
+*/
+proto.AuthorizedUserTransformation.prototype.setNew = function(value) {
+  return jspb.Message.setWrapperField(this, 2, value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.AuthorizedUserTransformation} returns this
+ */
+proto.AuthorizedUserTransformation.prototype.clearNew = function() {
+  return this.setNew(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.AuthorizedUserTransformation.prototype.hasNew = function() {
+  return jspb.Message.getField(this, 2) != null;
+};
+
+
+
+/**
+ * Oneof group definitions for this message. Each group defines the field
+ * numbers belonging to that group. When of these fields' value is set, all
+ * other fields in the group are cleared. During deserialization, if multiple
+ * fields are encountered for a group, only the last value seen will be kept.
+ * @private {!Array<!Array<number>>}
+ * @const
+ */
+proto.KillSwitchAuditLogEntry.oneofGroups_ = [[3,4,5,6,7]];
+
+/**
+ * @enum {number}
+ */
+proto.KillSwitchAuditLogEntry.DescriptionCase = {
+  DESCRIPTION_NOT_SET: 0,
+  KILL_SWITCH_ENABLED: 3,
+  KILL_SWITCH_DISABLED: 4,
+  AUTHORIZED_USER_ADDED: 5,
+  AUTHORIZED_USER_UPDATED: 6,
+  AUTHORIZED_USER_DELETED: 7
+};
+
+/**
+ * @return {proto.KillSwitchAuditLogEntry.DescriptionCase}
+ */
+proto.KillSwitchAuditLogEntry.prototype.getDescriptionCase = function() {
+  return /** @type {proto.KillSwitchAuditLogEntry.DescriptionCase} */(jspb.Message.computeOneofCase(this, proto.KillSwitchAuditLogEntry.oneofGroups_[0]));
+};
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.KillSwitchAuditLogEntry.prototype.toObject = function(opt_includeInstance) {
+  return proto.KillSwitchAuditLogEntry.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.KillSwitchAuditLogEntry} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.KillSwitchAuditLogEntry.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    timestamp: (f = msg.getTimestamp()) && google_protobuf_timestamp_pb.Timestamp.toObject(includeInstance, f),
+    user: (f = msg.getUser()) && proto.KillSwitchAuthorizedUser.toObject(includeInstance, f),
+    killSwitchEnabled: (f = msg.getKillSwitchEnabled()) && proto.KillSwitchAuditLogEntry.KillSwitchEnabled.toObject(includeInstance, f),
+    killSwitchDisabled: (f = msg.getKillSwitchDisabled()) && proto.KillSwitchAuditLogEntry.KillSwitchDisabled.toObject(includeInstance, f),
+    authorizedUserAdded: (f = msg.getAuthorizedUserAdded()) && proto.KillSwitchAuditLogEntry.AuthorizedUserAdded.toObject(includeInstance, f),
+    authorizedUserUpdated: (f = msg.getAuthorizedUserUpdated()) && proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated.toObject(includeInstance, f),
+    authorizedUserDeleted: (f = msg.getAuthorizedUserDeleted()) && proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted.toObject(includeInstance, f)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.KillSwitchAuditLogEntry}
+ */
+proto.KillSwitchAuditLogEntry.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.KillSwitchAuditLogEntry;
+  return proto.KillSwitchAuditLogEntry.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.KillSwitchAuditLogEntry} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.KillSwitchAuditLogEntry}
+ */
+proto.KillSwitchAuditLogEntry.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = new google_protobuf_timestamp_pb.Timestamp;
+      reader.readMessage(value,google_protobuf_timestamp_pb.Timestamp.deserializeBinaryFromReader);
+      msg.setTimestamp(value);
+      break;
+    case 2:
+      var value = new proto.KillSwitchAuthorizedUser;
+      reader.readMessage(value,proto.KillSwitchAuthorizedUser.deserializeBinaryFromReader);
+      msg.setUser(value);
+      break;
+    case 3:
+      var value = new proto.KillSwitchAuditLogEntry.KillSwitchEnabled;
+      reader.readMessage(value,proto.KillSwitchAuditLogEntry.KillSwitchEnabled.deserializeBinaryFromReader);
+      msg.setKillSwitchEnabled(value);
+      break;
+    case 4:
+      var value = new proto.KillSwitchAuditLogEntry.KillSwitchDisabled;
+      reader.readMessage(value,proto.KillSwitchAuditLogEntry.KillSwitchDisabled.deserializeBinaryFromReader);
+      msg.setKillSwitchDisabled(value);
+      break;
+    case 5:
+      var value = new proto.KillSwitchAuditLogEntry.AuthorizedUserAdded;
+      reader.readMessage(value,proto.KillSwitchAuditLogEntry.AuthorizedUserAdded.deserializeBinaryFromReader);
+      msg.setAuthorizedUserAdded(value);
+      break;
+    case 6:
+      var value = new proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated;
+      reader.readMessage(value,proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated.deserializeBinaryFromReader);
+      msg.setAuthorizedUserUpdated(value);
+      break;
+    case 7:
+      var value = new proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted;
+      reader.readMessage(value,proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted.deserializeBinaryFromReader);
+      msg.setAuthorizedUserDeleted(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.KillSwitchAuditLogEntry.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.KillSwitchAuditLogEntry.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.KillSwitchAuditLogEntry} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.KillSwitchAuditLogEntry.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getTimestamp();
+  if (f != null) {
+    writer.writeMessage(
+      1,
+      f,
+      google_protobuf_timestamp_pb.Timestamp.serializeBinaryToWriter
+    );
+  }
+  f = message.getUser();
+  if (f != null) {
+    writer.writeMessage(
+      2,
+      f,
+      proto.KillSwitchAuthorizedUser.serializeBinaryToWriter
+    );
+  }
+  f = message.getKillSwitchEnabled();
+  if (f != null) {
+    writer.writeMessage(
+      3,
+      f,
+      proto.KillSwitchAuditLogEntry.KillSwitchEnabled.serializeBinaryToWriter
+    );
+  }
+  f = message.getKillSwitchDisabled();
+  if (f != null) {
+    writer.writeMessage(
+      4,
+      f,
+      proto.KillSwitchAuditLogEntry.KillSwitchDisabled.serializeBinaryToWriter
+    );
+  }
+  f = message.getAuthorizedUserAdded();
+  if (f != null) {
+    writer.writeMessage(
+      5,
+      f,
+      proto.KillSwitchAuditLogEntry.AuthorizedUserAdded.serializeBinaryToWriter
+    );
+  }
+  f = message.getAuthorizedUserUpdated();
+  if (f != null) {
+    writer.writeMessage(
+      6,
+      f,
+      proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated.serializeBinaryToWriter
+    );
+  }
+  f = message.getAuthorizedUserDeleted();
+  if (f != null) {
+    writer.writeMessage(
+      7,
+      f,
+      proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted.serializeBinaryToWriter
+    );
+  }
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.KillSwitchAuditLogEntry.KillSwitchEnabled.prototype.toObject = function(opt_includeInstance) {
+  return proto.KillSwitchAuditLogEntry.KillSwitchEnabled.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.KillSwitchAuditLogEntry.KillSwitchEnabled} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.KillSwitchAuditLogEntry.KillSwitchEnabled.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    killSwitch: (f = msg.getKillSwitch()) && proto.KillSwitch.toObject(includeInstance, f)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.KillSwitchAuditLogEntry.KillSwitchEnabled}
+ */
+proto.KillSwitchAuditLogEntry.KillSwitchEnabled.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.KillSwitchAuditLogEntry.KillSwitchEnabled;
+  return proto.KillSwitchAuditLogEntry.KillSwitchEnabled.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.KillSwitchAuditLogEntry.KillSwitchEnabled} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.KillSwitchAuditLogEntry.KillSwitchEnabled}
+ */
+proto.KillSwitchAuditLogEntry.KillSwitchEnabled.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = new proto.KillSwitch;
+      reader.readMessage(value,proto.KillSwitch.deserializeBinaryFromReader);
+      msg.setKillSwitch(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.KillSwitchAuditLogEntry.KillSwitchEnabled.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.KillSwitchAuditLogEntry.KillSwitchEnabled.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.KillSwitchAuditLogEntry.KillSwitchEnabled} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.KillSwitchAuditLogEntry.KillSwitchEnabled.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getKillSwitch();
+  if (f != null) {
+    writer.writeMessage(
+      1,
+      f,
+      proto.KillSwitch.serializeBinaryToWriter
+    );
+  }
+};
+
+
+/**
+ * optional KillSwitch kill_switch = 1;
+ * @return {?proto.KillSwitch}
+ */
+proto.KillSwitchAuditLogEntry.KillSwitchEnabled.prototype.getKillSwitch = function() {
+  return /** @type{?proto.KillSwitch} */ (
+    jspb.Message.getWrapperField(this, proto.KillSwitch, 1));
+};
+
+
+/**
+ * @param {?proto.KillSwitch|undefined} value
+ * @return {!proto.KillSwitchAuditLogEntry.KillSwitchEnabled} returns this
+*/
+proto.KillSwitchAuditLogEntry.KillSwitchEnabled.prototype.setKillSwitch = function(value) {
+  return jspb.Message.setWrapperField(this, 1, value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.KillSwitchAuditLogEntry.KillSwitchEnabled} returns this
+ */
+proto.KillSwitchAuditLogEntry.KillSwitchEnabled.prototype.clearKillSwitch = function() {
+  return this.setKillSwitch(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.KillSwitchAuditLogEntry.KillSwitchEnabled.prototype.hasKillSwitch = function() {
+  return jspb.Message.getField(this, 1) != null;
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.KillSwitchAuditLogEntry.KillSwitchDisabled.prototype.toObject = function(opt_includeInstance) {
+  return proto.KillSwitchAuditLogEntry.KillSwitchDisabled.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.KillSwitchAuditLogEntry.KillSwitchDisabled} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.KillSwitchAuditLogEntry.KillSwitchDisabled.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    transformation: (f = msg.getTransformation()) && proto.KillSwitchTransformation.toObject(includeInstance, f)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.KillSwitchAuditLogEntry.KillSwitchDisabled}
+ */
+proto.KillSwitchAuditLogEntry.KillSwitchDisabled.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.KillSwitchAuditLogEntry.KillSwitchDisabled;
+  return proto.KillSwitchAuditLogEntry.KillSwitchDisabled.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.KillSwitchAuditLogEntry.KillSwitchDisabled} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.KillSwitchAuditLogEntry.KillSwitchDisabled}
+ */
+proto.KillSwitchAuditLogEntry.KillSwitchDisabled.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = new proto.KillSwitchTransformation;
+      reader.readMessage(value,proto.KillSwitchTransformation.deserializeBinaryFromReader);
+      msg.setTransformation(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.KillSwitchAuditLogEntry.KillSwitchDisabled.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.KillSwitchAuditLogEntry.KillSwitchDisabled.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.KillSwitchAuditLogEntry.KillSwitchDisabled} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.KillSwitchAuditLogEntry.KillSwitchDisabled.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getTransformation();
+  if (f != null) {
+    writer.writeMessage(
+      1,
+      f,
+      proto.KillSwitchTransformation.serializeBinaryToWriter
+    );
+  }
+};
+
+
+/**
+ * optional KillSwitchTransformation transformation = 1;
+ * @return {?proto.KillSwitchTransformation}
+ */
+proto.KillSwitchAuditLogEntry.KillSwitchDisabled.prototype.getTransformation = function() {
+  return /** @type{?proto.KillSwitchTransformation} */ (
+    jspb.Message.getWrapperField(this, proto.KillSwitchTransformation, 1));
+};
+
+
+/**
+ * @param {?proto.KillSwitchTransformation|undefined} value
+ * @return {!proto.KillSwitchAuditLogEntry.KillSwitchDisabled} returns this
+*/
+proto.KillSwitchAuditLogEntry.KillSwitchDisabled.prototype.setTransformation = function(value) {
+  return jspb.Message.setWrapperField(this, 1, value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.KillSwitchAuditLogEntry.KillSwitchDisabled} returns this
+ */
+proto.KillSwitchAuditLogEntry.KillSwitchDisabled.prototype.clearTransformation = function() {
+  return this.setTransformation(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.KillSwitchAuditLogEntry.KillSwitchDisabled.prototype.hasTransformation = function() {
+  return jspb.Message.getField(this, 1) != null;
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserAdded.prototype.toObject = function(opt_includeInstance) {
+  return proto.KillSwitchAuditLogEntry.AuthorizedUserAdded.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.KillSwitchAuditLogEntry.AuthorizedUserAdded} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserAdded.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    user: (f = msg.getUser()) && proto.KillSwitchAuthorizedUser.toObject(includeInstance, f)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.KillSwitchAuditLogEntry.AuthorizedUserAdded}
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserAdded.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.KillSwitchAuditLogEntry.AuthorizedUserAdded;
+  return proto.KillSwitchAuditLogEntry.AuthorizedUserAdded.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.KillSwitchAuditLogEntry.AuthorizedUserAdded} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.KillSwitchAuditLogEntry.AuthorizedUserAdded}
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserAdded.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = new proto.KillSwitchAuthorizedUser;
+      reader.readMessage(value,proto.KillSwitchAuthorizedUser.deserializeBinaryFromReader);
+      msg.setUser(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserAdded.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.KillSwitchAuditLogEntry.AuthorizedUserAdded.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.KillSwitchAuditLogEntry.AuthorizedUserAdded} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserAdded.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getUser();
+  if (f != null) {
+    writer.writeMessage(
+      1,
+      f,
+      proto.KillSwitchAuthorizedUser.serializeBinaryToWriter
+    );
+  }
+};
+
+
+/**
+ * optional KillSwitchAuthorizedUser user = 1;
+ * @return {?proto.KillSwitchAuthorizedUser}
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserAdded.prototype.getUser = function() {
+  return /** @type{?proto.KillSwitchAuthorizedUser} */ (
+    jspb.Message.getWrapperField(this, proto.KillSwitchAuthorizedUser, 1));
+};
+
+
+/**
+ * @param {?proto.KillSwitchAuthorizedUser|undefined} value
+ * @return {!proto.KillSwitchAuditLogEntry.AuthorizedUserAdded} returns this
+*/
+proto.KillSwitchAuditLogEntry.AuthorizedUserAdded.prototype.setUser = function(value) {
+  return jspb.Message.setWrapperField(this, 1, value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.KillSwitchAuditLogEntry.AuthorizedUserAdded} returns this
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserAdded.prototype.clearUser = function() {
+  return this.setUser(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserAdded.prototype.hasUser = function() {
+  return jspb.Message.getField(this, 1) != null;
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated.prototype.toObject = function(opt_includeInstance) {
+  return proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    transformation: (f = msg.getTransformation()) && proto.AuthorizedUserTransformation.toObject(includeInstance, f)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated}
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated;
+  return proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated}
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = new proto.AuthorizedUserTransformation;
+      reader.readMessage(value,proto.AuthorizedUserTransformation.deserializeBinaryFromReader);
+      msg.setTransformation(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getTransformation();
+  if (f != null) {
+    writer.writeMessage(
+      1,
+      f,
+      proto.AuthorizedUserTransformation.serializeBinaryToWriter
+    );
+  }
+};
+
+
+/**
+ * optional AuthorizedUserTransformation transformation = 1;
+ * @return {?proto.AuthorizedUserTransformation}
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated.prototype.getTransformation = function() {
+  return /** @type{?proto.AuthorizedUserTransformation} */ (
+    jspb.Message.getWrapperField(this, proto.AuthorizedUserTransformation, 1));
+};
+
+
+/**
+ * @param {?proto.AuthorizedUserTransformation|undefined} value
+ * @return {!proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated} returns this
+*/
+proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated.prototype.setTransformation = function(value) {
+  return jspb.Message.setWrapperField(this, 1, value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated} returns this
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated.prototype.clearTransformation = function() {
+  return this.setTransformation(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated.prototype.hasTransformation = function() {
+  return jspb.Message.getField(this, 1) != null;
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted.prototype.toObject = function(opt_includeInstance) {
+  return proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    oldUser: (f = msg.getOldUser()) && proto.KillSwitchAuthorizedUser.toObject(includeInstance, f)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted}
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted;
+  return proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted}
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = new proto.KillSwitchAuthorizedUser;
+      reader.readMessage(value,proto.KillSwitchAuthorizedUser.deserializeBinaryFromReader);
+      msg.setOldUser(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getOldUser();
+  if (f != null) {
+    writer.writeMessage(
+      1,
+      f,
+      proto.KillSwitchAuthorizedUser.serializeBinaryToWriter
+    );
+  }
+};
+
+
+/**
+ * optional KillSwitchAuthorizedUser old_user = 1;
+ * @return {?proto.KillSwitchAuthorizedUser}
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted.prototype.getOldUser = function() {
+  return /** @type{?proto.KillSwitchAuthorizedUser} */ (
+    jspb.Message.getWrapperField(this, proto.KillSwitchAuthorizedUser, 1));
+};
+
+
+/**
+ * @param {?proto.KillSwitchAuthorizedUser|undefined} value
+ * @return {!proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted} returns this
+*/
+proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted.prototype.setOldUser = function(value) {
+  return jspb.Message.setWrapperField(this, 1, value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted} returns this
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted.prototype.clearOldUser = function() {
+  return this.setOldUser(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted.prototype.hasOldUser = function() {
+  return jspb.Message.getField(this, 1) != null;
+};
+
+
+/**
+ * optional google.protobuf.Timestamp timestamp = 1;
+ * @return {?proto.google.protobuf.Timestamp}
+ */
+proto.KillSwitchAuditLogEntry.prototype.getTimestamp = function() {
+  return /** @type{?proto.google.protobuf.Timestamp} */ (
+    jspb.Message.getWrapperField(this, google_protobuf_timestamp_pb.Timestamp, 1));
+};
+
+
+/**
+ * @param {?proto.google.protobuf.Timestamp|undefined} value
+ * @return {!proto.KillSwitchAuditLogEntry} returns this
+*/
+proto.KillSwitchAuditLogEntry.prototype.setTimestamp = function(value) {
+  return jspb.Message.setWrapperField(this, 1, value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.KillSwitchAuditLogEntry} returns this
+ */
+proto.KillSwitchAuditLogEntry.prototype.clearTimestamp = function() {
+  return this.setTimestamp(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.KillSwitchAuditLogEntry.prototype.hasTimestamp = function() {
+  return jspb.Message.getField(this, 1) != null;
+};
+
+
+/**
+ * optional KillSwitchAuthorizedUser user = 2;
+ * @return {?proto.KillSwitchAuthorizedUser}
+ */
+proto.KillSwitchAuditLogEntry.prototype.getUser = function() {
+  return /** @type{?proto.KillSwitchAuthorizedUser} */ (
+    jspb.Message.getWrapperField(this, proto.KillSwitchAuthorizedUser, 2));
+};
+
+
+/**
+ * @param {?proto.KillSwitchAuthorizedUser|undefined} value
+ * @return {!proto.KillSwitchAuditLogEntry} returns this
+*/
+proto.KillSwitchAuditLogEntry.prototype.setUser = function(value) {
+  return jspb.Message.setWrapperField(this, 2, value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.KillSwitchAuditLogEntry} returns this
+ */
+proto.KillSwitchAuditLogEntry.prototype.clearUser = function() {
+  return this.setUser(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.KillSwitchAuditLogEntry.prototype.hasUser = function() {
+  return jspb.Message.getField(this, 2) != null;
+};
+
+
+/**
+ * optional KillSwitchEnabled kill_switch_enabled = 3;
+ * @return {?proto.KillSwitchAuditLogEntry.KillSwitchEnabled}
+ */
+proto.KillSwitchAuditLogEntry.prototype.getKillSwitchEnabled = function() {
+  return /** @type{?proto.KillSwitchAuditLogEntry.KillSwitchEnabled} */ (
+    jspb.Message.getWrapperField(this, proto.KillSwitchAuditLogEntry.KillSwitchEnabled, 3));
+};
+
+
+/**
+ * @param {?proto.KillSwitchAuditLogEntry.KillSwitchEnabled|undefined} value
+ * @return {!proto.KillSwitchAuditLogEntry} returns this
+*/
+proto.KillSwitchAuditLogEntry.prototype.setKillSwitchEnabled = function(value) {
+  return jspb.Message.setOneofWrapperField(this, 3, proto.KillSwitchAuditLogEntry.oneofGroups_[0], value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.KillSwitchAuditLogEntry} returns this
+ */
+proto.KillSwitchAuditLogEntry.prototype.clearKillSwitchEnabled = function() {
+  return this.setKillSwitchEnabled(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.KillSwitchAuditLogEntry.prototype.hasKillSwitchEnabled = function() {
+  return jspb.Message.getField(this, 3) != null;
+};
+
+
+/**
+ * optional KillSwitchDisabled kill_switch_disabled = 4;
+ * @return {?proto.KillSwitchAuditLogEntry.KillSwitchDisabled}
+ */
+proto.KillSwitchAuditLogEntry.prototype.getKillSwitchDisabled = function() {
+  return /** @type{?proto.KillSwitchAuditLogEntry.KillSwitchDisabled} */ (
+    jspb.Message.getWrapperField(this, proto.KillSwitchAuditLogEntry.KillSwitchDisabled, 4));
+};
+
+
+/**
+ * @param {?proto.KillSwitchAuditLogEntry.KillSwitchDisabled|undefined} value
+ * @return {!proto.KillSwitchAuditLogEntry} returns this
+*/
+proto.KillSwitchAuditLogEntry.prototype.setKillSwitchDisabled = function(value) {
+  return jspb.Message.setOneofWrapperField(this, 4, proto.KillSwitchAuditLogEntry.oneofGroups_[0], value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.KillSwitchAuditLogEntry} returns this
+ */
+proto.KillSwitchAuditLogEntry.prototype.clearKillSwitchDisabled = function() {
+  return this.setKillSwitchDisabled(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.KillSwitchAuditLogEntry.prototype.hasKillSwitchDisabled = function() {
+  return jspb.Message.getField(this, 4) != null;
+};
+
+
+/**
+ * optional AuthorizedUserAdded authorized_user_added = 5;
+ * @return {?proto.KillSwitchAuditLogEntry.AuthorizedUserAdded}
+ */
+proto.KillSwitchAuditLogEntry.prototype.getAuthorizedUserAdded = function() {
+  return /** @type{?proto.KillSwitchAuditLogEntry.AuthorizedUserAdded} */ (
+    jspb.Message.getWrapperField(this, proto.KillSwitchAuditLogEntry.AuthorizedUserAdded, 5));
+};
+
+
+/**
+ * @param {?proto.KillSwitchAuditLogEntry.AuthorizedUserAdded|undefined} value
+ * @return {!proto.KillSwitchAuditLogEntry} returns this
+*/
+proto.KillSwitchAuditLogEntry.prototype.setAuthorizedUserAdded = function(value) {
+  return jspb.Message.setOneofWrapperField(this, 5, proto.KillSwitchAuditLogEntry.oneofGroups_[0], value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.KillSwitchAuditLogEntry} returns this
+ */
+proto.KillSwitchAuditLogEntry.prototype.clearAuthorizedUserAdded = function() {
+  return this.setAuthorizedUserAdded(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.KillSwitchAuditLogEntry.prototype.hasAuthorizedUserAdded = function() {
+  return jspb.Message.getField(this, 5) != null;
+};
+
+
+/**
+ * optional AuthorizedUserUpdated authorized_user_updated = 6;
+ * @return {?proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated}
+ */
+proto.KillSwitchAuditLogEntry.prototype.getAuthorizedUserUpdated = function() {
+  return /** @type{?proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated} */ (
+    jspb.Message.getWrapperField(this, proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated, 6));
+};
+
+
+/**
+ * @param {?proto.KillSwitchAuditLogEntry.AuthorizedUserUpdated|undefined} value
+ * @return {!proto.KillSwitchAuditLogEntry} returns this
+*/
+proto.KillSwitchAuditLogEntry.prototype.setAuthorizedUserUpdated = function(value) {
+  return jspb.Message.setOneofWrapperField(this, 6, proto.KillSwitchAuditLogEntry.oneofGroups_[0], value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.KillSwitchAuditLogEntry} returns this
+ */
+proto.KillSwitchAuditLogEntry.prototype.clearAuthorizedUserUpdated = function() {
+  return this.setAuthorizedUserUpdated(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.KillSwitchAuditLogEntry.prototype.hasAuthorizedUserUpdated = function() {
+  return jspb.Message.getField(this, 6) != null;
+};
+
+
+/**
+ * optional AuthorizedUserDeleted authorized_user_deleted = 7;
+ * @return {?proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted}
+ */
+proto.KillSwitchAuditLogEntry.prototype.getAuthorizedUserDeleted = function() {
+  return /** @type{?proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted} */ (
+    jspb.Message.getWrapperField(this, proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted, 7));
+};
+
+
+/**
+ * @param {?proto.KillSwitchAuditLogEntry.AuthorizedUserDeleted|undefined} value
+ * @return {!proto.KillSwitchAuditLogEntry} returns this
+*/
+proto.KillSwitchAuditLogEntry.prototype.setAuthorizedUserDeleted = function(value) {
+  return jspb.Message.setOneofWrapperField(this, 7, proto.KillSwitchAuditLogEntry.oneofGroups_[0], value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.KillSwitchAuditLogEntry} returns this
+ */
+proto.KillSwitchAuditLogEntry.prototype.clearAuthorizedUserDeleted = function() {
+  return this.setAuthorizedUserDeleted(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.KillSwitchAuditLogEntry.prototype.hasAuthorizedUserDeleted = function() {
+  return jspb.Message.getField(this, 7) != null;
+};
+
+
+goog.object.extend(exports, proto);
diff --git a/frontend/src/api_proto/kill_switch_pb.js b/frontend/src/api_proto/kill_switch_pb.js
new file mode 100644
index 0000000..d9f9b6b
--- /dev/null
+++ b/frontend/src/api_proto/kill_switch_pb.js
@@ -0,0 +1,3094 @@
+// source: api_proto/kill_switch.proto
+/**
+ * @fileoverview
+ * @enhanceable
+ * @suppress {missingRequire} reports error on implicit type usages.
+ * @suppress {messageConventions} JS Compiler reports an error if a variable or
+ *     field starts with 'MSG_' and isn't a translatable message.
+ * @public
+ */
+// GENERATED CODE -- DO NOT EDIT!
+/* eslint-disable */
+// @ts-nocheck
+
+var jspb = require('google-protobuf');
+var goog = jspb;
+var global = Function('return this')();
+
+var api_proto_common_pb = require('../api_proto/common_pb.js');
+goog.object.extend(proto, api_proto_common_pb);
+var api_proto_kill_switch_objects_pb = require('../api_proto/kill_switch_objects_pb.js');
+goog.object.extend(proto, api_proto_kill_switch_objects_pb);
+goog.exportSymbol('proto.AddAuthorizedUserRequest', null, global);
+goog.exportSymbol('proto.AddAuthorizedUserResponse', null, global);
+goog.exportSymbol('proto.DeleteAuthorizedUserRequest', null, global);
+goog.exportSymbol('proto.DeleteAuthorizedUserResponse', null, global);
+goog.exportSymbol('proto.DisableKillSwitchRequest', null, global);
+goog.exportSymbol('proto.DisableKillSwitchResponse', null, global);
+goog.exportSymbol('proto.EnableKillSwitchRequest', null, global);
+goog.exportSymbol('proto.EnableKillSwitchResponse', null, global);
+goog.exportSymbol('proto.GetKillSwitchOverviewRequest', null, global);
+goog.exportSymbol('proto.GetKillSwitchOverviewResponse', null, global);
+goog.exportSymbol('proto.GetKillSwitchStatusRequest', null, global);
+goog.exportSymbol('proto.GetKillSwitchStatusResponse', null, global);
+goog.exportSymbol('proto.ListAuthorizedUsersRequest', null, global);
+goog.exportSymbol('proto.ListAuthorizedUsersResponse', null, global);
+goog.exportSymbol('proto.ListFeaturesRequest', null, global);
+goog.exportSymbol('proto.ListFeaturesResponse', null, global);
+goog.exportSymbol('proto.SyncFeaturesRequest', null, global);
+goog.exportSymbol('proto.SyncFeaturesResponse', null, global);
+goog.exportSymbol('proto.UpdateAuthorizedUserRequest', null, global);
+goog.exportSymbol('proto.UpdateAuthorizedUserResponse', null, global);
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.GetKillSwitchStatusRequest = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.GetKillSwitchStatusRequest, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.GetKillSwitchStatusRequest.displayName = 'proto.GetKillSwitchStatusRequest';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.GetKillSwitchStatusResponse = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, proto.GetKillSwitchStatusResponse.repeatedFields_, null);
+};
+goog.inherits(proto.GetKillSwitchStatusResponse, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.GetKillSwitchStatusResponse.displayName = 'proto.GetKillSwitchStatusResponse';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.GetKillSwitchOverviewRequest = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.GetKillSwitchOverviewRequest, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.GetKillSwitchOverviewRequest.displayName = 'proto.GetKillSwitchOverviewRequest';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.GetKillSwitchOverviewResponse = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, proto.GetKillSwitchOverviewResponse.repeatedFields_, null);
+};
+goog.inherits(proto.GetKillSwitchOverviewResponse, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.GetKillSwitchOverviewResponse.displayName = 'proto.GetKillSwitchOverviewResponse';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.ListFeaturesRequest = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.ListFeaturesRequest, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.ListFeaturesRequest.displayName = 'proto.ListFeaturesRequest';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.ListFeaturesResponse = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, proto.ListFeaturesResponse.repeatedFields_, null);
+};
+goog.inherits(proto.ListFeaturesResponse, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.ListFeaturesResponse.displayName = 'proto.ListFeaturesResponse';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.SyncFeaturesRequest = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, proto.SyncFeaturesRequest.repeatedFields_, null);
+};
+goog.inherits(proto.SyncFeaturesRequest, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.SyncFeaturesRequest.displayName = 'proto.SyncFeaturesRequest';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.SyncFeaturesResponse = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.SyncFeaturesResponse, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.SyncFeaturesResponse.displayName = 'proto.SyncFeaturesResponse';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.EnableKillSwitchRequest = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.EnableKillSwitchRequest, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.EnableKillSwitchRequest.displayName = 'proto.EnableKillSwitchRequest';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.EnableKillSwitchResponse = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.EnableKillSwitchResponse, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.EnableKillSwitchResponse.displayName = 'proto.EnableKillSwitchResponse';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.DisableKillSwitchRequest = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.DisableKillSwitchRequest, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.DisableKillSwitchRequest.displayName = 'proto.DisableKillSwitchRequest';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.DisableKillSwitchResponse = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.DisableKillSwitchResponse, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.DisableKillSwitchResponse.displayName = 'proto.DisableKillSwitchResponse';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.ListAuthorizedUsersRequest = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.ListAuthorizedUsersRequest, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.ListAuthorizedUsersRequest.displayName = 'proto.ListAuthorizedUsersRequest';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.ListAuthorizedUsersResponse = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, proto.ListAuthorizedUsersResponse.repeatedFields_, null);
+};
+goog.inherits(proto.ListAuthorizedUsersResponse, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.ListAuthorizedUsersResponse.displayName = 'proto.ListAuthorizedUsersResponse';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.AddAuthorizedUserRequest = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.AddAuthorizedUserRequest, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.AddAuthorizedUserRequest.displayName = 'proto.AddAuthorizedUserRequest';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.AddAuthorizedUserResponse = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.AddAuthorizedUserResponse, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.AddAuthorizedUserResponse.displayName = 'proto.AddAuthorizedUserResponse';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.UpdateAuthorizedUserRequest = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.UpdateAuthorizedUserRequest, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.UpdateAuthorizedUserRequest.displayName = 'proto.UpdateAuthorizedUserRequest';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.UpdateAuthorizedUserResponse = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.UpdateAuthorizedUserResponse, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.UpdateAuthorizedUserResponse.displayName = 'proto.UpdateAuthorizedUserResponse';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.DeleteAuthorizedUserRequest = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.DeleteAuthorizedUserRequest, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.DeleteAuthorizedUserRequest.displayName = 'proto.DeleteAuthorizedUserRequest';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.DeleteAuthorizedUserResponse = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.DeleteAuthorizedUserResponse, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.DeleteAuthorizedUserResponse.displayName = 'proto.DeleteAuthorizedUserResponse';
+}
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.GetKillSwitchStatusRequest.prototype.toObject = function(opt_includeInstance) {
+  return proto.GetKillSwitchStatusRequest.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.GetKillSwitchStatusRequest} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.GetKillSwitchStatusRequest.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    environment: (f = msg.getEnvironment()) && api_proto_common_pb.Environment.toObject(includeInstance, f)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.GetKillSwitchStatusRequest}
+ */
+proto.GetKillSwitchStatusRequest.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.GetKillSwitchStatusRequest;
+  return proto.GetKillSwitchStatusRequest.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.GetKillSwitchStatusRequest} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.GetKillSwitchStatusRequest}
+ */
+proto.GetKillSwitchStatusRequest.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = new api_proto_common_pb.Environment;
+      reader.readMessage(value,api_proto_common_pb.Environment.deserializeBinaryFromReader);
+      msg.setEnvironment(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.GetKillSwitchStatusRequest.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.GetKillSwitchStatusRequest.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.GetKillSwitchStatusRequest} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.GetKillSwitchStatusRequest.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getEnvironment();
+  if (f != null) {
+    writer.writeMessage(
+      1,
+      f,
+      api_proto_common_pb.Environment.serializeBinaryToWriter
+    );
+  }
+};
+
+
+/**
+ * optional Environment environment = 1;
+ * @return {?proto.Environment}
+ */
+proto.GetKillSwitchStatusRequest.prototype.getEnvironment = function() {
+  return /** @type{?proto.Environment} */ (
+    jspb.Message.getWrapperField(this, api_proto_common_pb.Environment, 1));
+};
+
+
+/**
+ * @param {?proto.Environment|undefined} value
+ * @return {!proto.GetKillSwitchStatusRequest} returns this
+*/
+proto.GetKillSwitchStatusRequest.prototype.setEnvironment = function(value) {
+  return jspb.Message.setWrapperField(this, 1, value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.GetKillSwitchStatusRequest} returns this
+ */
+proto.GetKillSwitchStatusRequest.prototype.clearEnvironment = function() {
+  return this.setEnvironment(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.GetKillSwitchStatusRequest.prototype.hasEnvironment = function() {
+  return jspb.Message.getField(this, 1) != null;
+};
+
+
+
+/**
+ * List of repeated fields within this message type.
+ * @private {!Array<number>}
+ * @const
+ */
+proto.GetKillSwitchStatusResponse.repeatedFields_ = [1];
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.GetKillSwitchStatusResponse.prototype.toObject = function(opt_includeInstance) {
+  return proto.GetKillSwitchStatusResponse.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.GetKillSwitchStatusResponse} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.GetKillSwitchStatusResponse.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    killSwitchesList: jspb.Message.toObjectList(msg.getKillSwitchesList(),
+    api_proto_kill_switch_objects_pb.KillSwitch.toObject, includeInstance)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.GetKillSwitchStatusResponse}
+ */
+proto.GetKillSwitchStatusResponse.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.GetKillSwitchStatusResponse;
+  return proto.GetKillSwitchStatusResponse.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.GetKillSwitchStatusResponse} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.GetKillSwitchStatusResponse}
+ */
+proto.GetKillSwitchStatusResponse.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = new api_proto_kill_switch_objects_pb.KillSwitch;
+      reader.readMessage(value,api_proto_kill_switch_objects_pb.KillSwitch.deserializeBinaryFromReader);
+      msg.addKillSwitches(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.GetKillSwitchStatusResponse.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.GetKillSwitchStatusResponse.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.GetKillSwitchStatusResponse} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.GetKillSwitchStatusResponse.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getKillSwitchesList();
+  if (f.length > 0) {
+    writer.writeRepeatedMessage(
+      1,
+      f,
+      api_proto_kill_switch_objects_pb.KillSwitch.serializeBinaryToWriter
+    );
+  }
+};
+
+
+/**
+ * repeated KillSwitch kill_switches = 1;
+ * @return {!Array<!proto.KillSwitch>}
+ */
+proto.GetKillSwitchStatusResponse.prototype.getKillSwitchesList = function() {
+  return /** @type{!Array<!proto.KillSwitch>} */ (
+    jspb.Message.getRepeatedWrapperField(this, api_proto_kill_switch_objects_pb.KillSwitch, 1));
+};
+
+
+/**
+ * @param {!Array<!proto.KillSwitch>} value
+ * @return {!proto.GetKillSwitchStatusResponse} returns this
+*/
+proto.GetKillSwitchStatusResponse.prototype.setKillSwitchesList = function(value) {
+  return jspb.Message.setRepeatedWrapperField(this, 1, value);
+};
+
+
+/**
+ * @param {!proto.KillSwitch=} opt_value
+ * @param {number=} opt_index
+ * @return {!proto.KillSwitch}
+ */
+proto.GetKillSwitchStatusResponse.prototype.addKillSwitches = function(opt_value, opt_index) {
+  return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.KillSwitch, opt_index);
+};
+
+
+/**
+ * Clears the list making it empty but non-null.
+ * @return {!proto.GetKillSwitchStatusResponse} returns this
+ */
+proto.GetKillSwitchStatusResponse.prototype.clearKillSwitchesList = function() {
+  return this.setKillSwitchesList([]);
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.GetKillSwitchOverviewRequest.prototype.toObject = function(opt_includeInstance) {
+  return proto.GetKillSwitchOverviewRequest.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.GetKillSwitchOverviewRequest} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.GetKillSwitchOverviewRequest.toObject = function(includeInstance, msg) {
+  var f, obj = {
+
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.GetKillSwitchOverviewRequest}
+ */
+proto.GetKillSwitchOverviewRequest.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.GetKillSwitchOverviewRequest;
+  return proto.GetKillSwitchOverviewRequest.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.GetKillSwitchOverviewRequest} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.GetKillSwitchOverviewRequest}
+ */
+proto.GetKillSwitchOverviewRequest.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.GetKillSwitchOverviewRequest.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.GetKillSwitchOverviewRequest.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.GetKillSwitchOverviewRequest} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.GetKillSwitchOverviewRequest.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+};
+
+
+
+/**
+ * List of repeated fields within this message type.
+ * @private {!Array<number>}
+ * @const
+ */
+proto.GetKillSwitchOverviewResponse.repeatedFields_ = [1];
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.GetKillSwitchOverviewResponse.prototype.toObject = function(opt_includeInstance) {
+  return proto.GetKillSwitchOverviewResponse.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.GetKillSwitchOverviewResponse} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.GetKillSwitchOverviewResponse.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    killSwitchesList: jspb.Message.toObjectList(msg.getKillSwitchesList(),
+    api_proto_kill_switch_objects_pb.KillSwitch.toObject, includeInstance)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.GetKillSwitchOverviewResponse}
+ */
+proto.GetKillSwitchOverviewResponse.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.GetKillSwitchOverviewResponse;
+  return proto.GetKillSwitchOverviewResponse.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.GetKillSwitchOverviewResponse} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.GetKillSwitchOverviewResponse}
+ */
+proto.GetKillSwitchOverviewResponse.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = new api_proto_kill_switch_objects_pb.KillSwitch;
+      reader.readMessage(value,api_proto_kill_switch_objects_pb.KillSwitch.deserializeBinaryFromReader);
+      msg.addKillSwitches(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.GetKillSwitchOverviewResponse.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.GetKillSwitchOverviewResponse.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.GetKillSwitchOverviewResponse} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.GetKillSwitchOverviewResponse.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getKillSwitchesList();
+  if (f.length > 0) {
+    writer.writeRepeatedMessage(
+      1,
+      f,
+      api_proto_kill_switch_objects_pb.KillSwitch.serializeBinaryToWriter
+    );
+  }
+};
+
+
+/**
+ * repeated KillSwitch kill_switches = 1;
+ * @return {!Array<!proto.KillSwitch>}
+ */
+proto.GetKillSwitchOverviewResponse.prototype.getKillSwitchesList = function() {
+  return /** @type{!Array<!proto.KillSwitch>} */ (
+    jspb.Message.getRepeatedWrapperField(this, api_proto_kill_switch_objects_pb.KillSwitch, 1));
+};
+
+
+/**
+ * @param {!Array<!proto.KillSwitch>} value
+ * @return {!proto.GetKillSwitchOverviewResponse} returns this
+*/
+proto.GetKillSwitchOverviewResponse.prototype.setKillSwitchesList = function(value) {
+  return jspb.Message.setRepeatedWrapperField(this, 1, value);
+};
+
+
+/**
+ * @param {!proto.KillSwitch=} opt_value
+ * @param {number=} opt_index
+ * @return {!proto.KillSwitch}
+ */
+proto.GetKillSwitchOverviewResponse.prototype.addKillSwitches = function(opt_value, opt_index) {
+  return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.KillSwitch, opt_index);
+};
+
+
+/**
+ * Clears the list making it empty but non-null.
+ * @return {!proto.GetKillSwitchOverviewResponse} returns this
+ */
+proto.GetKillSwitchOverviewResponse.prototype.clearKillSwitchesList = function() {
+  return this.setKillSwitchesList([]);
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.ListFeaturesRequest.prototype.toObject = function(opt_includeInstance) {
+  return proto.ListFeaturesRequest.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.ListFeaturesRequest} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.ListFeaturesRequest.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    withDeprecatedFeatures: jspb.Message.getBooleanFieldWithDefault(msg, 1, false)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.ListFeaturesRequest}
+ */
+proto.ListFeaturesRequest.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.ListFeaturesRequest;
+  return proto.ListFeaturesRequest.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.ListFeaturesRequest} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.ListFeaturesRequest}
+ */
+proto.ListFeaturesRequest.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {boolean} */ (reader.readBool());
+      msg.setWithDeprecatedFeatures(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.ListFeaturesRequest.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.ListFeaturesRequest.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.ListFeaturesRequest} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.ListFeaturesRequest.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getWithDeprecatedFeatures();
+  if (f) {
+    writer.writeBool(
+      1,
+      f
+    );
+  }
+};
+
+
+/**
+ * optional bool with_deprecated_features = 1;
+ * @return {boolean}
+ */
+proto.ListFeaturesRequest.prototype.getWithDeprecatedFeatures = function() {
+  return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 1, false));
+};
+
+
+/**
+ * @param {boolean} value
+ * @return {!proto.ListFeaturesRequest} returns this
+ */
+proto.ListFeaturesRequest.prototype.setWithDeprecatedFeatures = function(value) {
+  return jspb.Message.setProto3BooleanField(this, 1, value);
+};
+
+
+
+/**
+ * List of repeated fields within this message type.
+ * @private {!Array<number>}
+ * @const
+ */
+proto.ListFeaturesResponse.repeatedFields_ = [1];
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.ListFeaturesResponse.prototype.toObject = function(opt_includeInstance) {
+  return proto.ListFeaturesResponse.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.ListFeaturesResponse} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.ListFeaturesResponse.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    featuresList: jspb.Message.toObjectList(msg.getFeaturesList(),
+    api_proto_kill_switch_objects_pb.Feature.toObject, includeInstance)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.ListFeaturesResponse}
+ */
+proto.ListFeaturesResponse.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.ListFeaturesResponse;
+  return proto.ListFeaturesResponse.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.ListFeaturesResponse} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.ListFeaturesResponse}
+ */
+proto.ListFeaturesResponse.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = new api_proto_kill_switch_objects_pb.Feature;
+      reader.readMessage(value,api_proto_kill_switch_objects_pb.Feature.deserializeBinaryFromReader);
+      msg.addFeatures(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.ListFeaturesResponse.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.ListFeaturesResponse.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.ListFeaturesResponse} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.ListFeaturesResponse.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getFeaturesList();
+  if (f.length > 0) {
+    writer.writeRepeatedMessage(
+      1,
+      f,
+      api_proto_kill_switch_objects_pb.Feature.serializeBinaryToWriter
+    );
+  }
+};
+
+
+/**
+ * repeated Feature features = 1;
+ * @return {!Array<!proto.Feature>}
+ */
+proto.ListFeaturesResponse.prototype.getFeaturesList = function() {
+  return /** @type{!Array<!proto.Feature>} */ (
+    jspb.Message.getRepeatedWrapperField(this, api_proto_kill_switch_objects_pb.Feature, 1));
+};
+
+
+/**
+ * @param {!Array<!proto.Feature>} value
+ * @return {!proto.ListFeaturesResponse} returns this
+*/
+proto.ListFeaturesResponse.prototype.setFeaturesList = function(value) {
+  return jspb.Message.setRepeatedWrapperField(this, 1, value);
+};
+
+
+/**
+ * @param {!proto.Feature=} opt_value
+ * @param {number=} opt_index
+ * @return {!proto.Feature}
+ */
+proto.ListFeaturesResponse.prototype.addFeatures = function(opt_value, opt_index) {
+  return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.Feature, opt_index);
+};
+
+
+/**
+ * Clears the list making it empty but non-null.
+ * @return {!proto.ListFeaturesResponse} returns this
+ */
+proto.ListFeaturesResponse.prototype.clearFeaturesList = function() {
+  return this.setFeaturesList([]);
+};
+
+
+
+/**
+ * List of repeated fields within this message type.
+ * @private {!Array<number>}
+ * @const
+ */
+proto.SyncFeaturesRequest.repeatedFields_ = [1];
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.SyncFeaturesRequest.prototype.toObject = function(opt_includeInstance) {
+  return proto.SyncFeaturesRequest.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.SyncFeaturesRequest} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.SyncFeaturesRequest.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    featuresList: jspb.Message.toObjectList(msg.getFeaturesList(),
+    api_proto_kill_switch_objects_pb.Feature.toObject, includeInstance)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.SyncFeaturesRequest}
+ */
+proto.SyncFeaturesRequest.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.SyncFeaturesRequest;
+  return proto.SyncFeaturesRequest.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.SyncFeaturesRequest} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.SyncFeaturesRequest}
+ */
+proto.SyncFeaturesRequest.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = new api_proto_kill_switch_objects_pb.Feature;
+      reader.readMessage(value,api_proto_kill_switch_objects_pb.Feature.deserializeBinaryFromReader);
+      msg.addFeatures(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.SyncFeaturesRequest.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.SyncFeaturesRequest.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.SyncFeaturesRequest} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.SyncFeaturesRequest.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getFeaturesList();
+  if (f.length > 0) {
+    writer.writeRepeatedMessage(
+      1,
+      f,
+      api_proto_kill_switch_objects_pb.Feature.serializeBinaryToWriter
+    );
+  }
+};
+
+
+/**
+ * repeated Feature features = 1;
+ * @return {!Array<!proto.Feature>}
+ */
+proto.SyncFeaturesRequest.prototype.getFeaturesList = function() {
+  return /** @type{!Array<!proto.Feature>} */ (
+    jspb.Message.getRepeatedWrapperField(this, api_proto_kill_switch_objects_pb.Feature, 1));
+};
+
+
+/**
+ * @param {!Array<!proto.Feature>} value
+ * @return {!proto.SyncFeaturesRequest} returns this
+*/
+proto.SyncFeaturesRequest.prototype.setFeaturesList = function(value) {
+  return jspb.Message.setRepeatedWrapperField(this, 1, value);
+};
+
+
+/**
+ * @param {!proto.Feature=} opt_value
+ * @param {number=} opt_index
+ * @return {!proto.Feature}
+ */
+proto.SyncFeaturesRequest.prototype.addFeatures = function(opt_value, opt_index) {
+  return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.Feature, opt_index);
+};
+
+
+/**
+ * Clears the list making it empty but non-null.
+ * @return {!proto.SyncFeaturesRequest} returns this
+ */
+proto.SyncFeaturesRequest.prototype.clearFeaturesList = function() {
+  return this.setFeaturesList([]);
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.SyncFeaturesResponse.prototype.toObject = function(opt_includeInstance) {
+  return proto.SyncFeaturesResponse.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.SyncFeaturesResponse} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.SyncFeaturesResponse.toObject = function(includeInstance, msg) {
+  var f, obj = {
+
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.SyncFeaturesResponse}
+ */
+proto.SyncFeaturesResponse.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.SyncFeaturesResponse;
+  return proto.SyncFeaturesResponse.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.SyncFeaturesResponse} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.SyncFeaturesResponse}
+ */
+proto.SyncFeaturesResponse.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.SyncFeaturesResponse.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.SyncFeaturesResponse.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.SyncFeaturesResponse} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.SyncFeaturesResponse.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.EnableKillSwitchRequest.prototype.toObject = function(opt_includeInstance) {
+  return proto.EnableKillSwitchRequest.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.EnableKillSwitchRequest} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.EnableKillSwitchRequest.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    killSwitch: (f = msg.getKillSwitch()) && api_proto_kill_switch_objects_pb.KillSwitch.toObject(includeInstance, f)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.EnableKillSwitchRequest}
+ */
+proto.EnableKillSwitchRequest.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.EnableKillSwitchRequest;
+  return proto.EnableKillSwitchRequest.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.EnableKillSwitchRequest} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.EnableKillSwitchRequest}
+ */
+proto.EnableKillSwitchRequest.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = new api_proto_kill_switch_objects_pb.KillSwitch;
+      reader.readMessage(value,api_proto_kill_switch_objects_pb.KillSwitch.deserializeBinaryFromReader);
+      msg.setKillSwitch(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.EnableKillSwitchRequest.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.EnableKillSwitchRequest.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.EnableKillSwitchRequest} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.EnableKillSwitchRequest.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getKillSwitch();
+  if (f != null) {
+    writer.writeMessage(
+      1,
+      f,
+      api_proto_kill_switch_objects_pb.KillSwitch.serializeBinaryToWriter
+    );
+  }
+};
+
+
+/**
+ * optional KillSwitch kill_switch = 1;
+ * @return {?proto.KillSwitch}
+ */
+proto.EnableKillSwitchRequest.prototype.getKillSwitch = function() {
+  return /** @type{?proto.KillSwitch} */ (
+    jspb.Message.getWrapperField(this, api_proto_kill_switch_objects_pb.KillSwitch, 1));
+};
+
+
+/**
+ * @param {?proto.KillSwitch|undefined} value
+ * @return {!proto.EnableKillSwitchRequest} returns this
+*/
+proto.EnableKillSwitchRequest.prototype.setKillSwitch = function(value) {
+  return jspb.Message.setWrapperField(this, 1, value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.EnableKillSwitchRequest} returns this
+ */
+proto.EnableKillSwitchRequest.prototype.clearKillSwitch = function() {
+  return this.setKillSwitch(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.EnableKillSwitchRequest.prototype.hasKillSwitch = function() {
+  return jspb.Message.getField(this, 1) != null;
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.EnableKillSwitchResponse.prototype.toObject = function(opt_includeInstance) {
+  return proto.EnableKillSwitchResponse.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.EnableKillSwitchResponse} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.EnableKillSwitchResponse.toObject = function(includeInstance, msg) {
+  var f, obj = {
+
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.EnableKillSwitchResponse}
+ */
+proto.EnableKillSwitchResponse.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.EnableKillSwitchResponse;
+  return proto.EnableKillSwitchResponse.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.EnableKillSwitchResponse} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.EnableKillSwitchResponse}
+ */
+proto.EnableKillSwitchResponse.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.EnableKillSwitchResponse.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.EnableKillSwitchResponse.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.EnableKillSwitchResponse} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.EnableKillSwitchResponse.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.DisableKillSwitchRequest.prototype.toObject = function(opt_includeInstance) {
+  return proto.DisableKillSwitchRequest.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.DisableKillSwitchRequest} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.DisableKillSwitchRequest.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    killSwitchId: jspb.Message.getFieldWithDefault(msg, 1, 0)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.DisableKillSwitchRequest}
+ */
+proto.DisableKillSwitchRequest.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.DisableKillSwitchRequest;
+  return proto.DisableKillSwitchRequest.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.DisableKillSwitchRequest} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.DisableKillSwitchRequest}
+ */
+proto.DisableKillSwitchRequest.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {number} */ (reader.readInt32());
+      msg.setKillSwitchId(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.DisableKillSwitchRequest.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.DisableKillSwitchRequest.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.DisableKillSwitchRequest} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.DisableKillSwitchRequest.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getKillSwitchId();
+  if (f !== 0) {
+    writer.writeInt32(
+      1,
+      f
+    );
+  }
+};
+
+
+/**
+ * optional int32 kill_switch_id = 1;
+ * @return {number}
+ */
+proto.DisableKillSwitchRequest.prototype.getKillSwitchId = function() {
+  return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));
+};
+
+
+/**
+ * @param {number} value
+ * @return {!proto.DisableKillSwitchRequest} returns this
+ */
+proto.DisableKillSwitchRequest.prototype.setKillSwitchId = function(value) {
+  return jspb.Message.setProto3IntField(this, 1, value);
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.DisableKillSwitchResponse.prototype.toObject = function(opt_includeInstance) {
+  return proto.DisableKillSwitchResponse.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.DisableKillSwitchResponse} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.DisableKillSwitchResponse.toObject = function(includeInstance, msg) {
+  var f, obj = {
+
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.DisableKillSwitchResponse}
+ */
+proto.DisableKillSwitchResponse.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.DisableKillSwitchResponse;
+  return proto.DisableKillSwitchResponse.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.DisableKillSwitchResponse} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.DisableKillSwitchResponse}
+ */
+proto.DisableKillSwitchResponse.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.DisableKillSwitchResponse.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.DisableKillSwitchResponse.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.DisableKillSwitchResponse} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.DisableKillSwitchResponse.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.ListAuthorizedUsersRequest.prototype.toObject = function(opt_includeInstance) {
+  return proto.ListAuthorizedUsersRequest.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.ListAuthorizedUsersRequest} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.ListAuthorizedUsersRequest.toObject = function(includeInstance, msg) {
+  var f, obj = {
+
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.ListAuthorizedUsersRequest}
+ */
+proto.ListAuthorizedUsersRequest.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.ListAuthorizedUsersRequest;
+  return proto.ListAuthorizedUsersRequest.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.ListAuthorizedUsersRequest} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.ListAuthorizedUsersRequest}
+ */
+proto.ListAuthorizedUsersRequest.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.ListAuthorizedUsersRequest.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.ListAuthorizedUsersRequest.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.ListAuthorizedUsersRequest} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.ListAuthorizedUsersRequest.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+};
+
+
+
+/**
+ * List of repeated fields within this message type.
+ * @private {!Array<number>}
+ * @const
+ */
+proto.ListAuthorizedUsersResponse.repeatedFields_ = [1];
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.ListAuthorizedUsersResponse.prototype.toObject = function(opt_includeInstance) {
+  return proto.ListAuthorizedUsersResponse.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.ListAuthorizedUsersResponse} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.ListAuthorizedUsersResponse.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    usersList: jspb.Message.toObjectList(msg.getUsersList(),
+    api_proto_kill_switch_objects_pb.KillSwitchAuthorizedUser.toObject, includeInstance)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.ListAuthorizedUsersResponse}
+ */
+proto.ListAuthorizedUsersResponse.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.ListAuthorizedUsersResponse;
+  return proto.ListAuthorizedUsersResponse.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.ListAuthorizedUsersResponse} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.ListAuthorizedUsersResponse}
+ */
+proto.ListAuthorizedUsersResponse.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = new api_proto_kill_switch_objects_pb.KillSwitchAuthorizedUser;
+      reader.readMessage(value,api_proto_kill_switch_objects_pb.KillSwitchAuthorizedUser.deserializeBinaryFromReader);
+      msg.addUsers(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.ListAuthorizedUsersResponse.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.ListAuthorizedUsersResponse.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.ListAuthorizedUsersResponse} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.ListAuthorizedUsersResponse.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getUsersList();
+  if (f.length > 0) {
+    writer.writeRepeatedMessage(
+      1,
+      f,
+      api_proto_kill_switch_objects_pb.KillSwitchAuthorizedUser.serializeBinaryToWriter
+    );
+  }
+};
+
+
+/**
+ * repeated KillSwitchAuthorizedUser users = 1;
+ * @return {!Array<!proto.KillSwitchAuthorizedUser>}
+ */
+proto.ListAuthorizedUsersResponse.prototype.getUsersList = function() {
+  return /** @type{!Array<!proto.KillSwitchAuthorizedUser>} */ (
+    jspb.Message.getRepeatedWrapperField(this, api_proto_kill_switch_objects_pb.KillSwitchAuthorizedUser, 1));
+};
+
+
+/**
+ * @param {!Array<!proto.KillSwitchAuthorizedUser>} value
+ * @return {!proto.ListAuthorizedUsersResponse} returns this
+*/
+proto.ListAuthorizedUsersResponse.prototype.setUsersList = function(value) {
+  return jspb.Message.setRepeatedWrapperField(this, 1, value);
+};
+
+
+/**
+ * @param {!proto.KillSwitchAuthorizedUser=} opt_value
+ * @param {number=} opt_index
+ * @return {!proto.KillSwitchAuthorizedUser}
+ */
+proto.ListAuthorizedUsersResponse.prototype.addUsers = function(opt_value, opt_index) {
+  return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.KillSwitchAuthorizedUser, opt_index);
+};
+
+
+/**
+ * Clears the list making it empty but non-null.
+ * @return {!proto.ListAuthorizedUsersResponse} returns this
+ */
+proto.ListAuthorizedUsersResponse.prototype.clearUsersList = function() {
+  return this.setUsersList([]);
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.AddAuthorizedUserRequest.prototype.toObject = function(opt_includeInstance) {
+  return proto.AddAuthorizedUserRequest.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.AddAuthorizedUserRequest} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.AddAuthorizedUserRequest.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    user: (f = msg.getUser()) && api_proto_kill_switch_objects_pb.KillSwitchAuthorizedUser.toObject(includeInstance, f)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.AddAuthorizedUserRequest}
+ */
+proto.AddAuthorizedUserRequest.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.AddAuthorizedUserRequest;
+  return proto.AddAuthorizedUserRequest.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.AddAuthorizedUserRequest} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.AddAuthorizedUserRequest}
+ */
+proto.AddAuthorizedUserRequest.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = new api_proto_kill_switch_objects_pb.KillSwitchAuthorizedUser;
+      reader.readMessage(value,api_proto_kill_switch_objects_pb.KillSwitchAuthorizedUser.deserializeBinaryFromReader);
+      msg.setUser(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.AddAuthorizedUserRequest.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.AddAuthorizedUserRequest.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.AddAuthorizedUserRequest} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.AddAuthorizedUserRequest.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getUser();
+  if (f != null) {
+    writer.writeMessage(
+      1,
+      f,
+      api_proto_kill_switch_objects_pb.KillSwitchAuthorizedUser.serializeBinaryToWriter
+    );
+  }
+};
+
+
+/**
+ * optional KillSwitchAuthorizedUser user = 1;
+ * @return {?proto.KillSwitchAuthorizedUser}
+ */
+proto.AddAuthorizedUserRequest.prototype.getUser = function() {
+  return /** @type{?proto.KillSwitchAuthorizedUser} */ (
+    jspb.Message.getWrapperField(this, api_proto_kill_switch_objects_pb.KillSwitchAuthorizedUser, 1));
+};
+
+
+/**
+ * @param {?proto.KillSwitchAuthorizedUser|undefined} value
+ * @return {!proto.AddAuthorizedUserRequest} returns this
+*/
+proto.AddAuthorizedUserRequest.prototype.setUser = function(value) {
+  return jspb.Message.setWrapperField(this, 1, value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.AddAuthorizedUserRequest} returns this
+ */
+proto.AddAuthorizedUserRequest.prototype.clearUser = function() {
+  return this.setUser(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.AddAuthorizedUserRequest.prototype.hasUser = function() {
+  return jspb.Message.getField(this, 1) != null;
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.AddAuthorizedUserResponse.prototype.toObject = function(opt_includeInstance) {
+  return proto.AddAuthorizedUserResponse.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.AddAuthorizedUserResponse} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.AddAuthorizedUserResponse.toObject = function(includeInstance, msg) {
+  var f, obj = {
+
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.AddAuthorizedUserResponse}
+ */
+proto.AddAuthorizedUserResponse.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.AddAuthorizedUserResponse;
+  return proto.AddAuthorizedUserResponse.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.AddAuthorizedUserResponse} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.AddAuthorizedUserResponse}
+ */
+proto.AddAuthorizedUserResponse.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.AddAuthorizedUserResponse.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.AddAuthorizedUserResponse.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.AddAuthorizedUserResponse} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.AddAuthorizedUserResponse.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.UpdateAuthorizedUserRequest.prototype.toObject = function(opt_includeInstance) {
+  return proto.UpdateAuthorizedUserRequest.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.UpdateAuthorizedUserRequest} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.UpdateAuthorizedUserRequest.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    userId: jspb.Message.getFieldWithDefault(msg, 1, 0),
+    user: (f = msg.getUser()) && api_proto_kill_switch_objects_pb.KillSwitchAuthorizedUser.toObject(includeInstance, f)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.UpdateAuthorizedUserRequest}
+ */
+proto.UpdateAuthorizedUserRequest.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.UpdateAuthorizedUserRequest;
+  return proto.UpdateAuthorizedUserRequest.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.UpdateAuthorizedUserRequest} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.UpdateAuthorizedUserRequest}
+ */
+proto.UpdateAuthorizedUserRequest.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {number} */ (reader.readInt32());
+      msg.setUserId(value);
+      break;
+    case 2:
+      var value = new api_proto_kill_switch_objects_pb.KillSwitchAuthorizedUser;
+      reader.readMessage(value,api_proto_kill_switch_objects_pb.KillSwitchAuthorizedUser.deserializeBinaryFromReader);
+      msg.setUser(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.UpdateAuthorizedUserRequest.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.UpdateAuthorizedUserRequest.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.UpdateAuthorizedUserRequest} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.UpdateAuthorizedUserRequest.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getUserId();
+  if (f !== 0) {
+    writer.writeInt32(
+      1,
+      f
+    );
+  }
+  f = message.getUser();
+  if (f != null) {
+    writer.writeMessage(
+      2,
+      f,
+      api_proto_kill_switch_objects_pb.KillSwitchAuthorizedUser.serializeBinaryToWriter
+    );
+  }
+};
+
+
+/**
+ * optional int32 user_id = 1;
+ * @return {number}
+ */
+proto.UpdateAuthorizedUserRequest.prototype.getUserId = function() {
+  return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));
+};
+
+
+/**
+ * @param {number} value
+ * @return {!proto.UpdateAuthorizedUserRequest} returns this
+ */
+proto.UpdateAuthorizedUserRequest.prototype.setUserId = function(value) {
+  return jspb.Message.setProto3IntField(this, 1, value);
+};
+
+
+/**
+ * optional KillSwitchAuthorizedUser user = 2;
+ * @return {?proto.KillSwitchAuthorizedUser}
+ */
+proto.UpdateAuthorizedUserRequest.prototype.getUser = function() {
+  return /** @type{?proto.KillSwitchAuthorizedUser} */ (
+    jspb.Message.getWrapperField(this, api_proto_kill_switch_objects_pb.KillSwitchAuthorizedUser, 2));
+};
+
+
+/**
+ * @param {?proto.KillSwitchAuthorizedUser|undefined} value
+ * @return {!proto.UpdateAuthorizedUserRequest} returns this
+*/
+proto.UpdateAuthorizedUserRequest.prototype.setUser = function(value) {
+  return jspb.Message.setWrapperField(this, 2, value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.UpdateAuthorizedUserRequest} returns this
+ */
+proto.UpdateAuthorizedUserRequest.prototype.clearUser = function() {
+  return this.setUser(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.UpdateAuthorizedUserRequest.prototype.hasUser = function() {
+  return jspb.Message.getField(this, 2) != null;
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.UpdateAuthorizedUserResponse.prototype.toObject = function(opt_includeInstance) {
+  return proto.UpdateAuthorizedUserResponse.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.UpdateAuthorizedUserResponse} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.UpdateAuthorizedUserResponse.toObject = function(includeInstance, msg) {
+  var f, obj = {
+
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.UpdateAuthorizedUserResponse}
+ */
+proto.UpdateAuthorizedUserResponse.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.UpdateAuthorizedUserResponse;
+  return proto.UpdateAuthorizedUserResponse.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.UpdateAuthorizedUserResponse} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.UpdateAuthorizedUserResponse}
+ */
+proto.UpdateAuthorizedUserResponse.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.UpdateAuthorizedUserResponse.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.UpdateAuthorizedUserResponse.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.UpdateAuthorizedUserResponse} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.UpdateAuthorizedUserResponse.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.DeleteAuthorizedUserRequest.prototype.toObject = function(opt_includeInstance) {
+  return proto.DeleteAuthorizedUserRequest.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.DeleteAuthorizedUserRequest} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.DeleteAuthorizedUserRequest.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    userId: jspb.Message.getFieldWithDefault(msg, 1, 0)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.DeleteAuthorizedUserRequest}
+ */
+proto.DeleteAuthorizedUserRequest.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.DeleteAuthorizedUserRequest;
+  return proto.DeleteAuthorizedUserRequest.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.DeleteAuthorizedUserRequest} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.DeleteAuthorizedUserRequest}
+ */
+proto.DeleteAuthorizedUserRequest.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {number} */ (reader.readInt32());
+      msg.setUserId(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.DeleteAuthorizedUserRequest.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.DeleteAuthorizedUserRequest.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.DeleteAuthorizedUserRequest} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.DeleteAuthorizedUserRequest.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getUserId();
+  if (f !== 0) {
+    writer.writeInt32(
+      1,
+      f
+    );
+  }
+};
+
+
+/**
+ * optional int32 user_id = 1;
+ * @return {number}
+ */
+proto.DeleteAuthorizedUserRequest.prototype.getUserId = function() {
+  return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));
+};
+
+
+/**
+ * @param {number} value
+ * @return {!proto.DeleteAuthorizedUserRequest} returns this
+ */
+proto.DeleteAuthorizedUserRequest.prototype.setUserId = function(value) {
+  return jspb.Message.setProto3IntField(this, 1, value);
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.DeleteAuthorizedUserResponse.prototype.toObject = function(opt_includeInstance) {
+  return proto.DeleteAuthorizedUserResponse.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.DeleteAuthorizedUserResponse} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.DeleteAuthorizedUserResponse.toObject = function(includeInstance, msg) {
+  var f, obj = {
+
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.DeleteAuthorizedUserResponse}
+ */
+proto.DeleteAuthorizedUserResponse.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.DeleteAuthorizedUserResponse;
+  return proto.DeleteAuthorizedUserResponse.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.DeleteAuthorizedUserResponse} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.DeleteAuthorizedUserResponse}
+ */
+proto.DeleteAuthorizedUserResponse.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.DeleteAuthorizedUserResponse.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.DeleteAuthorizedUserResponse.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.DeleteAuthorizedUserResponse} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.DeleteAuthorizedUserResponse.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+};
+
+
+goog.object.extend(exports, proto);
