Add device enrollment API and agent protocol

Expose ITAM REST endpoints for agents, console GraphQL for device
management, and wire probod bootstrap with enrollment e2e coverage.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
This commit is contained in:
Ludovic Vielle
2026-07-14 20:39:45 +02:00
parent 1f79453386
commit e767dd8377
30 changed files with 2129 additions and 6 deletions

View File

@@ -17,6 +17,7 @@ import (
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/iam"
"go.probo.inc/probo/pkg/itam"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/probo"
"go.probo.inc/probo/pkg/server/api/console/v1/schema"
@@ -1307,6 +1308,35 @@ func (r *organizationResolver) ThirdPartiesDocument(ctx context.Context, obj *ty
return types.NewDocument(document), nil
}
// Devices is the resolver for the devices field.
func (r *organizationResolver) Devices(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DeviceOrderBy) (*types.DeviceConnection, error) {
scope, err := r.authorize(ctx, obj.ID, itam.ActionDeviceList)
if err != nil {
return nil, err
}
pageOrderBy := page.OrderBy[coredata.DeviceOrderField]{
Field: coredata.DeviceOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.DeviceOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
devicesPage, err := r.itam.ListForOrganizationID(ctx, scope, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization devices", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewDeviceConnection(devicesPage, r, obj.ID), nil
}
// WebhookSubscriptions is the resolver for the webhookSubscriptions field.
func (r *organizationResolver) WebhookSubscriptions(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.WebhookSubscriptionOrderBy) (*types.WebhookSubscriptionConnection, error) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionWebhookSubscriptionList)