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

Method BuildAgentBootstrap

internal/server/handlers_bootstrap.go:422–651  ·  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

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

Callers 1

handleGetBootstrapMethod · 0.95

Calls 15

visibleCollectionIDsMethod · 0.95
guestResourceFilterMethod · 0.95
isCollectionVisibleFunction · 0.85
projectConventionIndexFunction · 0.85
projectBootstrapRoleFunction · 0.85
projectPlaybookMetadataFunction · 0.85

Tested by

no test coverage detected