feat: expose reload_required in AuthStatus; destale ~/.fai doc comments
Some checks failed
Security / Security check (push) Failing after 2s

Stubs regenerated from the current proto: AuthStatusResponse gains
reload_required (true when the hub's on-disk auth config or its env
vars diverge from the live validator — ReloadAuth pending), and the
generated comments pick up the .chain bundle wording. Hand-written
dartdoc in hub_client.dart updated from the pre-rename ~/.fai paths
and .fai bundle extension.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-07-15 05:39:22 +02:00
parent ec3b684e6e
commit 3381cb1728
4 changed files with 37 additions and 14 deletions

View file

@ -1380,7 +1380,7 @@ class CapabilityEntry extends $pb.GeneratedMessage {
/// distinction) `source_kind` records HOW the Hub reaches /// distinction) `source_kind` records HOW the Hub reaches
/// the implementation. Studio renders this as a badge next to /// the implementation. Studio renders this as a badge next to
/// the capability name. /// the capability name.
/// "bundle" installed .fai WASM bundle /// "bundle" installed .chain WASM bundle
/// "system" Hub built-in (fai.system/*) /// "system" Hub built-in (fai.system/*)
/// "mcp" federated via an MCP service /// "mcp" federated via an MCP service
/// "n8n" federated via an n8n endpoint /// "n8n" federated via an n8n endpoint
@ -3428,7 +3428,7 @@ class InstallModuleRequest extends $pb.GeneratedMessage {
$pb.GeneratedMessage.$_defaultFor<InstallModuleRequest>(create); $pb.GeneratedMessage.$_defaultFor<InstallModuleRequest>(create);
static InstallModuleRequest? _defaultInstance; static InstallModuleRequest? _defaultInstance;
/// Local path or http(s) URL of the .fai bundle, OR a /// Local path or http(s) URL of the .chain bundle, OR a
/// capability name (e.g. "text.extract") resolved via the /// capability name (e.g. "text.extract") resolved via the
/// store index. /// store index.
@$pb.TagNumber(1) @$pb.TagNumber(1)
@ -5326,7 +5326,7 @@ class StoreEntry extends $pb.GeneratedMessage {
/// from `kind` (native-vs-federated) `source_kind` says /// from `kind` (native-vs-federated) `source_kind` says
/// HOW the Hub reaches the implementation. Values mirror /// HOW the Hub reaches the implementation. Values mirror
/// `CapabilityEntry.source_kind`: /// `CapabilityEntry.source_kind`:
/// "bundle" installed .fai WASM bundle (native entries) /// "bundle" installed .chain WASM bundle (native entries)
/// "mcp" federated via an MCP service /// "mcp" federated via an MCP service
/// "n8n" federated via an n8n endpoint /// "n8n" federated via an n8n endpoint
/// "temporal" federated via a Temporal service (e.g. SPARK) /// "temporal" federated via a Temporal service (e.g. SPARK)
@ -7414,12 +7414,14 @@ class AuthStatusResponse extends $pb.GeneratedMessage {
$core.bool? anonymousAllowed, $core.bool? anonymousAllowed,
$core.Iterable<AuthTokenInfo>? tokens, $core.Iterable<AuthTokenInfo>? tokens,
JwtValidatorInfo? jwt, JwtValidatorInfo? jwt,
$core.bool? reloadRequired,
}) { }) {
final result = create(); final result = create();
if (validator != null) result.validator = validator; if (validator != null) result.validator = validator;
if (anonymousAllowed != null) result.anonymousAllowed = anonymousAllowed; if (anonymousAllowed != null) result.anonymousAllowed = anonymousAllowed;
if (tokens != null) result.tokens.addAll(tokens); if (tokens != null) result.tokens.addAll(tokens);
if (jwt != null) result.jwt = jwt; if (jwt != null) result.jwt = jwt;
if (reloadRequired != null) result.reloadRequired = reloadRequired;
return result; return result;
} }
@ -7442,6 +7444,7 @@ class AuthStatusResponse extends $pb.GeneratedMessage {
subBuilder: AuthTokenInfo.create) subBuilder: AuthTokenInfo.create)
..aOM<JwtValidatorInfo>(4, _omitFieldNames ? '' : 'jwt', ..aOM<JwtValidatorInfo>(4, _omitFieldNames ? '' : 'jwt',
subBuilder: JwtValidatorInfo.create) subBuilder: JwtValidatorInfo.create)
..aOB(5, _omitFieldNames ? '' : 'reloadRequired')
..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.')
@ -7463,7 +7466,8 @@ class AuthStatusResponse extends $pb.GeneratedMessage {
$pb.GeneratedMessage.$_defaultFor<AuthStatusResponse>(create); $pb.GeneratedMessage.$_defaultFor<AuthStatusResponse>(create);
static AuthStatusResponse? _defaultInstance; static AuthStatusResponse? _defaultInstance;
/// Active validator kind: "static" or "jwt-rs256". /// Validator kind in the on-disk operator config: "static" or
/// "jwt-rs256".
@$pb.TagNumber(1) @$pb.TagNumber(1)
$core.String get validator => $_getSZ(0); $core.String get validator => $_getSZ(0);
@$pb.TagNumber(1) @$pb.TagNumber(1)
@ -7473,8 +7477,11 @@ class AuthStatusResponse extends $pb.GeneratedMessage {
@$pb.TagNumber(1) @$pb.TagNumber(1)
void clearValidator() => $_clearField(1); void clearValidator() => $_clearField(1);
/// True when the hub accepts anonymous calls (static validator /// True when the hub CURRENTLY accepts anonymous calls computed
/// with an empty `auth.tokens:` list the local-dev default). /// from the live validator, not the on-disk config (the two differ
/// until `ReloadAuth` picks up a config edit; see reload_required).
/// Anonymous mode is the static validator with an empty
/// `auth.tokens:` list the local-dev default.
@$pb.TagNumber(2) @$pb.TagNumber(2)
$core.bool get anonymousAllowed => $_getBF(1); $core.bool get anonymousAllowed => $_getBF(1);
@$pb.TagNumber(2) @$pb.TagNumber(2)
@ -7499,6 +7506,20 @@ class AuthStatusResponse extends $pb.GeneratedMessage {
void clearJwt() => $_clearField(4); void clearJwt() => $_clearField(4);
@$pb.TagNumber(4) @$pb.TagNumber(4)
JwtValidatorInfo ensureJwt() => $_ensure(3); JwtValidatorInfo ensureJwt() => $_ensure(3);
/// True when the on-disk auth config (or the env vars it
/// references) no longer produces the validator the hub is
/// enforcing the operator edited config.yaml or rotated a
/// secret and still needs `ReloadAuth` (or a restart). Also true
/// when the on-disk config is currently invalid.
@$pb.TagNumber(5)
$core.bool get reloadRequired => $_getBF(4);
@$pb.TagNumber(5)
set reloadRequired($core.bool value) => $_setBool(4, value);
@$pb.TagNumber(5)
$core.bool hasReloadRequired() => $_has(4);
@$pb.TagNumber(5)
void clearReloadRequired() => $_clearField(5);
} }
class AuthTokenInfo extends $pb.GeneratedMessage { class AuthTokenInfo extends $pb.GeneratedMessage {

View file

@ -434,7 +434,7 @@ class HubAdminClient extends $grpc.Client {
return $createUnaryCall(_$removeStore, request, options: options); return $createUnaryCall(_$removeStore, request, options: options);
} }
/// Install a module from a .fai bundle (local path or http(s) URL). /// Install a module from a .chain bundle (local path or http(s) URL).
$grpc.ResponseFuture<$0.InstallModuleResponse> installModule( $grpc.ResponseFuture<$0.InstallModuleResponse> installModule(
$0.InstallModuleRequest request, { $0.InstallModuleRequest request, {
$grpc.CallOptions? options, $grpc.CallOptions? options,
@ -467,7 +467,7 @@ class HubAdminClient extends $grpc.Client {
/// Read the inline-docs (MODULE.md / MODULE.<locale>.md) of an /// Read the inline-docs (MODULE.md / MODULE.<locale>.md) of an
/// installed module from disk. No network fetch, no provider- /// installed module from disk. No network fetch, no provider-
/// specific URL probing the docs ship in the .fai bundle and /// specific URL probing the docs ship in the .chain bundle and
/// live next to module.wasm on disk after install. Returns an /// live next to module.wasm on disk after install. Returns an
/// empty body when the module is installed but ships no inline /// empty body when the module is installed but ships no inline
/// docs; Studio uses that to hide the docs button entirely. /// docs; Studio uses that to hide the docs button entirely.

View file

@ -1819,6 +1819,7 @@ const AuthStatusResponse$json = {
'6': '.chain.v1.JwtValidatorInfo', '6': '.chain.v1.JwtValidatorInfo',
'10': 'jwt' '10': 'jwt'
}, },
{'1': 'reload_required', '3': 5, '4': 1, '5': 8, '10': 'reloadRequired'},
], ],
}; };
@ -1827,7 +1828,8 @@ final $typed_data.Uint8List authStatusResponseDescriptor = $convert.base64Decode
'ChJBdXRoU3RhdHVzUmVzcG9uc2USHAoJdmFsaWRhdG9yGAEgASgJUgl2YWxpZGF0b3ISKwoRYW' 'ChJBdXRoU3RhdHVzUmVzcG9uc2USHAoJdmFsaWRhdG9yGAEgASgJUgl2YWxpZGF0b3ISKwoRYW'
'5vbnltb3VzX2FsbG93ZWQYAiABKAhSEGFub255bW91c0FsbG93ZWQSLwoGdG9rZW5zGAMgAygL' '5vbnltb3VzX2FsbG93ZWQYAiABKAhSEGFub255bW91c0FsbG93ZWQSLwoGdG9rZW5zGAMgAygL'
'MhcuY2hhaW4udjEuQXV0aFRva2VuSW5mb1IGdG9rZW5zEiwKA2p3dBgEIAEoCzIaLmNoYWluLn' 'MhcuY2hhaW4udjEuQXV0aFRva2VuSW5mb1IGdG9rZW5zEiwKA2p3dBgEIAEoCzIaLmNoYWluLn'
'YxLkp3dFZhbGlkYXRvckluZm9SA2p3dA=='); 'YxLkp3dFZhbGlkYXRvckluZm9SA2p3dBInCg9yZWxvYWRfcmVxdWlyZWQYBSABKAhSDnJlbG9h'
'ZFJlcXVpcmVk');
@$core.Deprecated('Use authTokenInfoDescriptor instead') @$core.Deprecated('Use authTokenInfoDescriptor instead')
const AuthTokenInfo$json = { const AuthTokenInfo$json = {

View file

@ -270,7 +270,7 @@ class HubClient {
/// Replace the operator's `default_scope:`. The hub validates /// Replace the operator's `default_scope:`. The hub validates
/// the list (non-empty after trimming), persists to /// the list (non-empty after trimming), persists to
/// `~/.fai/config.yaml`, and hot-swaps the in-memory copy /// `~/.chain/config.yaml`, and hot-swaps the in-memory copy
/// without a daemon restart. Returns the snapshot. /// without a daemon restart. Returns the snapshot.
Future<({List<String> scope, List<String> knownProviders})> Future<({List<String> scope, List<String> knownProviders})>
setDefaultScope(List<String> scope) async { setDefaultScope(List<String> scope) async {
@ -450,7 +450,7 @@ class HubClient {
} }
/// Read the installed module's `MODULE.md` (or `MODULE.<locale>.md`) /// Read the installed module's `MODULE.md` (or `MODULE.<locale>.md`)
/// from disk under `~/.fai/modules/<module>/`. No network. Works in /// from disk under `~/.chain/modules/<module>/`. No network. Works in
/// air-gapped installs. The response distinguishes three states via /// air-gapped installs. The response distinguishes three states via
/// [GetInstalledModuleDocsResponse.notInstalled] and an empty /// [GetInstalledModuleDocsResponse.notInstalled] and an empty
/// [GetInstalledModuleDocsResponse.text]: /// [GetInstalledModuleDocsResponse.text]:
@ -535,7 +535,7 @@ class HubClient {
return _admin.refreshMcpClients(Empty()); return _admin.refreshMcpClients(Empty());
} }
/// Persist a new MCP server in `~/.fai/config.yaml` and /// Persist a new MCP server in `~/.chain/config.yaml` and
/// trigger discovery in one round-trip. /// trigger discovery in one round-trip.
Future<ListMcpClientsResponse> addMcpClient({ Future<ListMcpClientsResponse> addMcpClient({
required String name, required String name,
@ -618,7 +618,7 @@ class HubClient {
} }
/// Persist a new System-AI configuration. Validates + /// Persist a new System-AI configuration. Validates +
/// writes back to ~/.fai/config.yaml + hot-reloads the live /// writes back to ~/.chain/config.yaml + hot-reloads the live
/// hub state in one call. Returns the resulting status so /// hub state in one call. Returns the resulting status so
/// the UI can refresh in one round-trip. /// the UI can refresh in one round-trip.
Future<SystemAiStatusResponse> updateSystemAi({ Future<SystemAiStatusResponse> updateSystemAi({
@ -763,7 +763,7 @@ class HubClient {
return _admin.removeStore(pb.RemoveStoreRequest(name: name)); return _admin.removeStore(pb.RemoveStoreRequest(name: name));
} }
/// Install a module from a `.fai` bundle. [source] is either a /// Install a module from a `.chain` bundle. [source] is either a
/// URL or a local filesystem path; [expectedSha256] is an /// URL or a local filesystem path; [expectedSha256] is an
/// optional hex digest the hub verifies before unpacking. /// optional hex digest the hub verifies before unpacking.
Future<InstallModuleResponse> installModule({ Future<InstallModuleResponse> installModule({