MCPcopy Create free account
hub / github.com/PerpetualSoftware/pad / BuildAgentBootstrap

Method BuildAgentBootstrap

internal/server/handlers_bootstrap.go:423–633  ·  view source on GitHub ↗

BuildAgentBootstrap assembles the bootstrap blob from store queries. This is the single canonical code path; the HTTP handler, the MCP resource handler, and the MCP `pad_set_workspace` embed all call this. r is the live request — used for the dashboard sub-build AND to resolve the calling principal

(workspaceID string, user *models.User, r *http.Request)

Source from the content-addressed store, hash-verified

421// safe ONLY for callers that have already verified full-member access
422// out-of-band. Production HTTP/MCP paths MUST pass the live request.
423func (s *Server) BuildAgentBootstrap(workspaceID string, user *models.User, r *http.Request) (*AgentBootstrap, error) {
424 ws, err := s.store.GetWorkspaceByID(workspaceID)
425 if err != nil {
426 return nil, err
427 }
428
429 out := &AgentBootstrap{
430 Workspace: AgentBootstrapWorkspace{
431 ID: ws.ID,
432 Slug: ws.Slug,
433 Name: ws.Name,
434 Description: ws.Description,
435 },
436 }
437 if user != nil {
438 out.User = AgentBootstrapUser{
439 ID: user.ID,
440 Name: user.Name,
441 Email: user.Email,
442 }
443 }
444
445 // Resolve visibility once so collections/conventions/playbooks/roles
446 // all project the same authorized view. nil visibleIDs means "no
447 // restriction" — a full workspace member (or a nil-r caller that
448 // has already verified access out-of-band). For guests with
449 // item-level grants, we also need ItemIDs filtering so a grant to
450 // one specific playbook doesn't leak the whole collection.
451 var visibleIDs []string
452 var grantedItemIDs []string
453 var fullCollIDs []string
454 if r != nil {
455 visibleIDs, err = s.visibleCollectionIDs(r, workspaceID)
456 if err != nil {
457 return nil, err
458 }
459 fullCollIDs, grantedItemIDs, err = s.guestResourceFilter(r, workspaceID)
460 if err != nil {
461 return nil, err
462 }
463 }
464
465 // Collections — load and apply visibility filtering. We hold these
466 // in their full models.Collection shape through the role/count
467 // recompute below (which keys lookups by Collection.ID), then
468 // project to BootstrapCollection at the end of this section. The
469 // projection drops id/workspace_id/timestamps/settings and parses
470 // the schema string into a nested object — see BootstrapCollection
471 // godoc + PLAN-1410 / TASK-1412.
472 collections, err := s.store.ListCollections(workspaceID)
473 if err != nil {
474 return nil, err
475 }
476 if visibleIDs != nil {
477 filtered := make([]models.Collection, 0, len(collections))
478 for _, c := range collections {
479 if isCollectionVisible(c.ID, visibleIDs) {
480 filtered = append(filtered, c)

Callers 1

handleGetBootstrapMethod · 0.95

Calls 15

visibleCollectionIDsMethod · 0.95
guestResourceFilterMethod · 0.95
isCollectionVisibleFunction · 0.85
isCollectionSlugVisibleFunction · 0.85
projectBootstrapRoleFunction · 0.85
capBootstrapDashboardFunction · 0.85
GetWorkspaceByIDMethod · 0.80

Tested by

no test coverage detected