feat(client): reloadAuth() wrapper
Some checks failed
Security / Security check (push) Failing after 1s
Some checks failed
Security / Security check (push) Failing after 1s
Studio + pilot apps can now trigger a hub-side TokenStore swap without restarting the daemon: await client.reloadAuth(); // returns new token count Throws when the new config is invalid; the existing store stays in place server-side so a botched rotation can't lock the operator out. Bindings regenerated for the new HubAdmin.ReloadAuth + ReloadAuthResponse + LoggedEvent .caller_name proto additions. dart analyze clean; dart test green (4 tests). Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
parent
023adcec31
commit
db13bdb4a7
5 changed files with 137 additions and 2 deletions
|
|
@ -1056,6 +1056,7 @@ class LoggedEvent extends $pb.GeneratedMessage {
|
||||||
$fixnum.Int64? durationMs,
|
$fixnum.Int64? durationMs,
|
||||||
$core.String? error,
|
$core.String? error,
|
||||||
$core.String? detail,
|
$core.String? detail,
|
||||||
|
$core.String? callerName,
|
||||||
}) {
|
}) {
|
||||||
final result = create();
|
final result = create();
|
||||||
if (eventId != null) result.eventId = eventId;
|
if (eventId != null) result.eventId = eventId;
|
||||||
|
|
@ -1070,6 +1071,7 @@ class LoggedEvent extends $pb.GeneratedMessage {
|
||||||
if (durationMs != null) result.durationMs = durationMs;
|
if (durationMs != null) result.durationMs = durationMs;
|
||||||
if (error != null) result.error = error;
|
if (error != null) result.error = error;
|
||||||
if (detail != null) result.detail = detail;
|
if (detail != null) result.detail = detail;
|
||||||
|
if (callerName != null) result.callerName = callerName;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1098,6 +1100,7 @@ class LoggedEvent extends $pb.GeneratedMessage {
|
||||||
..aInt64(10, _omitFieldNames ? '' : 'durationMs')
|
..aInt64(10, _omitFieldNames ? '' : 'durationMs')
|
||||||
..aOS(11, _omitFieldNames ? '' : 'error')
|
..aOS(11, _omitFieldNames ? '' : 'error')
|
||||||
..aOS(12, _omitFieldNames ? '' : 'detail')
|
..aOS(12, _omitFieldNames ? '' : 'detail')
|
||||||
|
..aOS(13, _omitFieldNames ? '' : 'callerName')
|
||||||
..hasRequiredFields = false;
|
..hasRequiredFields = false;
|
||||||
|
|
||||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
|
|
@ -1230,6 +1233,21 @@ class LoggedEvent extends $pb.GeneratedMessage {
|
||||||
$core.bool hasDetail() => $_has(11);
|
$core.bool hasDetail() => $_has(11);
|
||||||
@$pb.TagNumber(12)
|
@$pb.TagNumber(12)
|
||||||
void clearDetail() => $_clearField(12);
|
void clearDetail() => $_clearField(12);
|
||||||
|
|
||||||
|
/// Operator-friendly name of the token whose holder
|
||||||
|
/// triggered this event. Empty when the call was anonymous
|
||||||
|
/// (auth.tokens: not configured), when the event was emitted
|
||||||
|
/// by hub-internal code (boot housekeeping, federation
|
||||||
|
/// discovery), or when the row pre-dates the audit-
|
||||||
|
/// attribution migration (0006).
|
||||||
|
@$pb.TagNumber(13)
|
||||||
|
$core.String get callerName => $_getSZ(12);
|
||||||
|
@$pb.TagNumber(13)
|
||||||
|
set callerName($core.String value) => $_setString(12, value);
|
||||||
|
@$pb.TagNumber(13)
|
||||||
|
$core.bool hasCallerName() => $_has(12);
|
||||||
|
@$pb.TagNumber(13)
|
||||||
|
void clearCallerName() => $_clearField(13);
|
||||||
}
|
}
|
||||||
|
|
||||||
class SaveFlowRequest extends $pb.GeneratedMessage {
|
class SaveFlowRequest extends $pb.GeneratedMessage {
|
||||||
|
|
@ -5967,6 +5985,63 @@ class DefaultScopeResponse extends $pb.GeneratedMessage {
|
||||||
$pb.PbList<$core.String> get knownProviders => $_getList(1);
|
$pb.PbList<$core.String> get knownProviders => $_getList(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ReloadAuthResponse extends $pb.GeneratedMessage {
|
||||||
|
factory ReloadAuthResponse({
|
||||||
|
$core.int? tokenCount,
|
||||||
|
}) {
|
||||||
|
final result = create();
|
||||||
|
if (tokenCount != null) result.tokenCount = tokenCount;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReloadAuthResponse._();
|
||||||
|
|
||||||
|
factory ReloadAuthResponse.fromBuffer($core.List<$core.int> data,
|
||||||
|
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||||
|
create()..mergeFromBuffer(data, registry);
|
||||||
|
factory ReloadAuthResponse.fromJson($core.String json,
|
||||||
|
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||||
|
create()..mergeFromJson(json, registry);
|
||||||
|
|
||||||
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
||||||
|
_omitMessageNames ? '' : 'ReloadAuthResponse',
|
||||||
|
package: const $pb.PackageName(_omitMessageNames ? '' : 'fai.v1'),
|
||||||
|
createEmptyInstance: create)
|
||||||
|
..aI(1, _omitFieldNames ? '' : 'tokenCount', fieldType: $pb.PbFieldType.OU3)
|
||||||
|
..hasRequiredFields = false;
|
||||||
|
|
||||||
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
|
ReloadAuthResponse clone() => deepCopy();
|
||||||
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
|
ReloadAuthResponse copyWith(void Function(ReloadAuthResponse) updates) =>
|
||||||
|
super.copyWith((message) => updates(message as ReloadAuthResponse))
|
||||||
|
as ReloadAuthResponse;
|
||||||
|
|
||||||
|
@$core.override
|
||||||
|
$pb.BuilderInfo get info_ => _i;
|
||||||
|
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static ReloadAuthResponse create() => ReloadAuthResponse._();
|
||||||
|
@$core.override
|
||||||
|
ReloadAuthResponse createEmptyInstance() => create();
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static ReloadAuthResponse getDefault() => _defaultInstance ??=
|
||||||
|
$pb.GeneratedMessage.$_defaultFor<ReloadAuthResponse>(create);
|
||||||
|
static ReloadAuthResponse? _defaultInstance;
|
||||||
|
|
||||||
|
/// Number of tokens loaded into the live store after the
|
||||||
|
/// swap. Operators sanity-check this against the number
|
||||||
|
/// they expected to have in `auth.tokens:`.
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$core.int get tokenCount => $_getIZ(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
set tokenCount($core.int value) => $_setUnsignedInt32(0, value);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$core.bool hasTokenCount() => $_has(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
void clearTokenCount() => $_clearField(1);
|
||||||
|
}
|
||||||
|
|
||||||
class McpClientConfigEntry extends $pb.GeneratedMessage {
|
class McpClientConfigEntry extends $pb.GeneratedMessage {
|
||||||
factory McpClientConfigEntry({
|
factory McpClientConfigEntry({
|
||||||
$core.String? name,
|
$core.String? name,
|
||||||
|
|
|
||||||
|
|
@ -378,6 +378,20 @@ class HubAdminClient extends $grpc.Client {
|
||||||
return $createUnaryCall(_$setDefaultScope, request, options: options);
|
return $createUnaryCall(_$setDefaultScope, request, options: options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Re-read `auth.tokens:` from operator config + env vars and
|
||||||
|
/// atomically swap the live token store. Used by operators to
|
||||||
|
/// rotate tokens without restarting the daemon. Returns the
|
||||||
|
/// new token count. Errors if the new config is invalid (env
|
||||||
|
/// var missing, duplicate secret, no scopes, …) — the
|
||||||
|
/// existing store stays in place so a botched rotation can't
|
||||||
|
/// lock the operator out.
|
||||||
|
$grpc.ResponseFuture<$0.ReloadAuthResponse> reloadAuth(
|
||||||
|
$1.Empty request, {
|
||||||
|
$grpc.CallOptions? options,
|
||||||
|
}) {
|
||||||
|
return $createUnaryCall(_$reloadAuth, request, options: options);
|
||||||
|
}
|
||||||
|
|
||||||
/// List host services declared in the operator config. Each
|
/// List host services declared in the operator config. Each
|
||||||
/// entry carries name + endpoint; reachability is operator-side
|
/// entry carries name + endpoint; reachability is operator-side
|
||||||
/// (on-demand `fai service status` or Studio probe).
|
/// (on-demand `fai service status` or Studio probe).
|
||||||
|
|
@ -721,6 +735,11 @@ class HubAdminClient extends $grpc.Client {
|
||||||
'/fai.v1.HubAdmin/SetDefaultScope',
|
'/fai.v1.HubAdmin/SetDefaultScope',
|
||||||
($0.SetDefaultScopeRequest value) => value.writeToBuffer(),
|
($0.SetDefaultScopeRequest value) => value.writeToBuffer(),
|
||||||
$0.DefaultScopeResponse.fromBuffer);
|
$0.DefaultScopeResponse.fromBuffer);
|
||||||
|
static final _$reloadAuth =
|
||||||
|
$grpc.ClientMethod<$1.Empty, $0.ReloadAuthResponse>(
|
||||||
|
'/fai.v1.HubAdmin/ReloadAuth',
|
||||||
|
($1.Empty value) => value.writeToBuffer(),
|
||||||
|
$0.ReloadAuthResponse.fromBuffer);
|
||||||
static final _$listServices = $grpc.ClientMethod<$1.Empty, $0.ServiceList>(
|
static final _$listServices = $grpc.ClientMethod<$1.Empty, $0.ServiceList>(
|
||||||
'/fai.v1.HubAdmin/ListServices',
|
'/fai.v1.HubAdmin/ListServices',
|
||||||
($1.Empty value) => value.writeToBuffer(),
|
($1.Empty value) => value.writeToBuffer(),
|
||||||
|
|
@ -1024,6 +1043,13 @@ abstract class HubAdminServiceBase extends $grpc.Service {
|
||||||
($core.List<$core.int> value) =>
|
($core.List<$core.int> value) =>
|
||||||
$0.SetDefaultScopeRequest.fromBuffer(value),
|
$0.SetDefaultScopeRequest.fromBuffer(value),
|
||||||
($0.DefaultScopeResponse value) => value.writeToBuffer()));
|
($0.DefaultScopeResponse value) => value.writeToBuffer()));
|
||||||
|
$addMethod($grpc.ServiceMethod<$1.Empty, $0.ReloadAuthResponse>(
|
||||||
|
'ReloadAuth',
|
||||||
|
reloadAuth_Pre,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
($core.List<$core.int> value) => $1.Empty.fromBuffer(value),
|
||||||
|
($0.ReloadAuthResponse value) => value.writeToBuffer()));
|
||||||
$addMethod($grpc.ServiceMethod<$1.Empty, $0.ServiceList>(
|
$addMethod($grpc.ServiceMethod<$1.Empty, $0.ServiceList>(
|
||||||
'ListServices',
|
'ListServices',
|
||||||
listServices_Pre,
|
listServices_Pre,
|
||||||
|
|
@ -1392,6 +1418,14 @@ abstract class HubAdminServiceBase extends $grpc.Service {
|
||||||
$async.Future<$0.DefaultScopeResponse> setDefaultScope(
|
$async.Future<$0.DefaultScopeResponse> setDefaultScope(
|
||||||
$grpc.ServiceCall call, $0.SetDefaultScopeRequest request);
|
$grpc.ServiceCall call, $0.SetDefaultScopeRequest request);
|
||||||
|
|
||||||
|
$async.Future<$0.ReloadAuthResponse> reloadAuth_Pre(
|
||||||
|
$grpc.ServiceCall $call, $async.Future<$1.Empty> $request) async {
|
||||||
|
return reloadAuth($call, await $request);
|
||||||
|
}
|
||||||
|
|
||||||
|
$async.Future<$0.ReloadAuthResponse> reloadAuth(
|
||||||
|
$grpc.ServiceCall call, $1.Empty request);
|
||||||
|
|
||||||
$async.Future<$0.ServiceList> listServices_Pre(
|
$async.Future<$0.ServiceList> listServices_Pre(
|
||||||
$grpc.ServiceCall $call, $async.Future<$1.Empty> $request) async {
|
$grpc.ServiceCall $call, $async.Future<$1.Empty> $request) async {
|
||||||
return listServices($call, await $request);
|
return listServices($call, await $request);
|
||||||
|
|
|
||||||
|
|
@ -356,6 +356,7 @@ const LoggedEvent$json = {
|
||||||
{'1': 'duration_ms', '3': 10, '4': 1, '5': 3, '10': 'durationMs'},
|
{'1': 'duration_ms', '3': 10, '4': 1, '5': 3, '10': 'durationMs'},
|
||||||
{'1': 'error', '3': 11, '4': 1, '5': 9, '10': 'error'},
|
{'1': 'error', '3': 11, '4': 1, '5': 9, '10': 'error'},
|
||||||
{'1': 'detail', '3': 12, '4': 1, '5': 9, '10': 'detail'},
|
{'1': 'detail', '3': 12, '4': 1, '5': 9, '10': 'detail'},
|
||||||
|
{'1': 'caller_name', '3': 13, '4': 1, '5': 9, '10': 'callerName'},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -367,7 +368,8 @@ final $typed_data.Uint8List loggedEventDescriptor = $convert.base64Decode(
|
||||||
'52b2NhdGlvbklkEhsKCWZsb3dfbmFtZRgGIAEoCVIIZmxvd05hbWUSFwoHc3RlcF9pZBgHIAEo'
|
'52b2NhdGlvbklkEhsKCWZsb3dfbmFtZRgGIAEoCVIIZmxvd05hbWUSFwoHc3RlcF9pZBgHIAEo'
|
||||||
'CVIGc3RlcElkEh8KC21vZHVsZV9uYW1lGAggASgJUgptb2R1bGVOYW1lEiUKDm1vZHVsZV92ZX'
|
'CVIGc3RlcElkEh8KC21vZHVsZV9uYW1lGAggASgJUgptb2R1bGVOYW1lEiUKDm1vZHVsZV92ZX'
|
||||||
'JzaW9uGAkgASgJUg1tb2R1bGVWZXJzaW9uEh8KC2R1cmF0aW9uX21zGAogASgDUgpkdXJhdGlv'
|
'JzaW9uGAkgASgJUg1tb2R1bGVWZXJzaW9uEh8KC2R1cmF0aW9uX21zGAogASgDUgpkdXJhdGlv'
|
||||||
'bk1zEhQKBWVycm9yGAsgASgJUgVlcnJvchIWCgZkZXRhaWwYDCABKAlSBmRldGFpbA==');
|
'bk1zEhQKBWVycm9yGAsgASgJUgVlcnJvchIWCgZkZXRhaWwYDCABKAlSBmRldGFpbBIfCgtjYW'
|
||||||
|
'xsZXJfbmFtZRgNIAEoCVIKY2FsbGVyTmFtZQ==');
|
||||||
|
|
||||||
@$core.Deprecated('Use saveFlowRequestDescriptor instead')
|
@$core.Deprecated('Use saveFlowRequestDescriptor instead')
|
||||||
const SaveFlowRequest$json = {
|
const SaveFlowRequest$json = {
|
||||||
|
|
@ -1391,6 +1393,18 @@ final $typed_data.Uint8List defaultScopeResponseDescriptor = $convert.base64Deco
|
||||||
'ChREZWZhdWx0U2NvcGVSZXNwb25zZRIUCgVzY29wZRgBIAMoCVIFc2NvcGUSJwoPa25vd25fcH'
|
'ChREZWZhdWx0U2NvcGVSZXNwb25zZRIUCgVzY29wZRgBIAMoCVIFc2NvcGUSJwoPa25vd25fcH'
|
||||||
'JvdmlkZXJzGAIgAygJUg5rbm93blByb3ZpZGVycw==');
|
'JvdmlkZXJzGAIgAygJUg5rbm93blByb3ZpZGVycw==');
|
||||||
|
|
||||||
|
@$core.Deprecated('Use reloadAuthResponseDescriptor instead')
|
||||||
|
const ReloadAuthResponse$json = {
|
||||||
|
'1': 'ReloadAuthResponse',
|
||||||
|
'2': [
|
||||||
|
{'1': 'token_count', '3': 1, '4': 1, '5': 13, '10': 'tokenCount'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Descriptor for `ReloadAuthResponse`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
|
final $typed_data.Uint8List reloadAuthResponseDescriptor = $convert.base64Decode(
|
||||||
|
'ChJSZWxvYWRBdXRoUmVzcG9uc2USHwoLdG9rZW5fY291bnQYASABKA1SCnRva2VuQ291bnQ=');
|
||||||
|
|
||||||
@$core.Deprecated('Use mcpClientConfigEntryDescriptor instead')
|
@$core.Deprecated('Use mcpClientConfigEntryDescriptor instead')
|
||||||
const McpClientConfigEntry$json = {
|
const McpClientConfigEntry$json = {
|
||||||
'1': 'McpClientConfigEntry',
|
'1': 'McpClientConfigEntry',
|
||||||
|
|
|
||||||
|
|
@ -188,6 +188,18 @@ class HubClient {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Re-read `auth.tokens:` from operator config + env vars
|
||||||
|
/// and atomically swap the hub's live token store. Used by
|
||||||
|
/// operators to rotate tokens without restarting the daemon.
|
||||||
|
/// Returns the new token count after the swap. Throws when
|
||||||
|
/// the new config is invalid; the existing store stays in
|
||||||
|
/// place in that case so a botched rotation can't lock the
|
||||||
|
/// operator out.
|
||||||
|
Future<int> reloadAuth() async {
|
||||||
|
final r = await _admin.reloadAuth(Empty());
|
||||||
|
return r.tokenCount;
|
||||||
|
}
|
||||||
|
|
||||||
/// Server-streaming audit-log subscription. The hub first
|
/// Server-streaming audit-log subscription. The hub first
|
||||||
/// replays up to [backfill] historical events (oldest-last so
|
/// replays up to [backfill] historical events (oldest-last so
|
||||||
/// the receiver sees them in chronological order), then keeps
|
/// the receiver sees them in chronological order), then keeps
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
name: fai_client_sdk
|
name: fai_client_sdk
|
||||||
description: gRPC client SDK for the F∆I Platform hub. Used by F∆I Studio and Tier-3 domain apps.
|
description: gRPC client SDK for the F∆I Platform hub. Used by F∆I Studio and Tier-3 domain apps.
|
||||||
version: 0.17.0
|
version: 0.17.1
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
repository: https://git.flemming.ai/fai/client-sdk-dart
|
repository: https://git.flemming.ai/fai/client-sdk-dart
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue