Skip to content

Worked path: blank tenant to tenant enhancement

One worked path, start to finish: assume (or provision) an empty customer tenant, then land one tenant-level enhancement: a scoped capability backed by a skill, a tool/MCP install, and a connector binding, verified in governed sessions and handed over. Each step is labeled [product] (the platform enforces it; surfaces, APIs, and tables from pasted sources) or [practice] (field discipline this guide recommends; the platform does not enforce it).

Grounding: [product] steps below (provisioning workflow, /preparing to /onboarding, MCP catalog/install model, binding contract, approval gates) are from the pasted tenant-lifecycle, customer-onboarding, MCP admin, and connector-contract sources. [practice] steps (scope doc, probe sequencing, capabilities register, training flow) are field practice: how to rehearse and verify, not what the product enforces.

Stage 0: start from an empty customer tenant

Section titled “Stage 0: start from an empty customer tenant”

Assume a freshly provisioned customer tenant with nothing customized, or provision one. Either way, confirm emptiness before building.

  • [product] Tenant exists via /admin/tenants Create tenant (requires PRESH org-1 membership and platform_ops in org 1; API calls require org_id=1). Kind Customer; slug picked (presh reserved); hostname <slug>.preshos.com or a custom hostname entered at Create. Full sequence: New-tenant checklist.
  • [product] provision-tenant Inngest workflow ran, in order: registry, branding, hostname, config, RBAC, mint_workos_org, link_registry, attach_domains, vault_placeholders, ai_gateway_key (token-gated/overridable, skippable without blocking core-ready), verify_defaults, seed_default_agents, seed_owner and send_invite, converge_post_owner, vercel_alias (required for core-ready).
  • [product] Readiness confirmed by polling GET /api/v1/admin/tenants/[id]/provisioning and evaluateTenantReadiness, not by guessing. Alias re-verified after any redeploy that moves traffic.
  • [practice] Emptiness confirmed: no custom environments beyond seed_default_agents output, no tenant MCP installs, no connector bindings for this workload. Record the baseline (hostname, org, date). The enhancement diffs against this.
FDE blank to live: discovery, environment, skills tools MCP, approvals, governed session, handoff

Stage order: Create tenant in /admin/tenants, provision-tenant workflow, core-ready (includes vercel_alias), /preparing to /onboarding, empty tenant with baseline recorded.

Stage 1: walk /preparing to /onboarding to dashboard

Section titled “Stage 1: walk /preparing to /onboarding to dashboard”
  • [product] Owner invite accepted on the tenant hostname (invite is hostname-bound; hostname wins for multi-tenant identities).
  • [product] /preparing waited through if seen. Provisioning finishing, not a second-tenant signal. Do not re-register.
  • [product] Onboarding wizard completed (app/(onboarding)/onboarding to /onboarding/*): organization name (org-name) required; domain, branding, members, connectors deferrable.
  • [product] Dashboard reached; org identity confirmed in Settings. Customer APIs live under /api/v1/orgs/[id]/*.
  • [practice] Day-0 recorded against the Day-0 checklist: invite, hostname, preparing, wizard, home, Settings, first governed session.

Stage 2: scope the enhancement (one workload)

Section titled “Stage 2: scope the enhancement (one workload)”

Do not build yet. Write the one-page scope doc first (Discovery).

  • [practice] Workload named (2 to 3 concrete case types, not “everything in the queue”); in-scope systems and data (queues, groups, windows) listed; exclusions written; org_id context pinned.
  • [practice] Read needs vs. change needs separated (draft vs. execute); risky actions listed (irreversible, customer-visible, cross-system); approver roles named by role (Roles).
  • [practice] Connector gaps filed as requests with the ops intake (R4). Code is not connected: HubSpot and ConnectWise PSA are the registered adapters; Salesforce scaffolds are not implementations; outbound HubSpot writes are disabled.
  • [practice] Work owners signed off: “yes, this is the work.” Success defined as an observable pilot outcome.
Workload: <name>, org scope: <org_id>, systems: <explicit>, data: <queues/groups/windows>
Out of scope: <explicit>, risky: <list>, approvers: <roles>, connector gaps: <system and request status>
Success: <observable pilot outcome>

Stage 3: build the environment narrow, verify before users

Section titled “Stage 3: build the environment narrow, verify before users”

Translate the scope doc into context, tools, and policy (Environment).

  • [practice] Context covers exactly the workload’s systems, nothing adjacent “just in case”; data boundaries concrete; exclusions preserved as exclusions.
  • [practice] Tool set minimal: reads needed now, drafts for consequential outputs, executes only where the workload requires. No bonus tools.
  • [product] Connector deps honest: nothing marked connected that is not verified in-environment. Bindings need org, package, and connection coordinates in install settings.object_mappings (SDK concepts).
  • [practice] Probe sequence run in order as test sessions: happy-path read, boundary probe, draft quality, gate check, denial path, wrong-org check (org_id correct). Each passes before the next; failures loop back to the build.

Stage 4: add the capability (skill and tool/MCP install)

Section titled “Stage 4: add the capability (skill and tool/MCP install)”

Capabilities turn the scoped but empty environment into one that does the workload (Skills, tools and MCP). Sequencing: tools first, skills second, wiring verified last.

  • [product] MCP path chosen deliberately and recorded: catalog install (ai.mcp_catalog_server_version to tenant ai.mcp_servers via POST /api/v1/mcp-servers/install-from-catalog) or custom tenant MCP (/ai/mcp-servers/new, catalog_server_id null, with operational rechecks and fingerprint recheck and DNS-pinned guarded fetch). Browse at /ai/mcp-servers, discover at /ai/mcp-servers/discover.
  • [product] Install landed in the tenant’s ai.mcp_servers under the correct org_id (one tenant’s installs never leak into another’s). OAuth profile confirmed if applicable (com.google.drive/mcp, com.hubspot/mcp).
  • [product] Fingerprint recheck and DNS-pinned guarded fetch observed working before pilot users arrive. Installed is not trusted; rechecked is.
  • [practice] Skill encoded once tools are solid (order of operations, what to gather before acting, when to stop and ask); each piece verified standalone plus failure modes observed once on purpose; scope and approval behavior confirmed per piece.
  • [practice] Capabilities register extended: capability, layer (skill, tool, MCP install and binding), status (specified or verified), verification date, notes.

Stage 5: bind the connector-backed tool (if the enhancement reads external records)

Section titled “Stage 5: bind the connector-backed tool (if the enhancement reads external records)”

A connector tool is only real for the tenant when its binding exists (Extend).

  • [product] Bindings written in install settings.object_mappings with all three coordinates (org, package, and connection); identity binding:<uuid> in ai.connector_object_map (new bindings get new UUIDs).
  • [product] Destination from target-catalog.ts, for example targetObject: 'work-items' with workItemTypeId; never retired tasks/deliverables. Edited through the shared UI (components/integrations/package-object-mappings.tsx) or Admin API /api/v1/integration-packages/[packageKey]/object-mappings (object-mapping-contract.ts to object-mapping-store.ts).
  • [product] Import runs from an authorized runner: syncConnectorObjectMappings({ orgId, connectionId, packageKey }) via a function-catalog Inngest function (never connector-sync-runner); watermark advances only when failed === 0. Full runnable pass: E2E: HubSpot inbound import.
  • [practice] End-to-end chain verified in-environment: skill to tools (via MCP install where applicable), under environment policy, gates firing. Contract-test evidence (create, update, retry, pause) recorded for the affected org, package, and connection.

Stage 6: prove it in governed sessions, design approvals

Section titled “Stage 6: prove it in governed sessions, design approvals”
  • [practice] Approval matrix built from the scope doc’s risky actions: action class, allow or gate or deny-by-default, approver role, what the approver sees (what, on-what, why, blast radius). Approvers by role, not name. Full method: Approvals design.
  • [product + practice] Matrix verified in probe sessions: each gated class fires its gate with complete content; allow path runs with a complete record; deny path degrades gracefully; deny-by-default classes unreachable via approval.
  • [practice] Pilot with real users on real goals (not staged demos). One governed session to a recorded outcome minimum; denial patterns read as design feedback, then loop back (environment, capabilities, approvals) as needed.

Stage 7: hand over the tenant-level enhancement

Section titled “Stage 7: hand over the tenant-level enhancement”
  • [practice] Pre-handoff gate holds: pilot ran on real goals; environment spec, capabilities register, and approval matrix current; probes re-run after the last change; connector states honest (connected, requested, deferred); open items ticketed with owners and dates, none verbal.
  • [practice] Each role trained on their slice with live pairing: users (Tenant users), operators (User sessions path), admins (Tenant admins).
  • [practice] Handoff pack delivered: scope doc, environment spec, capabilities register, approval matrix, open items list, rhythm one-pager. Week-2 check-in scheduled; pilot success criteria measured; platform learnings fed back to ops and product.

Docs futures, not blocking: checklists on this site are currently static Markdown (no persisted per-reader state), and site search stays off. Pagefind is disabled because the SSR password gate means no static HTML is emitted to index (see astro.config.mjs). Interactive checklists and search are future work, tracked, not part of this path.