First Class Modules

ActiveWorkplace

Pins any permitted Record into a collaborative workplace over its secured recursive relationship graph, with people, GoClaws, workflows, Record Pulse, Inbox attention, activity, and read-only Graph Playback.

Open raw .md
Runtime key
module.active-workplace
Experience
Recursive work coordination
Security
Server-enforced

Use ActiveWorkplace when work crosses several connected records and people need one durable coordination view without creating a duplicate project, case, customer, file, or other business record.

Note

The bundled renderer key is module.active-workplace. First-class means BuildWithHQ supplies a native, typed, secured runtime experience inside normal app provisioning and the signed-in user's existing permissions.

What it does

Pins any permitted Record into a collaborative workplace over its secured recursive relationship graph, with people, GoClaws, workflows, Record Pulse, Inbox attention, activity, and read-only Graph Playback.

Key capabilities

  • Pin any currently permitted Record once as the workplace root.
  • Capture a cycle-safe, bounded Active Graph over existing typed Record Relations.
  • Coordinate named users, GoClaw assistants, and published workflows with explicit responsibilities.
  • Track Active, Waiting, At Risk, Stale, Dormant, and Resolved Record Pulse states.
  • Create or touch one Universal Inbox attention item when a workplace becomes At Risk or Stale.
  • Record meaningful comments, participant changes, status transitions, related-record changes, and graph refreshes in an immutable activity stream.
  • Reconstruct retained workplace, participant, graph, and activity state through unmistakably read-only Graph Playback while applying current permissions.
  • Accept bounded builder defaults for root modules, graph depth/nodes, stale timing, participant types, GoClaw watchers, comments, and playback.

The Active Graph

The pinned Record stays owned by its native module. ActiveWorkplace follows the existing RecordRelations graph to the configured depth and node limit, records identity/topology snapshots, and resolves titles, status, module, location, and edit state through the current secured Record envelope. Cycles are safe, and hidden nodes and their edges are omitted.

Record Pulse

PulseMeaning
ActiveMeaningful work is moving.
WaitingWork is intentionally waiting for a date, response, or dependency.
At RiskThe configured inactivity threshold is approaching.
StaleThe inactivity threshold has passed and attention is required.
DormantThe workplace is intentionally inactive without being resolved.
ResolvedThe coordinated work is complete.

A bounded background evaluator observes meaningful activity and configured timing. At Risk and Stale transitions reuse Universal Inbox create-or-touch behavior, so a retry updates the existing attention item instead of creating an alert pile.

Participants and governed assistance

A participant assignment states responsibility; it does not grant access. A user still needs current Record permission. A GoClaw must independently have AI-read access through its backing user, and material actions still require the existing action permission and approval policy. A workflow remains limited to its published definition and normal execution authority.

Graph Playback

Playback combines temporal workplace/participant state, immutable events, retained graph snapshots, and historical Record values. It then intersects every retained Record identity with the viewer’s current DataRole and location scope. Historical mode has a prominent read-only banner and removes status, participant, comment, workflow, GoClaw, refresh, and destructive controls.

Common uses

  • Complex customer, case, opportunity, project, asset, incident, contract, or collections coordination.
  • A Wave-like shared work surface around connected records without copying those records.
  • Cross-team handoffs where responsibilities, inactivity, dependencies, and history must stay visible.
  • GoClaw monitoring and workflow participation under the same permissions and approvals as the rest of the app.

How it connects

ActiveWorkplace composes the universal Records/RecordRelations graph, tenant DataRole/location envelope, activity, workflows, GoClaw identities and actions, and Universal Inbox attention. Its state belongs to the tenant runtime database. AI Orchestration is used only when an AI job actually plans or executes work; it does not hold a shadow workplace or graph.

Where applicable, its records use the universal RecordId conventions so they can participate in secured relationships, activity history, favorites, dynamic fields, notifications, Inbox attention, and global search without copying the source record.

Security and data boundary

The server derives app, account, user, DataRole, and locations. Root creation requires current read/edit access; each displayed graph node is reauthorized; GoClaw assignment requires independent AI-read access; and playback applies current authorization before returning any retained identity or event. Direct table access is denied to runtime and Pulse-worker roles.

  • The authenticated service derives the SaaS app, tenant account, user, DataRole, and location scope; browser identifiers are never authorization proof.
  • The page editor composes React components with validated data bindings. Those bindings call typed runtime APIs, whose application services execute reviewed stored procedures.
  • List, search, detail, relation, activity, favorite, and write operations reapply their required server-side permissions.

Add it to an app

  1. Add the validated module.active-workplace block to an appropriate page and place that page in existing user-type menus.
  2. Choose optional root module filters, graph depth (1–5), node limit (2–200), stale threshold, warning window, participant types, comments, and playback defaults.
  3. If desired, select eligible default GoClaw participant IDs and retain human approval for material actions; unavailable or unauthorized agents are not assigned.
  4. Confirm the app has useful typed Record Relations, then test pinning a cyclic graph, an inaccessible branch, another location, Waiting expiry, At Risk/Stale Inbox attention, and Resolved behavior.
  5. Test Graph Playback after changing a user’s DataRole or location and confirm historical mode exposes no mutation controls.

Copy/paste the complete ActiveWorkplace experience

The native block already combines root-record search and pinning, bounded graph capture, Pulse state, participants, comments, Inbox attention, graph refresh, and read-only playback. Builder props set safe defaults; the server remains authoritative.

{
  "blocks": [
    {
      "_id": "active-work", "_type": "module.active-workplace",
      "props": {
        "allowedRootModuleKeys": [], "maxDepth": 2, "maxNodes": 100,
        "staleAfterMinutes": 4320, "warningBeforeStaleMinutes": 720,
        "participantTypes": ["User", "GoClaw", "Workflow"],
        "defaultGoClawParticipantIds": [], "commentsEnabled": true, "playbackEnabled": true
      },
      "children": []
    }
  ]
}

Custom unstyled React list, graph, people, and activity

The list is server-paged. Detail returns a cycle-safe graph snapshot capped by the workplace's reviewed depth/node policy, up to depth 5 and 200 nodes; hidden nodes and their edges are absent before React receives the response.

import { FormEvent, useEffect, useMemo, useState } from "react";
import { activeWorkplaceStatusLabel, type ActiveWorkplaceDetail, type ActiveWorkplaceList } from "@buildwithhq/module-sdk";
import { getActiveWorkplace, listActiveWorkplaces } from "./api";

const empty: ActiveWorkplaceList = { contractVersion: 1, pageNumber: 1, pageSize: 50, totalRecords: 0, totalPages: 0, items: [] };

export function UnstyledActiveWorkplace({ ownerUserId = "", participantId = "" }) {
  const [draft, setDraft] = useState("");
  const [search, setSearch] = useState("");
  const [status, setStatus] = useState("");
  const [page, setPage] = useState(1);
  const [result, setResult] = useState<ActiveWorkplaceList>(empty);
  const [detail, setDetail] = useState<ActiveWorkplaceDetail | null>(null);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const controller = new AbortController();
    listActiveWorkplaces(search, status, page, controller.signal, 50, ownerUserId, participantId)
      .then(setResult)
      .catch((caught: unknown) => { if (!controller.signal.aborted) setError(caught instanceof Error ? caught.message : "Workplaces could not be loaded."); });
    return () => controller.abort();
  }, [ownerUserId, page, participantId, search, status]);

  const nodesByDepth = useMemo(() => {
    const grouped = new Map<number, ActiveWorkplaceDetail["graph"]["nodes"]>();
    for (const node of detail?.graph.nodes || []) { const depth = node.depth || 0; grouped.set(depth, [...(grouped.get(depth) || []), node]); }
    return [...grouped.entries()].sort(([left], [right]) => left - right);
  }, [detail]);

  function submit(event: FormEvent) { event.preventDefault(); setPage(1); setSearch(draft.trim()); }
  async function open(activeWorkplaceId: string) { setDetail(await getActiveWorkplace(activeWorkplaceId)); }

  return <section className="custom-active-workplace">
    <h1>ActiveWorkplace</h1>
    <form role="search" onSubmit={submit}><label>Find work<input value={draft} maxLength={200} onChange={event => setDraft(event.target.value)} /></label><label>Pulse<select value={status} onChange={event => { setStatus(event.target.value); setPage(1); }}><option value="">All</option>{["Active", "Waiting", "AtRisk", "Stale", "Dormant", "Resolved"].map(value => <option key={value}>{value}</option>)}</select></label><button>Search</button></form>
    {error && <p role="alert">{error}</p>}
    <div className="workplace-columns">
      <aside><ol>{result.items.map(item => <li key={item.activeWorkplaceId}><button onClick={() => void open(item.activeWorkplaceId)}><strong>{item.displayName}</strong><span>{activeWorkplaceStatusLabel(item.status)} - {item.ownerDisplayName}</span><small>{item.participantCount} people/agents - {item.pendingInboxCount} attention items</small></button></li>)}</ol></aside>
      <main>{detail ? <><header><h2>{detail.displayName}</h2><strong>{activeWorkplaceStatusLabel(detail.status)}</strong><p>{detail.rootRecord.title} ({detail.rootRecord.moduleName})</p></header><section><h3>Connected records</h3>{nodesByDepth.map(([depth, nodes]) => <div key={depth}><h4>{depth === 0 ? "Root" : `Depth ${depth}`}</h4>{nodes.map(node => <article key={node.recordId}><strong>{node.title}</strong><span>{node.moduleName} - {node.locationName || "All locations"}</span></article>)}</div>)}</section><section><h3>Participants</h3><ul>{detail.participants.map(person => <li key={person.activeWorkplaceParticipantId}>{person.displayName} - {person.participantType} - {person.responsibilityText || "Watching"}</li>)}</ul></section><section><h3>Activity</h3><ol>{detail.activity.map(item => <li key={item.activeWorkplaceEventId}><strong>{item.summary}</strong> <small>{item.actorDisplayName || item.actorType} - {new Date(item.eventAtUtc).toLocaleString()}</small></li>)}</ol></section></> : <p>Select a workplace.</p>}</main>
    </div>
    <nav aria-label="Workplace pages"><button disabled={page <= 1} onClick={() => setPage(value => value - 1)}>Previous</button><span>Page {result.pageNumber} of {Math.max(1, result.totalPages)}</span><button disabled={page >= result.totalPages} onClick={() => setPage(value => value + 1)}>Next</button></nav>
  </section>;
}

Pin a record, replace settings, and move the Pulse

Create uses a visible canonical root RecordId. Update and Pulse changes are optimistic: always send the latest updatedUtc and reload after success or a 409 conflict.

import type { ActiveWorkplaceDetail, ActiveWorkplaceStatus } from "@buildwithhq/module-sdk";
import { createActiveWorkplace, getActiveWorkplace, setActiveWorkplaceStatus, updateActiveWorkplace } from "./api";

export async function pinRecord(rootRecordId: string) {
  const created = await createActiveWorkplace({ rootRecordId, priority: 2, graphScope: { maxDepth: 2, maxNodes: 100, playbackEnabled: true }, staleAfterMinutes: 4320, warningBeforeStaleMinutes: 720 });
  return getActiveWorkplace(created.activeWorkplaceId);
}

export async function renameWorkplace(current: ActiveWorkplaceDetail, displayName: string) {
  await updateActiveWorkplace(current.activeWorkplaceId, { displayName, ownerUserId: current.ownerUserId, priority: current.priority, graphScope: current.graphScope, staleAfterMinutes: current.staleAfterMinutes, warningBeforeStaleMinutes: current.warningBeforeStaleMinutes, expectedUpdatedUtc: current.updatedUtc });
  return getActiveWorkplace(current.activeWorkplaceId);
}

export async function changePulse(current: ActiveWorkplaceDetail, status: ActiveWorkplaceStatus, waiting?: { untilUtc?: string; reason?: string }) {
  await setActiveWorkplaceStatus(current.activeWorkplaceId, { status, waitingUntilUtc: status === "Waiting" ? waiting?.untilUtc : undefined, waitingReason: status === "Waiting" ? waiting?.reason : undefined, expectedUpdatedUtc: current.updatedUtc });
  return getActiveWorkplace(current.activeWorkplaceId);
}

Participants, governed GoClaw, comments, refresh, and playback

Select participants only from the server catalog. Assignment expresses responsibility; it does not grant data access. A GoClaw remains bound to its effective user, AI-read scope, action permission, and approval policy.

import type { ActiveWorkplaceDetail, ActiveWorkplaceParticipantWrite } from "@buildwithhq/module-sdk";
import { addActiveWorkplaceParticipant, getActiveWorkplace, getActiveWorkplaceParticipantCatalog, getActiveWorkplacePlayback, recordActiveWorkplaceActivity, refreshActiveWorkplaceGraph, removeActiveWorkplaceParticipant } from "./api";

export const participantCatalog = (workplaceId: string) => getActiveWorkplaceParticipantCatalog(workplaceId);

export async function addParticipant(current: ActiveWorkplaceDetail, participant: ActiveWorkplaceParticipantWrite) {
  if (!current.canEdit) throw new Error("This workplace cannot be edited.");
  await addActiveWorkplaceParticipant(current.activeWorkplaceId, participant);
  return getActiveWorkplace(current.activeWorkplaceId);
}

export async function addGovernedGoClaw(current: ActiveWorkplaceDetail, participantId: string) {
  return addParticipant(current, { participantType: "GoClaw", participantId, responsibilityText: "Monitor changes and prepare suggestions", isWatcher: true, canAct: false, approvalPolicy: { materialActions: "humanApproval" } });
}

export async function removeParticipant(current: ActiveWorkplaceDetail, activeWorkplaceParticipantId: string) {
  await removeActiveWorkplaceParticipant(current.activeWorkplaceId, activeWorkplaceParticipantId);
  return getActiveWorkplace(current.activeWorkplaceId);
}

export async function postUpdate(current: ActiveWorkplaceDetail, summary: string) {
  await recordActiveWorkplaceActivity(current.activeWorkplaceId, { eventType: "Comment", summary, isMeaningfulActivity: true });
  return getActiveWorkplace(current.activeWorkplaceId);
}

export async function refreshGraph(current: ActiveWorkplaceDetail) { await refreshActiveWorkplaceGraph(current.activeWorkplaceId); return getActiveWorkplace(current.activeWorkplaceId); }
export const playBackReadOnly = (current: ActiveWorkplaceDetail, asOfUtc: string) => getActiveWorkplacePlayback(current.activeWorkplaceId, asOfUtc);

Optional starter styling

.custom-active-workplace { width: 100%; max-width: none; }
.custom-active-workplace > form, .custom-active-workplace > nav { align-items: end; display: flex; flex-wrap: wrap; gap: .75rem; }
.workplace-columns { display: grid; gap: 1rem; grid-template-columns: 280px minmax(0, 1fr); margin: 1rem 0; }
.workplace-columns ol { list-style: none; margin: 0; padding: 0; }
.workplace-columns aside button { background: transparent; border: 0; display: grid; gap: .2rem; padding: .75rem; text-align: left; width: 100%; }
.workplace-columns main { border: 1px solid var(--line, #d8dee8); padding: 1rem; }
.workplace-columns main section article { border-left: 3px solid var(--accent, #4967d5); display: grid; margin: .5rem 0; padding: .5rem .75rem; }
@media (max-width: 760px) { .workplace-columns { grid-template-columns: 1fr; } }

Exact lifecycle and data path

PurposeRouteProcedure
List/detailGET /api/modules/active-workplace and /{activeWorkplaceId}sp_ActiveWorkplace_ListSecured, sp_ActiveWorkplace_GetSecured
Pin/replace/PulsePOST /api/modules/active-workplace, PATCH /{id}, POST /{id}/statussp_ActiveWorkplace_CreateSecured, sp_ActiveWorkplace_UpdateSecured, sp_ActiveWorkplace_SetStatusSecured
ParticipantsGET /{id}/participants/catalog, POST /{id}/participants, DELETE /{id}/participants/{participantId}sp_ActiveWorkplace_GetParticipantCatalogSecured, sp_ActiveWorkplace_AddParticipantSecured, sp_ActiveWorkplace_RemoveParticipantSecured
Activity/graphPOST /{id}/activity, POST /{id}/graph/refreshsp_ActiveWorkplace_RecordActivitySecured, sp_ActiveWorkplace_RefreshGraphSecured
Read-only historyGET /{id}/playback?at=...sp_ActiveWorkplace_GetPlaybackSecured

At Risk and Stale transitions create-or-touch Universal Inbox attention instead of duplicating alerts. Playback is explicitly readOnly: true and intersects retained history with the viewer's current permissions.

Build a professional ActiveWorkplace dashboard

These six registry-backed presentation blocks let a designer turn the secured ActiveWorkplace API into a complete admin page without writing a chart, grid, status badge, empty state, or timeline from scratch. The normal operational API begins at /api/modules/active-workplace; a dashboard-wide count or trend should come from a separate purpose-built presentation binding so the browser never downloads a broad record population to calculate one number.

The ZIP contains this feature's fictional design composition at pages/first-class/active-workplace-sample.json, its executable authenticated page at pages/first-class/active-workplace-live.json, and the catalog-driven FirstClassPresentationGallery.tsx. Use the sample only for visual design. The live page calls the real native API and reviewed stored procedures under the signed-in user's scope.

Payload kindRuntime blockUseful ActiveWorkplace projection
metric-setcore.metric-stripActive, healthy, at-risk, blocked, and inactive counts
entity-listcore.entity-listWorkspaces requiring the current participant's attention
progress-listcore.progress-listDistribution by health, owner, team, or state
series-chartcore.series-chartUpdates, handoffs, completed work, and blockers
data-gridcore.presentation-gridOne bounded participant-authorized workspace page
timelinecore.timelineCreate, participant, relation, update, handoff, blocker, and completion

Copy/paste design preview: all six blocks

This complete static page document renders immediately in Puck/Monaco and is useful while styling a template. Its names, counts, dates, and IDs are fictional design fixtures; static preview values are not live tenant facts.

Copy the complete six-block page JSON
{
  "blocks": [
    {
      "_id": "active-workplace-metrics",
      "_type": "core.metric-strip",
      "props": {
        "title": "ActiveWorkplace operations",
        "asOfUtc": "2026-09-04T18:00:00Z",
        "items": [
          {
            "key": "active",
            "label": "Active workspaces",
            "value": 38,
            "format": "number",
            "tone": "primary"
          },
          {
            "key": "attention",
            "label": "Need attention",
            "value": 7,
            "format": "number",
            "tone": "warning"
          },
          {
            "key": "blocked",
            "label": "Blocked",
            "value": 3,
            "format": "number",
            "tone": "danger"
          },
          {
            "key": "healthy",
            "label": "On track",
            "value": 28,
            "format": "number",
            "tone": "success"
          }
        ]
      },
      "children": []
    },
    {
      "_id": "active-workplace-recent",
      "_type": "core.entity-list",
      "props": {
        "title": "Workspaces needing attention",
        "hasMore": true,
        "items": [
          {
            "id": "active-workplace-sample-1",
            "recordId": "active-workplace-record-1",
            "primary": "West region rollout",
            "secondary": "8 participants - 3 related records",
            "status": {
              "key": "at-risk",
              "label": "At risk",
              "tone": "warning"
            },
            "trailing": "2 blockers"
          },
          {
            "id": "active-workplace-sample-2",
            "recordId": "active-workplace-record-2",
            "primary": "West region rollout - Follow-up",
            "secondary": "8 participants - 3 related records - Updated two hours ago by the assigned owner",
            "status": {
              "key": "in-review",
              "label": "In review",
              "tone": "primary"
            },
            "trailing": "Today"
          },
          {
            "id": "active-workplace-sample-3",
            "recordId": "active-workplace-record-3",
            "primary": "West region rollout - West region",
            "secondary": "8 participants - 3 related records - Related to three visible records at the Reno location",
            "status": {
              "key": "on-track",
              "label": "On track",
              "tone": "success"
            },
            "trailing": "3 related"
          },
          {
            "id": "active-workplace-sample-4",
            "recordId": "active-workplace-record-4",
            "primary": "West region rollout - Customer response",
            "secondary": "8 participants - 3 related records - Waiting for an external response before work can continue",
            "status": {
              "key": "scheduled",
              "label": "Scheduled",
              "tone": "warning"
            },
            "trailing": "Tomorrow"
          },
          {
            "id": "active-workplace-sample-5",
            "recordId": "active-workplace-record-5",
            "primary": "West region rollout - Regional operations review with a deliberately long title",
            "secondary": "8 participants - 3 related records - This deliberately longer supporting line verifies wrapping, truncation, responsive spacing, and dense dashboard behavior.",
            "status": {
              "key": "needs-attention",
              "label": "Needs attention",
              "tone": "danger"
            },
            "trailing": "Review",
            "tertiary": "Long-content fixture: verify keyboard focus, wrapping, narrow columns, and mobile overflow before publishing."
          },
          {
            "id": "active-workplace-sample-6",
            "recordId": "active-workplace-record-6",
            "primary": "West region rollout - Completed preview",
            "secondary": "8 participants - 3 related records - Closed after review with its related evidence retained",
            "status": {
              "key": "complete",
              "label": "Complete",
              "tone": "success"
            },
            "trailing": "Closed"
          }
        ]
      },
      "children": []
    },
    {
      "_id": "active-workplace-bystatus",
      "_type": "core.progress-list",
      "props": {
        "title": "Workspace health",
        "items": [
          {
            "key": "track",
            "label": "On track",
            "value": 28,
            "maximum": 38,
            "displayValue": "28",
            "tone": "success",
            "status": {
              "key": "track",
              "label": "On track",
              "tone": "success"
            }
          },
          {
            "key": "risk",
            "label": "At risk",
            "value": 7,
            "maximum": 38,
            "displayValue": "7",
            "tone": "warning",
            "status": {
              "key": "risk",
              "label": "At risk",
              "tone": "warning"
            }
          },
          {
            "key": "blocked",
            "label": "Blocked",
            "value": 3,
            "maximum": 38,
            "displayValue": "3",
            "tone": "danger",
            "status": {
              "key": "blocked",
              "label": "Blocked",
              "tone": "danger"
            }
          }
        ]
      },
      "children": []
    },
    {
      "_id": "active-workplace-trend",
      "_type": "core.series-chart",
      "props": {
        "title": "Workplace activity",
        "variant": "bar",
        "defaultPeriodKey": "d7",
        "periods": [
          {
            "key": "d7",
            "label": "7 days",
            "labels": [
              "Fri",
              "Sat",
              "Sun",
              "Mon",
              "Tue",
              "Wed",
              "Thu"
            ],
            "series": [
              {
                "key": "primary",
                "label": "Updates",
                "tone": "primary",
                "values": [
                  8,
                  5,
                  4,
                  12,
                  15,
                  11,
                  17
                ]
              },
              {
                "key": "secondary",
                "label": "Completed items",
                "tone": "success",
                "values": [
                  6,
                  4,
                  3,
                  9,
                  12,
                  10,
                  14
                ]
              }
            ]
          }
        ]
      },
      "children": []
    },
    {
      "_id": "active-workplace-table",
      "_type": "core.presentation-grid",
      "props": {
        "title": "Active workspaces",
        "columns": [
          {
            "key": "workspace",
            "label": "Workspace",
            "type": "text",
            "align": "left"
          },
          {
            "key": "owner",
            "label": "Owner",
            "type": "text",
            "align": "left"
          },
          {
            "key": "participants",
            "label": "Participants",
            "type": "number",
            "align": "right"
          },
          {
            "key": "health",
            "label": "Health",
            "type": "status",
            "align": "left"
          },
          {
            "key": "updated",
            "label": "Updated",
            "type": "date",
            "align": "left"
          }
        ],
        "rows": [
          {
            "id": "active-workplace-row-1",
            "recordId": "active-workplace-record-1",
            "cells": {
              "workspace": "West region rollout",
              "owner": "Maya Chen",
              "participants": 8,
              "health": {
                "key": "risk",
                "label": "At risk",
                "tone": "warning"
              },
              "updated": "2026-09-04T17:02:00Z"
            }
          },
          {
            "id": "active-workplace-row-2",
            "recordId": "active-workplace-record-2",
            "cells": {
              "workspace": "West region rollout - Follow-up",
              "owner": "Maya Chen",
              "participants": 9,
              "health": {
                "key": "in-review",
                "label": "In review",
                "tone": "primary"
              },
              "updated": "2026-09-04T15:42:00Z"
            }
          },
          {
            "id": "active-workplace-row-3",
            "recordId": "active-workplace-record-3",
            "cells": {
              "workspace": "West region rollout - West region",
              "owner": "Maya Chen",
              "participants": 10,
              "health": {
                "key": "on-track",
                "label": "On track",
                "tone": "success"
              },
              "updated": "2026-09-04T12:18:00Z"
            }
          },
          {
            "id": "active-workplace-row-4",
            "recordId": "active-workplace-record-4",
            "cells": {
              "workspace": "West region rollout - Customer response",
              "owner": "Maya Chen",
              "participants": 11,
              "health": {
                "key": "scheduled",
                "label": "Scheduled",
                "tone": "warning"
              },
              "updated": "2026-09-03T21:07:00Z"
            }
          },
          {
            "id": "active-workplace-row-5",
            "recordId": "active-workplace-record-5",
            "cells": {
              "workspace": "West region rollout - Regional operations review with a deliberately long title",
              "owner": "Maya Chen - This deliberately longer supporting line verifies wrapping, truncation, responsive spacing, and dense dashboard behavior.",
              "participants": 12,
              "health": {
                "key": "needs-attention",
                "label": "Needs attention",
                "tone": "danger"
              },
              "updated": "2026-09-03T16:31:00Z"
            }
          },
          {
            "id": "active-workplace-row-6",
            "recordId": "active-workplace-record-6",
            "cells": {
              "workspace": "West region rollout - Completed preview",
              "owner": "Maya Chen",
              "participants": 13,
              "health": {
                "key": "complete",
                "label": "Complete",
                "tone": "success"
              },
              "updated": "2026-09-02T19:14:00Z"
            }
          }
        ],
        "page": {
          "pageNumber": 1,
          "pageSize": 6,
          "totalRecords": 38,
          "totalIsExact": true,
          "hasMore": true
        }
      },
      "children": []
    },
    {
      "_id": "active-workplace-timeline",
      "_type": "core.timeline",
      "props": {
        "title": "Workspace activity",
        "hasMore": true,
        "items": [
          {
            "id": "active-workplace-event-1",
            "recordId": "active-workplace-record-1",
            "occurredUtc": "2026-09-04T17:58:00Z",
            "title": "Blocker added",
            "description": "Network approval is blocking the Reno rollout.",
            "actor": "Jordan Lee",
            "tone": "danger"
          },
          {
            "id": "active-workplace-event-2",
            "recordId": "active-workplace-record-2",
            "occurredUtc": "2026-09-04T15:42:00Z",
            "title": "Blocker added - Follow-up",
            "description": "Network approval is blocking the Reno rollout. Updated two hours ago by the assigned owner.",
            "actor": "Avery Patel",
            "tone": "primary"
          },
          {
            "id": "active-workplace-event-3",
            "recordId": "active-workplace-record-3",
            "occurredUtc": "2026-09-04T12:18:00Z",
            "title": "Blocker added - West region",
            "description": "Network approval is blocking the Reno rollout. Related to three visible records at the Reno location.",
            "actor": "Sam Rivera",
            "tone": "success"
          },
          {
            "id": "active-workplace-event-4",
            "recordId": "active-workplace-record-4",
            "occurredUtc": "2026-09-03T21:07:00Z",
            "title": "Blocker added - Customer response",
            "description": "Network approval is blocking the Reno rollout. Waiting for an external response before work can continue.",
            "actor": "Maya Chen",
            "tone": "warning"
          },
          {
            "id": "active-workplace-event-5",
            "recordId": "active-workplace-record-5",
            "occurredUtc": "2026-09-03T16:31:00Z",
            "title": "Blocker added - Regional operations review with a deliberately long title",
            "description": "Network approval is blocking the Reno rollout. This deliberately longer supporting line verifies wrapping, truncation, responsive spacing, and dense dashboard behavior.",
            "actor": "Automation",
            "tone": "danger"
          },
          {
            "id": "active-workplace-event-6",
            "recordId": "active-workplace-record-6",
            "occurredUtc": "2026-09-02T19:14:00Z",
            "title": "Blocker added - Completed preview",
            "description": "Network approval is blocking the Reno rollout. Closed after review with its related evidence retained.",
            "actor": "Jordan Lee",
            "tone": "success"
          }
        ]
      },
      "children": []
    }
  ]
}

Copy/paste React composition

Copy InteractivePresentationComponents.tsx and its optional CSS from the Professional Foundation Developer Kit, then add this module-specific composition. It is semantic and unstyled by default; pass styled after importing interactive-presentation-components.css for the supplied polished foundation. Either version accepts only a bounded already-authorized document and fails closed through the shared strict parsers.

import {
  EntityList,
  MetricStrip,
  PresentationGrid,
  ProgressList,
  SeriesChart,
  Timeline,
} from "./InteractivePresentationComponents";

export interface ActiveWorkplacePresentationData {
  readonly metrics: unknown;
  readonly recent: unknown;
  readonly byStatus: unknown;
  readonly trend: unknown;
  readonly table: unknown;
  readonly timeline: unknown;
}

export interface ActiveWorkplacePresentationProps {
  /** Pass only the already-authorized presentation document returned by the API. */
  readonly data?: ActiveWorkplacePresentationData | null;
  readonly loading?: boolean;
  readonly error?: boolean;
  readonly styled?: boolean;
  /** Record identity is navigation context; the detail API must authorize it again. */
  readonly onOpenRecord?: (recordId: string) => void;
}

export function ActiveWorkplacePresentation({
  data,
  loading = false,
  error = false,
  styled = false,
  onOpenRecord,
}: ActiveWorkplacePresentationProps) {
  if (error) return <p role="alert">The ActiveWorkplace presentation could not be loaded.</p>;
  if (loading || !data) return <p role="status">Loading ActiveWorkplace presentation...</p>;

  return (
    <main className={styled ? "bwhq-api-example" : undefined}>
      <header>
        <p>ActiveWorkplace</p>
        <h1>ActiveWorkplace operations</h1>
        <p>Coordinated workspaces, health, ownership, dependencies, participation, and recent work.</p>
      </header>

      <MetricStrip data={data.metrics} styled={styled} />
      <div className={styled ? "bwhq-api-example__split" : undefined}>
        <ProgressList data={data.byStatus} styled={styled} />
        <EntityList data={data.recent} styled={styled} onOpenRecord={onOpenRecord} />
      </div>
      <SeriesChart data={data.trend} styled={styled} />
      <PresentationGrid data={data.table} styled={styled} onOpenRecord={onOpenRecord} />
      <Timeline data={data.timeline} styled={styled} onOpenRecord={onOpenRecord} />
    </main>
  );
}

Copy the live, authenticated module page

This document has no placeholder key and needs no invented endpoint. Save it to a page and add that page to a User Type menu. The registered native component calls /api/modules/active-workplace, uses the current tenant session, and preserves the module's real list, detail, create/update, pagination, empty, loading, and error behavior. Dynamic Records discovers the organization's real tenant-owned modules when no module key is configured.

Copy the executable live page
{
  "blocks": [
    {
      "_id": "active-workplace-live",
      "_type": "module.active-workplace",
      "props": {},
      "children": []
    }
  ]
}

The server derives SaaS app, organization, user, DataRoles, locations, module-specific membership/privacy, and any AI-read gate from verified identity. A returned identifier can select a detail target, but the detail or write endpoint authorizes it again. Page layout, status, tone, totals, action names, and identifiers never grant authority.

Tip

Start with depth 2, at most 100 nodes, conservative stale timing, comments enabled, and playback enabled. Add one default GoClaw watcher only after its represented user and approval policy are correct. Builder settings shape behavior but never replace server authorization.

Important

A renderer being bundled in the tenant application does not make its data visible in every app. The server returns only components and records authorized for the current app and signed-in user; unavailable or unauthorized blocks fail closed.

Capability review: 2026-09-14. For exact current technical availability, use the generated API Map and first-class module inventory.