Commit graph

47 commits

Author SHA1 Message Date
flemming-it
0eafaa763a feat: trust/exposure fields — installVerification, keyPinned, exposure
Some checks failed
Security / Security check (push) Failing after 2s
Regenerated stubs for the additive proto: per-entry
StoreEntry.installVerification, StoreSource.keyPinned, the
ListStoresResponse policy snapshot (requireSignatures /
trustedPublisherCount) and DeclaredService.exposure. New
listStoresFull() exposes the response-level snapshot; listStores()
stays as the plain source list.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-21 12:56:35 +02:00
flemming-it
d9ef3ecdb6 feat: listInvocationsFull — monitor payload incl. detachedEnabled
Some checks failed
Security / Security check (push) Failing after 1s
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-18 00:17:20 +02:00
flemming-it
aca36102e4 feat: planSetup — guided-setup plan preview over the hub connection
Some checks failed
Security / Security check (push) Failing after 2s
Wraps the new HubAdmin.PlanSetup RPC (pure plan assembly, no state
change). Regenerated stubs from the updated proto.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-17 00:59:01 +02:00
flemming-it
3381cb1728 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>
2026-07-15 05:39:22 +02:00
flemming-it
ec3b684e6e feat: probe() — health check that separates auth rejection from unreachable
Some checks failed
Security / Security check (push) Failing after 2s
healthy() collapses every failure to false, so a hub that is up
but rejects the bearer token was indistinguishable from a dead
endpoint. probe() returns serving / notServing / authRejected
(UNAUTHENTICATED or PERMISSION_DENIED) / unreachable so client
UIs can point the operator at the token instead of the wire.
healthy() is unchanged.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-15 04:45:16 +02:00
flemming-it
9141a91314 feat: authStatus() — read-only hub auth-policy snapshot
Some checks failed
Security / Security check (push) Failing after 2s
Regenerated stubs for the additive AuthStatus HubAdmin RPC and a
typed wrapper: active validator, anonymous flag, token entries with
scope grants, rate limits and env-var set-state. Secret values never
cross the wire.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-15 00:50:21 +02:00
flemming-it
3fe96c9487 feat: listInvocations() for the detached-runs monitor
Some checks failed
Security / Security check (push) Failing after 1s
Returns every tracked detached invocation (newest-first) with id,
phase, current step, timestamps, error, flow name and project.
Regenerated stubs from the platform hub.proto.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-12 14:34:24 +02:00
flemming-it
f67e430b09 feat: project override on runSavedFlow
Some checks failed
Security / Security check (push) Failing after 2s
Empty keeps the saved flow's own project:, then general (resolved
hub-side) — the wire field existed, the wrapper now exposes it.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-12 13:35:14 +02:00
flemming-it
dd909b58f4 feat: project registry + per-project filters (stage 1 wire surface)
Some checks are pending
Security / Security check (push) Waiting to run
- listProjects() returns the shared hub's registry (general first;
  sealed areas never appear — they are their own hub instance).
- eventLog, streamEvents and listApprovals take an optional project:
  filter; LoggedEvent, PendingApprovalEntry and FlowSummary carry
  project. Stubs regenerated from the platform's hub.proto.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-12 13:33:08 +02:00
flemming-it
c46dc58ac3 feat: submitStreaming + detached-invocation client (T2/T3)
Some checks failed
Security / Security check (push) Failing after 2s
Regenerates the gRPC stubs from the updated proto and adds:
- HubClient.submitStreaming(...) -> Stream<SubmitStreamEvent>: follow a
  flow execution live (step markers, module emit-events, terminal
  result/error). Works over native gRPC and, on web, gRPC-Web (the
  same conditional channel factory the rest of the SDK uses).
- submit(..., detach: true) and getInvocationStatus /
  getInvocationResult / cancelInvocation wrappers (T3).
- SubmitStreamEvent + InvocationStatus re-exported as typedefs.

Shared _buildSubmitRequest between submit + submitStreaming. analyze
clean, tests pass.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-06 01:56:43 +02:00
flemming-it
9fea05df76 feat(sdk): addStore() accepts pinnedPubkeyPem
Some checks failed
Security / Security check (push) Failing after 1s
Regenerate Dart bindings for AddStoreRequest.pinned_pubkey_pem and
thread it through HubClient.addStore so clients can pin a per-store
publisher key.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-19 02:54:48 +02:00
flemming-it
597f6bec4f feat(sdk): HubClient.submit() with JSON inputs and outputs
Some checks failed
Security / Security check (push) Failing after 1s
Wrap the Submit RPC so callers can run a flow inline with typed
inputs and read its outputs. jsonInputs (each value a Dart Map) are
converted to a google.protobuf.Struct via a recursive builder and
sent as Payload.json — the only path that can feed a json-typed
module input (e.g. econ.skm_score, law.benefit_score). The returned
SubmitResponse.outputs carry the flow outputs, which the audit log
does not persist.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-18 21:29:10 +02:00
flemming-it
d07a0a9777 feat(client): listStores / addStore / removeStore for the store manager
Some checks failed
Security / Security check (push) Failing after 2s
Regenerate the gRPC stubs for the new HubAdmin store-management RPCs and
wrap them in HubClient (returns StoreSource list / Add+RemoveStoreResponse)
so Studio can list and edit the module-store list from the GUI.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-18 15:49:23 +02:00
flemming-it
d680cf3462 refactor: regenerate gRPC stubs for chain.v1 wire package
Some checks are pending
Security / Security check (push) Waiting to run
The hub renamed its gRPC package fai.v1 -> chain.v1 (proto dir
proto/fai/v1 -> proto/chain/v1). Move the generated stubs to
generated/chain/v1 and rewrite the wire package + service paths
(/fai.v1.Hub/* -> /chain.v1.Hub/*) so the client talks to the
renamed hub. Pure package rename — no message/field changes.
HubClient public API is unchanged, so dependents need no edits.
dart analyze: clean.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-16 16:59:35 +02:00
flemming-it
9c0d461fb7 feat: regenerate protos + federation client methods
Some checks failed
Security / Security check (push) Failing after 2s
Regenerate the Dart bindings from the platform protos (now including
fai/v1/federation.proto and the IssueBootstrapToken / ListSatellites
HubAdmin RPCs + the new primary_ca_pem field). Add HubClient
wrappers: listSatellites() and issueBootstrapToken(name, region,
ttl), the latter returning the primary CA so callers can bootstrap a
satellite in one step.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-13 14:07:30 +02:00
flemming-it
db13bdb4a7 feat(client): reloadAuth() wrapper
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>
2026-05-29 18:40:20 +02:00
flemming-it
023adcec31 chore(deps): grpc 4→5, protobuf 4→6
Some checks failed
Security / Security check (push) Failing after 2s
Two coupled majors that have been blocking the rest of the
Dart-side dependency lift in Studio (the constraint solver
pins meta/characters/etc. through these). Picked up:

- grpc 5.1.0 (was 4.2.0)
- protobuf 6.0.0 (was 4.2.0)
- analyzer 13.0.0, _fe_analyzer_shared 100.0.0
- google_cloud 0.5.0, googleapis_auth 2.3.1 (transitive)

The bindings now live in `lib/src/generated/fai/v1/` only —
the well-known-types `lib/src/generated/google/protobuf/`
copy has been deleted. protobuf 6 ships its own bundled
`well_known_types/google/protobuf/empty.pb.dart` and the
`HubAdminClient` API expects the *packaged* Empty type;
emitting a local copy created two distinct Empty types and
broke every `_admin.<rpc>(Empty())` call site.

`tools/generate.sh` now skips the WKT generation pass and
wipes `lib/src/generated/google/` on every run so the
duplicate-types breakage can't regress silently. The
import in `hub_client.dart` switches from the local copy to
`package:protobuf/well_known_types/google/protobuf/empty.pb
.dart`.

Smoke-verified: dart analyze clean, dart test green
(4 tests). Bumped to 0.17.0 — Studio absorbs in the next
commit.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-29 14:35:05 +02:00
flemming-it
427bd6c0d9 feat(client): getDefaultScope / setDefaultScope wrappers
Some checks failed
Security / Security check (push) Failing after 2s
Studio's upcoming default_scope editor in Settings calls
through these wrappers. Both return a record with the live
`scope` and the catalog-known publisher shortlist so the UI
can render a typeahead while letting operators paste private
publisher segments freely.

Bindings regenerated from fai_platform/proto.

dart analyze + dart test green (4 tests).

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-29 00:19:24 +02:00
flemming-it
c90a88481c feat(client): streamEvents() wraps server-streaming audit log
Some checks failed
Security / Security check (push) Failing after 2s
Adds `HubClient.streamEvents(backfill:, types:)` returning a
`Stream<LoggedEvent>` that fronts the new
`HubAdmin/StreamEvents` RPC. Each event arrives the instant
the hub appends it; cancel the subscription to close the RPC.

`backfill` defaults to 50 historical events (oldest-last for
chronological reception). `RESOURCE_EXHAUSTED` from the
server means the receiver fell behind — reconnect with a
fresh backfill to resync.

Bindings regenerated from fai_platform/proto.

dart analyze + dart test green (4 tests).

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-28 16:54:51 +02:00
flemming-it
549f9df5c6 feat(client): authToken parameter for Bearer auth
Some checks failed
Security / Security check (push) Failing after 1s
`HubClient` accepts an optional `authToken: String?` that
attaches `authorization: Bearer <token>` to every gRPC + gRPC-
Web call as default CallOptions metadata.

Operators with `auth.tokens:` configured on the hub now have
a one-line client-side wire-up:

  final client = HubClient(
    endpoint: HubEndpoint(host: '...', port: 50051),
    authToken: 'secret-from-1password-or-vault',
  );

Without `authToken`, calls go unauthenticated — the hub
either accepts (anonymous mode) or rejects with
`UNAUTHENTICATED` (16) when auth is required.

dart analyze + dart test green (4 tests).

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-28 16:37:08 +02:00
flemming-it
ed92f337b4 feat(client): uninstallModule takes optional version param
Some checks failed
Security / Security check (push) Failing after 2s
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-28 14:26:47 +02:00
flemming-it
332d11af1d feat(client): searchStore takes provider + namespace filter params
Some checks failed
Security / Security check (push) Failing after 2s
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-28 14:23:32 +02:00
flemming-it
f481eee687 feat(client): GrpcWebClientChannel on web targets via conditional import
Some checks failed
Security / Security check (push) Failing after 1s
Splits channel construction into two files selected at
compile-time via `if (dart.library.html)`:

  channel_factory_io.dart   — native ClientChannel (HTTP/2)
  channel_factory_web.dart  — GrpcWebClientChannel.xhr (HTTP/1.1)

HubClient._channel is now `ClientChannelBase` so both
implementations satisfy the same field type. dart:html-only
imports (`package:grpc/grpc_web.dart`) stay isolated from the
native compile path.

Pairs with the hub-side `fai_grpc_web` adapter crate
(fai/platform 0d07892) — `tonic-web` on the same port as
native gRPC, so one `fai serve` listener handles both
surfaces.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-26 13:34:26 +02:00
flemming-it
5604e5eaf3 chore(proto): regenerate after InvokePluginTranslate RPC
Adds HubClient.invokePluginTranslate as a typed method.
Same shape as invokePluginTheme: capability + args in,
typed response out.

Signed-off-by: flemming-it <sf@flemming.it>
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-25 23:02:21 +02:00
flemming-it
4a582f2b8d chore(proto): regenerate after InvokePluginTheme RPC
Tracks fai/platform's new gRPC RPC + matching request /
response messages. Adds HubClient.invokePluginTheme as a
typed Dart method.

Signed-off-by: flemming-it <sf@flemming.it>
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-25 21:49:39 +02:00
flemming-it
0879a95aba feat(hub-client): GetInstalledModuleDocs + per-file MIME
- New getInstalledModuleDocs(name, locale) wraps the new gRPC
  RPC; callers get text + source path + a not-installed flag so
  Studio can decide whether to show a Documentation section at
  all.
- runSavedFlow gains an optional fileMimeTypes map keyed
  parallel to fileInputs. Hard-coded application/octet-stream
  remains as the fallback, but text.extract and other
  MIME-gating modules now get an accurate type when the caller
  knows one.
- fetchModuleDocs is marked @Deprecated; it still works for
  older consumers but Studio no longer calls it.
- Proto bindings regenerated against fai/platform proto.

Signed-off-by: flemming-it <sf@flemming.it>
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-25 11:17:31 +02:00
flemming-it
b8bcae4b14 feat(hub-client): forward locale to FetchModuleDocs
Some checks failed
Security / Security check (push) Failing after 1s
Hub now accepts a locale field on FetchModuleDocsRequest so
README.<locale>.md (e.g. README.de.md) gets tried before the
generic README.md. SDK passes it via an optional named param;
empty string keeps the previous behaviour.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-24 22:07:16 +02:00
flemming-it
1e98ab9ccf feat: getFlowDefinition wrapper + FlowInputDef DTO (v0.15.0)
Surface the new platform RPC `GetFlowDefinition` as a typed
Dart method so Studio (and other GUI clients) can render an
input form before calling `runSavedFlow`. Each declared input
arrives as a `FlowInputDef` with the verbatim type tag from
the flow YAML — usually `text`, `bytes`, `json`, or `file`.

Regenerated proto bindings to pick up the new
`GetFlowDefinitionRequest`, `FlowDefinition`, and
`FlowInputSpec` message types.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-09 10:12:59 +02:00
flemming-it
193f59302a feat: runSavedFlow accepts file (bytes) inputs (v0.14.0)
Studio's Flows tab couldn't run any sample flow with a
binary input (extract / extract-summarize / …) because
runSavedFlow only knew how to wrap textInputs as text
Payloads. Operators saw the hub return
"step references missing value '\$inputs.document'" because
the document key never made it into the request.

`runSavedFlow` is now mixed-mode:

  Future<SubmitResponse> runSavedFlow({
    required String name,
    Map<String, String> textInputs = const {},
    Map<String, Uint8List> fileInputs = const {},
  })

Both maps default to empty so existing text-only callers
keep working without code changes — the previous required
`textInputs:` parameter is now optional with a default. File
entries get wrapped as `Bytes` Payloads with
`application/octet-stream` MIME — good enough for the
text.extract / text.summarize chain that the bundled flows
exercise. Per-file MIME-type override is a follow-up if any
operator workflow ever needs it.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-09 02:07:07 +02:00
flemming-it
45f60ef77b feat: n8n endpoints federation surface (v0.13.0)
Sister of the MCP-client surface — four new HubAdmin RPCs
(`ListN8nEndpoints`, `RefreshN8nEndpoints`, `AddN8nEndpoint`,
`RemoveN8nEndpoint`) plus the matching typedefs so callers
read configuration off `N8nEndpointStatus` without importing
generated/.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-08 01:00:03 +02:00
flemming-it
776e3c0221 feat: MCP-client federation surface (v0.12.0)
Picks up the four new HubAdmin RPCs that drive Studio's
MCP-clients editor:

- `listMcpClients()` — config + last-discovery snapshot.
- `refreshMcpClients()` — re-run discovery against the live
  daemon.
- `addMcpClient(name, endpoint, apiKeyEnv?, description?)` —
  persist + refresh in one round-trip.
- `removeMcpClient(name)` — drop persisted entry and live
  synthetic capabilities.

Typedefs for `ListMcpClientsResponse`, `McpClientStatus`,
`McpClientConfigEntry` so callers don't import generated/.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-07 22:39:19 +02:00
flemming-it
6efbdb2ff9 feat: fetchModuleDocs wrapper (v0.10.0)
Picks up HubAdmin.FetchModuleDocs. HubClient exposes it as
fetchModuleDocs(name) returning the FetchModuleDocsResponse
verbatim — Studio maps the error_kind to friendly copy.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-07 20:45:59 +02:00
flemming-it
90405e6fc3 feat: uninstallModule + daemonPaths wrappers (v0.9.0)
HubClient gains:
- daemonPaths() — typed access to the new DaemonPaths RPC.
- uninstallModule(name) — typed wrapper for UninstallModule.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-07 17:46:32 +02:00
flemming-it
6dc058344b feat: System-AI cache surface (v0.8.0)
Picks up cache-related additions in HubAdmin:
- AskAi gains `forceFresh` request flag and `cached` /
  `cachedAt` / `cacheHits` response fields.
- New ClearSystemLlmCache + ForgetCachedExplanation RPCs.
- SystemAiStatus carries `cacheCount` so the UI can render
  "Cache: N cached explanations".

HubClient exposes `clearSystemLlmCache()` returning the
purged count and `forgetCachedExplanation(prompt)` for the
Regenerate flow.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-07 17:29:26 +02:00
flemming-it
26d9d1f502 feat: clearEventLog wrapper (v0.7.1)
Picks up the new HubAdmin.ClearEventLog RPC. Exposed as
HubClient.clearEventLog(reviewer:, reason:) returning the
purged count + active channel for the caller to confirm.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-07 17:09:52 +02:00
flemming-it
4dad51da6d feat: hardwareInfo + listSystemAiCuratedModels RPCs (v0.7.0)
Regenerated protos pick up the two new HubAdmin RPCs. HubClient
exposes them as hardwareInfo() and listSystemAiCuratedModels(),
with HardwareInfoResponse, ListSystemAiCuratedModelsResponse,
CuratedModel re-exported as typedefs so callers don't import
the generated/ directory directly.

Studio uses the pair to colour-code models in the System-AI
editor against the operator's actual hardware.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-07 15:39:12 +02:00
flemming-it
f04da40751 feat: testSystemAi accepts draft config; list+pull models (v0.6.0)
`testSystemAi` now takes optional provider/endpoint/model/
apiKeyEnv/privacyMode params; the editor passes form values so
Test Connection works before Save. New `listSystemAiModels`
fetches the provider's `/v1/models` listing, `pullSystemAiModel`
calls Ollama's `/api/pull` synchronously.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-07 14:02:43 +02:00
flemming-it
8798119903 feat: updateSystemAi + testSystemAi RPCs (v0.5.0)
`HubClient.updateSystemAi(...)` persists a new System-AI config
to ~/.fai/config.yaml AND hot-reloads the live hub state in one
round-trip; returns the resulting SystemAiStatus so the UI
refreshes without a second call.

`HubClient.testSystemAi()` probes the configured provider with
a tiny ping and returns the same error-kind taxonomy as askAi.
Studio's "Test connection" button uses this.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-07 13:41:10 +02:00
flemming-it
f0db42264f feat: SystemAiStatus + AskAi RPCs (v0.4.0)
`HubClient.systemAiStatus()` reports whether the hub-internal LLM
hook is configured and which provider / privacy mode is active.
`HubClient.askAi(prompt)` issues a one-shot prompt and returns
the answer or a structured error kind so the UI can map each
failure to its inline-fix copy.

LoggedEvent gains `detail` upstream (no SDK change required).

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-07 13:18:22 +02:00
flemming-it
73dbdc16ef feat: store + install + channel status (v0.3.0)
Catches the Dart bindings up to the platform's gRPC additions:
  * `searchStore({query, category, tag, status, limit})` — wraps
    HubAdmin.SearchStore so Studio can build a Store browser
    page.
  * `installModule({source, expectedSha256})` — wraps
    HubAdmin.InstallModule so the operator can one-click install
    a `.fai` bundle from the UI.
  * `channelStatus()` — new HubAdmin.ChannelStatus RPC. Returns
    active channel name + per-channel running flag + endpoint.

Re-exports the new proto types (StoreEntry,
StoreSearchResponse, InstallModuleResponse, ChannelStatusResponse,
ChannelEntry) so callers don't import protobuf directly.

LoggedEvent gains a `detail` field (free-form JSON string)
upstream; the regenerated bindings expose it without further
work — Studio's audit drill-down renders it pretty-printed.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-07 11:54:30 +02:00
flemming-it
c5e11395fb feat: regenerate for HubAdmin.CheckUpdate (v0.2.0)
Adds `checkUpdate()` to HubClient and re-exports
`CheckUpdateResponse` so callers (Studio Doctor page) can render
update + offline states without importing protobuf directly.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-06 15:53:13 +02:00
flemming-it
9249fbe4f5 feat: HubClient.listFlows + runSavedFlow
Two more wrappers for Studio's new Flows page. Saved flows can
be listed (FlowSummary: name + path + size) and executed by
name with a map of named text inputs. Returns a SubmitResponse
whose `outputs` map carries the flow's declared outputs as
Payloads.

Common payload type re-exposed via the `Payload` typedef from
common.pb.dart so the Studio side can pattern-match on
text/json/bytes/file without dragging in proto imports.

Bumps fai_dart_sdk 0.4.0 -> 0.5.0.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-05 23:35:47 +02:00
flemming-it
4b67055fc7 refactor: share single ClientChannel between Hub and HubAdmin
Initial scaffold accidentally created three separate gRPC
channels (one for each of `_channel`, `_hub`, `_admin`).
Refactor to a single shared channel — cleaner, fewer file
descriptors, and `close()` actually closes everything now.
Idle timeout raised to 5 minutes so polling-style page loops
don't keep reconnecting.

No public-API change.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-05 22:51:19 +02:00
flemming-it
a2e3f4514a feat: HubClient.moduleInfo for Studio module-detail sheet
Wraps the existing HubAdmin.ModuleInfo RPC so Studio can
render a detail panel for one module without re-implementing
the proto types.

Bumps fai_dart_sdk 0.3.0 -> 0.4.0.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-05 22:13:49 +02:00
flemming-it
1eaa36b1a0 feat: HubClient.verifyEventChain + listServices
Mirrors the two new HubAdmin RPCs in fai_platform 0.10.44.
Studio's Doctor page consumes these directly. Generated proto
bindings refreshed to include VerifyEventChainResponse,
ServiceList, DeclaredService.

Bumps fai_dart_sdk 0.2.0 -> 0.3.0.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-05 22:05:40 +02:00
flemming-it
da10820959 feat: live HubClient with generated proto bindings
Proto codegen wired in. tools/generate.sh wraps protoc against
../fai_platform/proto/, including the well-known types (Empty,
Struct, Timestamp) so they are generated alongside fai's own
messages — protobuf 4.x doesn't ship them as importable Dart
types, so we have to generate them ourselves.

HubClient now exposes typed methods backed by real RPCs:
- healthy() — Hub.Health probe (returns false on connect refused).
- listCapabilities() — HubAdmin.ListCapabilities.
- eventLog() — HubAdmin.EventLog with type filter.
- listApprovals() — HubAdmin.ListApprovals (status filter).
- approve() / reject() — HubAdmin.DecideApproval.

Generated bindings under lib/src/generated/ are excluded from
analyze (out of our style control). protoc_plugin pinned to
22.2.0 in tools/generate.sh comment because newer plugins
generate code against protobuf 6.x, while grpc 4.x still
constrains us to protobuf 4.x.

Bumps fai_dart_sdk 0.1.0 -> 0.2.0.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-05 16:24:16 +02:00
flemming-it
d405a6a9bd feat: fai_dart_sdk scaffold
Dart package skeleton for the F∆I gRPC client. Used by F∆I
Studio (Tier-2) and Tier-3 domain apps (DigiScout / J∆I /
Scout). Public surface — HubClient, HubEndpoint — is committed
as a typed stub so downstream apps can compile against it
immediately. Generated proto bindings land in a follow-up
commit once the codegen step (planned: tools/generate.sh
wrapping protoc-gen-dart against ../fai_platform/proto) is
wired in.

Future Forgejo path: fai/dart-sdk.

dart analyze: clean. dart test: 4/4.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-05 14:19:39 +02:00