Build MCP
Build cookbook: Security and runtime boundaries
Private routes, secrets, viewer identity and the runtime boundaries an artifact app must keep.
Security and Runtime Boundaries
Treat the artifact package as an untrusted application boundary with only declared platform capabilities. A successful local build does not authorize a cloud, database, identity, or publish operation.
Viewer and routes
Set viewerPolicy to private or tenant. Route APIs under /_artifact/*
and call them relatively from browser code (./_artifact/...) so draft, live,
and immutable-version paths continue to work. Never call platform /api/*, use
a root-absolute artifact fetch, or add an undeclared absolute URL.
The viewer-scoped binding path is intentionally narrow: it requires a signed-in
viewer, resource: "customers", and emailField: "email"; the runtime filters
to the matching viewer. It is not a replacement for arbitrary source ACLs.
Data, secrets, and private state
Use catalog/read-only tools and bounded declared datasets for source data. Do not put database URLs, source API credentials, keys, passwords, bearer tokens, or cloud credentials in source, manifests, browser bundles, or ordinary env variables. The app runtime must not connect directly to Postgres.
For a third-party API, declare an exact region-matching Secrets Manager ARN in
secretBindings[]. The runtime receives the ARN and resolves the value with
its least-privilege role (platformSecrets.get(...) in Node or
get_secret(...) in Python). Keep vendor calls server-side behind a declared
artifact route.
When a private tool needs its own durable state during authoring, use the
guarded run_artifact_workspace_sql namespace for that task/artifact. Source
and analytics reads remain on run_psql; workspace-table writes must be derived
or operator-provided and documented. Do not use it as an unscoped platform
database escape hatch.
Webhooks and Bedrock
An ordinary private API route depends on the platform viewer/session check. External provider webhooks are not artifact-native today: raw function URLs require AWS IAM, stable routes authorize a viewer, required provider headers are not a general forwarding contract, and no transactional ingress-idempotency store is declared by the manifest. Route webhook ingestion to a reviewed platform service; an artifact may visualize its approved status data later.
The narrow machine-ingress exception is a validated, promoted
kind: "mcp_server" deployment at exact /_artifact/mcp. It uses FastMCP
3.4.7 Streamable HTTP with stateless JSON responses. Topline creates and keeps
the bearer private, IAM-signs the Lambda request, and forwards only bounded MCP
protocol headers plus a trusted platform claim. The artifact never declares,
reads, rotates, or receives that credential. A workspace manager connects the
live artifact in Developer Access, reviews every tool, and explicitly enables
chat and/or coding agents before use.
For simple chat, use one bounded server-side Bedrock Converse call per turn on
a private /_artifact/api/* route. Use the platform-injected
platform_artifact_inference.BedrockInference helper and
PLATFORM_ARTIFACT_BEDROCK_MODEL_ID. The helper assumes the model-scoped Topline
production inference role with in-memory temporary credentials; customer data
and secret clients retain workload IAM. Customers never enable models in their
own AWS accounts. Validate/bound messages, mock the call in
local tests, and return a clear 503 if the model setting is absent. Do not
hardcode a model ID, request a Bedrock API key, put Bedrock in browser code, or
silently add tools, memory, streaming, history, or an agent loop.
Operator boundary
The sandbox must not run direct cloud deploy, IAM, database-write, or secret commands. Use bridge tools for the documented artifact lifecycle. If the needed bridge capability is absent, stop and name the missing tool; do not substitute an unapproved route.