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>
This commit is contained in:
flemming-it 2026-07-12 13:33:08 +02:00
parent 408f0eb850
commit dd909b58f4
5 changed files with 383 additions and 11 deletions

View file

@ -81,6 +81,7 @@ typedef N8nEndpointStatus = pb.N8nEndpointStatus;
typedef N8nEndpointConfigEntry = pb.N8nEndpointConfigEntry;
typedef ModuleInfoResponse = pb.ModuleInfoResponse;
typedef FlowSummary = pb.FlowSummary;
typedef ProjectInfo = pb.ProjectInfo;
typedef StoreEntry = pb.StoreEntry;
typedef StoreSearchResponse = pb.StoreSearchResponse;
typedef InstallModuleResponse = pb.InstallModuleResponse;
@ -183,18 +184,31 @@ class HubClient {
}
/// Recent events from the audit log, newest-first. Pass an
/// empty `types` list for all event types.
/// empty `types` list for all event types. A non-empty
/// [project] scopes the view to that project's runs (the slug
/// is normalized hub-side, so a display name works too).
Future<List<LoggedEvent>> eventLog({
int limit = 100,
List<String> types = const [],
String project = '',
}) async {
final req = pb.EventLogRequest()
..limit = limit
..eventTypes.addAll(types);
..eventTypes.addAll(types)
..project = project;
final r = await _admin.eventLog(req);
return r.events;
}
/// The shared hub's project registry (`general` first): the
/// lightweight labels grouping flows, runs, approvals and audit
/// events. Sealed areas never appear here they are their own
/// hub instance a client connects to directly.
Future<List<ProjectInfo>> listProjects() async {
final r = await _admin.listProjects(Empty());
return r.projects;
}
/// Read the operator's `default_scope:` — the ordered list of
/// provider segments the bare-form capability resolver
/// consults when a flow names a capability without an explicit
@ -248,21 +262,26 @@ class HubClient {
Stream<LoggedEvent> streamEvents({
int backfill = 50,
List<String> types = const [],
String project = '',
}) {
final req = pb.StreamEventsRequest()
..backfill = backfill
..eventTypes.addAll(types);
..eventTypes.addAll(types)
..project = project;
return _admin.streamEvents(req);
}
/// Pending approvals filtered by status. Defaults to all.
/// Pending approvals filtered by status and/or project.
/// Defaults to all.
Future<List<PendingApprovalEntry>> listApprovals({
List<String> statuses = const [],
int limit = 100,
String project = '',
}) async {
final req = pb.ListApprovalsRequest()
..limit = limit
..statuses.addAll(statuses);
..statuses.addAll(statuses)
..project = project;
final r = await _admin.listApprovals(req);
return r.entries;
}