Manifest and Targets
Define package behavior in tap-miniapp.config.ts. The SDK compiles that authoring input into the schema-v2 tap-miniapp.build.json, then writes the schema-v2 manifest.tap.json as the provider-neutral byte inventory used for local development and Marketplace publication.
Use the typed defineTapMiniapp(...) authoring API. Do not hand-edit generated build or source manifests. The published schemas exist for tools that inspect assembled output.
Package and Release Identity
Source packages do not contain TAP Registry package, publisher, organization, or release IDs. The AI Platform owns those identities:
- A linked local package receives device-local development identity from its exact source.
- A Marketplace import is attached to a workspace-owned package and receives a TAP release ID.
- Publishing moves an exact TAP release pointer. It does not rewrite package bytes or identity.
Keep versionLabel, presentation details, target names, expose names, and contribution IDs stable when they represent the same logical feature. They are source metadata, not Registry authority.
manifest.tap.json binds installation to artifact paths, byte lengths, SHA-256 digests, and target locks. The Marketplace release root derives from those exact bytes. Provider coordinates, URLs, display metadata, and MIME headers do not choose release identity.
Compatibility
Declare the oldest compatible host in the authoring config:
The SDK writes its own exact installed version to compatibility.tapSdk. Pin the SDK dependency to that exact version. Use a semantic-version range for tapHost that excludes hosts older than the behavior you require. The host verifies both values before activation.
Target Graphs
Each key under targets in the compiled build manifest identifies one independently compiled runtime graph. A target records:
- its unique Module Federation remote name;
- the remote entry and optional Federation manifest;
- the asset lock for the complete emitted graph;
- integrity values for the entry, manifest, lock, and each expose; and
- the runtime selected for each expose.
The SDK build owns integrity fields. Authoring inputs do not provide hashes. The assembled source manifest contains only final byte records.
Use different remote names and build directories for different targets. A desktop and mobile target can expose different modules while retaining the same package and release identity.
Contributions
Contributions connect a stable contribution ID to one or more target exposes. Common kinds include:
The JSON Schema is authoritative for all supported kinds and their options. Contribution IDs contain 1 to 256 ASCII letters, digits, underscores, or hyphens. Dots are not valid contribution-ID separators.
Every target selected by a contribution must exist in the package target map, and every expose must exist in that target's locked Federation graph. A mismatch fails before activation.
Every ui.surface also requires a top-level lifecycle.lifecycleExpose. Each
target selected by that surface must declare the lifecycle expose, and its
runtime must match the surface runtime. create-tap-miniapp generates the
canonical ./tap/lifecycle module and target wiring; keep that contract when
adding a local service or another contribution.
Declaring a Specialist
A package can ship its own specialist. Install registers it, it appears on the Specialists screen, and it can be used in a channel like any other specialist or invoked directly from your miniapp with no channel at all.
Four things are required. Each one fails with a symptom that names something else, so check all four before debugging anything deeper:
-
A specialist manifest file in the package at
specialists/<slug>/<version>.json. -
A
kind: specialistcontribution withlifecycleScope: "installation"and ahost-declarativetarget. -
That contribution ID listed in the
miniappcontribution'soptions.contributionIds. This is the step with no discoverable failure mode: omit it and the specialist simply never registers, with nothing reporting why. -
Enablement for the account or workspace that will use it. This is not something your manifest can grant itself:
A workspace install is opt-in on purpose — a package cannot switch itself on for everyone in a workspace. If your specialist appears in the Specialists screen but a turn reports it as unavailable, check this first.
The host resolves a declared specialist as <name>@<version> — for example
standup-drafter@0.2.0. That is the ID sdk.specialist.runTurnWithTools
expects, and the ID the host matches against the package's declared
specialists. A specialist the current package release does not declare is
rejected regardless of workspace visibility.
Do not use sdk.specialist.upsertManaged to make a specialist invokable.
Manifest declaration is the supported path; see
Specialists in the SDK reference.
Authorization
Use authorization.allOf only for named permission actions that must be
granted before the host projects the contribution. Use
authorization.onDemand for actions the mounted UI may request and check at
the point of use; denying or revoking one of these actions does not hide the
surface. Use authorization.effects to describe protected effects. All three
fields are declarations, not grants, so keep requested access specific to the
contribution and scope.
For authorization.allOf, the host requires a persisted direct-human grant for
each action at one of that action's catalog scopes. The UI contribution's scope
describes where the host mounts it; it does not force every required action to
use the same scope. A workspace surface can, for example, require both a
user-scoped profile action and a workspace-scoped data action. Every SDK
operation still enforces the exact principal and resource scope at call time.
Manifest declarations do not give code direct access. They let the host evaluate policy and consent when the contribution requests an SDK operation.
Exact package-runtime MCP storage reads
A package-runtime mcp.tool can narrow its read-only SDK storage snapshot with
options.storageReads. Each selector names an already-authorized storage
namespace and one exact key template:
The namespace must appear in the storage effects of the server authorization,
tool authorization, and tool execution options. Templates may contain literal
text plus the host-resolved {channelId} and {userId} placeholders only. A
call fails closed when a required host context value is unavailable. A present
list selects at most 64 exact rows; an empty list selects none. Omitting
storageReads preserves the compatible whole-authorized-namespace snapshot,
which remains subject to the host snapshot row and byte limits.
Native embedded views
A desktop ESM surface that embeds a host-owned browser view must declare each
destination origin under both embedded-frame and external-network. The two
effect kinds must contain matching canonical https:// origins: do not include
paths, credentials, query strings, fragments, or wildcards. Keep the lists to
the origins the surface actually navigates, including authentication redirects.
The host derives a package-scoped browser identity from the verified
installation and surface. A manifest cannot claim a first-party product
compatibility alias. Each geometry request is still checked against the exact
frame document, package asset origin, declared effects, and destination origin;
the native OnBeforeBrowse boundary rejects an undeclared initial URL,
redirect, reuse navigation, or popup before its request is issued. The
renderer also closes any unexpected committed address and shows a policy error
as defense in depth.
Events
Declare events under the top-level events object and list contribution-specific event names in publishes or subscribes. Match event payloads to the declared schema and version.
Use context.events from the surface mount contract to publish and subscribe. Undeclared event names can be rejected by the host.
Presentation Assets
Declare passive SVG or PNG presentation assets with their media type, package-relative path, sizes, and theme. Build tooling verifies and locks the bytes.
Package code should resolve runtime assets through resolvePackageAssetUrl. Do not build asset URLs from a host origin or an absolute filesystem path.