Commit graph

47 commits

Author SHA1 Message Date
flemming-it
75a4b2b306 docs: old product name F∆I Platform -> Ch∆In + contact chain@flemming.ai
Some checks failed
Security / Security check (push) Failing after 1s
The old 'F∆I Platform' product name and platform@flemming.ai contact
survived in docs/NOTICE/descriptions/help text; the product is Ch∆In and
the contact is chain@flemming.ai. Generic 'cross-platform/platform-native'
left untouched.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-16 10:14:33 +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
35a8ee2844 feat: ModuleInfoResponse.inputs/outputs + ModuleField
Some checks failed
Security / Security check (push) Failing after 2s
Generated bindings for the schema_version 3 / ModuleField
proto addition in fai_platform commit f8b364e. Studio's
flow editor can now ask the hub for declared inputs and
outputs per module, with i18n descriptions, instead of
parsing references out of the flow YAML.

Bumps fai_client_sdk to 0.18.0.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-01 22:13:07 +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
7569e2aa53 chore(proto): regen for InstallModuleRequest.version
Some checks failed
Security / Security check (push) Failing after 2s
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-28 14:21:21 +02:00
flemming-it
bb18c1fcfc chore(proto): regenerate Dart bindings for StoreEntry.source_kind
Some checks failed
Security / Security check (push) Failing after 2s
Hub proto (platform 17998ce) added a `source_kind` field on
StoreEntry mirroring the same field on CapabilityEntry. Dart
SDK surfaces it for Studio's per-entry transport badge.

No hand-written code; only the regenerated bindings under
lib/src/generated/.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-28 12:06:58 +02:00
flemming-it
27278b89a9 chore(proto): regenerate Dart bindings for 0.12.0 CapabilityEntry
Some checks failed
Security / Security check (push) Failing after 2s
Hub-side proto (fai/platform 879bd97) grew three fields on
CapabilityEntry: `provider`, `source_kind`, `version_advisory`.
Dart SDK now surfaces them — Studio + DigiScout can read
which transport delivered each capability, the publisher
identity, and whether the version pin is advisory.

No hand-written code changed; only the regenerated files
under lib/src/generated/. dart analyze + dart test green.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-28 10:45:07 +02:00
flemming-it
f882b7f955 chore: rename package + dir + repo to fai_client_sdk
Some checks failed
Security / Security check (push) Failing after 1s
Adopts the three SDK families convention from
fai/platform/docs/architecture/sdks.md — base name carries
the family, language suffix on dir + repo only:

  fai_dart_sdk          (pkg) → fai_client_sdk
  fai_dart_sdk          (dir) → fai_client_sdk_dart
  fai/dart-sdk          (repo) → fai/client-sdk-dart

Internal lib/test/example file renames track the package
name. Old git.flemming.ws URL also retired here.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-26 13:46:16 +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
6ebec5e3ae chore(proto): regenerate after CapabilityEntry.kind + accepts_mime
Tracks the platform's hub.proto v0.11 update — adds the new
fields to the generated Dart bindings:

- `CapabilityEntry.kind` (string) — wasm / builtin / federated.
  Studio uses it to gate the Install button so built-ins like
  `system.approval` and federated MCP/n8n tools never get
  offered an install path that doesn't exist.
- `ModuleInfoResponse.accepts_mime` (repeated string) — MIME
  allow-list declared in `module.yaml`. Studio reads it for
  file-picker filtering.

No hand-edited code in this commit — `tools/generate.sh`
output only.

Signed-off-by: flemming-it <sf@flemming.it>
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-25 12:35:45 +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
ab2205466a ci(security): add self-test harness (mirror of fai/platform)
Some checks failed
Security / Security check (push) Has been cancelled
18 scenarios that verify the security script's rules still
trip on every tripwire — PATs, AWS keys, PEM headers, env
files, allowlist exempts, confidentiality terms, marketing
phrases, .security-allow exclusion, plus message-mode
(Conventional Commits, DCO, Claude trailer, banned phrases).

Wired into the security workflow as a second-line gate after
the diff-based check. Catches the refactor-weakens-a-rule
class of regression: the diff scan can be green while a rule
silently no-ops; the harness fails loudly when that happens.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-10 21:41:24 +02:00
flemming-it
8e378d4fc2 ci: add Forgejo security workflow (mirror of pre-commit hook)
Some checks failed
Security / Security check (push) Has been cancelled
Runs `tools/security/check-staged.sh ci` on every push to main
and every PR. Same script as the local pre-commit hook so the gate
is identical whether or not a contributor activated the local
hook via `bash tools/install-hooks.sh`. No Flutter / Dart toolchain
needed in the runner — the check is plain bash + git.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-09 13:40:37 +02:00
flemming-it
99ef83ccf0 ci(hooks): pre-commit security check (mirror of fai/platform)
Mirrors the hook + script from `fai/platform`@1ebf893 verbatim
so commits to fai_dart_sdk go through the same gate: secrets,
forbidden filenames, confidentiality references, marketing-
speak, DCO sign-off, Conventional Commits subject, no Claude
co-author trailer.

No `.security-allow` needed here — the SDK has no banned-words
gate or policy doc that mentions the filtered terms verbatim.
A full-history dry-run came back clean.

Activate once per clone with `bash tools/install-hooks.sh`.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-09 13:32:44 +02:00
flemming-it
5c96d74744 chore: regen for FlowSummary.required_capabilities (v0.16.0)
`pb.FlowSummary.requiredCapabilities` flows through the
existing typedef untouched, so callers see the new field
without a wrapper change.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-09 11:14:34 +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
f91f477230 feat: kind+provider fields on StoreEntry (v0.12.1)
Studio uses these to mark synthetic capabilities and suppress
their Install button.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-07 22:44:12 +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
a893361ff9 feat: icon/screenshots/docs_url fields on StoreEntry (v0.11.0)
Picks up the three new optional fields on the StoreEntry
proto. No new client method — fields are plumbed through
SearchStore. Studio reads them off the entry directly.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-07 21:51:29 +02:00
flemming-it
df6ab995d3 feat: featured flag on StoreEntry (v0.10.1)
Picks up the new `featured: bool` field in the StoreEntry
proto. No new client method — the flag is plumbed through
SearchStore. Studio reads it directly off the entry.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-07 21:05:03 +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