Marketplace distribution program
This runbook owns the expanded marketplace launch program for Threada. It is an operator control document, not evidence that any marketplace listing is live.
Scope
The active program starts with Slack Marketplace as the prerequisite listing, then moves through Zapier, Microsoft Teams, Google Workspace Marketplace, Jira / Atlassian Marketplace, Zendesk Marketplace, HubSpot App Marketplace, Salesforce AppExchange, Intercom App Store, Okta Integration Network, Freshworks Marketplace for Freshdesk, GitHub Marketplace, Notion Marketplace, Asana App Directory, monday.com Marketplace, AWS Marketplace, Microsoft Marketplace, Google Cloud Marketplace, Oracle Cloud Marketplace, Datadog, PagerDuty, and Discord App Directory.
Do not treat a provider as live because a doc, scaffold, manifest, or local package exists. Live means the provider-owned install or acquisition path works, Threada maps the install to a tenant, the v1 workflow succeeds end to end in production or a reviewer-safe environment, and the marketplace has approved the listing or integration.
For commercial cloud marketplaces, the internal
BillingService.RecordMarketplaceProcurementEvent path and signed public BFF
procurement callbacks are live for verified procurement state, and private
package artifacts exist for AWS Marketplace, Microsoft commercial marketplace,
Google Cloud Marketplace, and Oracle Cloud Marketplace. That is not public
marketplace availability by itself; the provider-owned seller/partner offer,
fulfillment-adapter callback configuration, reviewer smoke evidence, and
marketplace approval still decide launch status.
Definition of done
Every marketplace must have all of the following before public launch:
- Real provider account, partner account, developer account, seller account, or marketplace publisher account connected to Threada ownership.
- Real production app, listing, offer, integration, or package IDs configured outside the repo.
- OAuth, approved install flow, SSO setup, SaaS acquisition flow, or partner integration flow configured with production callback, landing, support, privacy, and terms URLs.
- Secrets, tokens, signing keys, webhook secrets, client secrets, metering credentials, and marketplace API credentials stored in Secret Manager or an approved external evidence system.
- Tenant, workspace, organization, account, repository, board, page, service, or billing-account mapping in Threada.
- One narrow v1 workflow that succeeds end to end and can be shown to reviewers.
- Setup-required, authorization failure, disconnect, uninstall, cancellation, or deprovisioning behavior for the relevant provider.
- Sanitized evidence bundle with no secrets, cookies, raw exports, reviewer credentials, customer data, or private tenant payloads.
- Public setup/support docs, listing copy, assets, screenshots, reviewer notes, support contact, privacy link, terms link, and data-sharing disclosure.
- Marketplace submission, review status, approval evidence, and post-approval maintenance owner.
- Runtime binding in Threada’s source-of-truth runtime contracts. Marketplace
package submission readiness must fail closed unless the package descriptor
names a real
IntegrationTypeorWebhookProviderand declares a sanitized*_RUNTIME_BINDING_REFproof requirement, or the missing runtime binding is recorded as an explicit blocker.
Enterprise-safe v1 surfaces
Keep each first listing narrow:
| Marketplace | First surface |
|---|---|
| Slack Marketplace | Slack command or mapped-channel intake creates governed WorkItems. |
| Zapier | Action-only WorkItem create, append message, and update. |
| Microsoft Teams | Teams command/message-extension intake creates governed WorkItems. |
| Google Workspace Marketplace | Google Chat-to-WorkItem app before Gmail or broad Workspace scopes. |
| Jira / Atlassian Marketplace | Forge Jira issue-context panel creates or links governed WorkItems. |
| Zendesk Marketplace | Governed ticket creation, with ticket updates/comments as follow-ons. |
| HubSpot App Marketplace | OAuth-installed governed contact upsert before broader CRM surfaces. |
| Salesforce AppExchange | OAuth-installed governed Contact upsert before broader CRM surfaces. |
| Intercom App Store | OAuth-installed governed Intercom ticket creation. |
| Okta Integration Network | Governed directory action first; identity-provider listing remains blocked. |
| Freshworks Marketplace / Freshdesk | Governed Freshdesk ticket creation. |
| GitHub Marketplace | GitHub App links issues, pull requests, or repository events to WorkItems. |
| Notion Marketplace | Public Notion connection for selected page/database WorkItem flow. |
| Asana App Directory | Task or project context creates or links governed WorkItems. |
| monday.com Marketplace | Board item or workflow action creates or links governed WorkItems. |
| AWS Marketplace | SaaS subscription/contract acquisition routes to tenant provisioning. |
| Microsoft Marketplace | SaaS offer acquisition routes to tenant provisioning. |
| Google Cloud Marketplace | SaaS procurement routes to tenant provisioning. |
| Oracle Cloud Marketplace | Application/service listing routes to sales-assisted tenant provisioning. |
| Datadog | Integration surfaces Threada metrics/events and links incidents or WorkItems. |
| PagerDuty | Service integration triggers or links governed PagerDuty incidents. |
| Discord App Directory | Slash command or message command creates governed WorkItems. |
Evidence rules
- Store evidence in
.deploy-evidence/or an approved external evidence system with sanitized references in the repo. - Do not commit real provider credentials, OAuth client secrets, refresh tokens, API tokens, webhook signing secrets, marketplace metering credentials, cookies, customer records, raw incident/ticket/conversation exports, screenshots with private tenant data, or reviewer credentials.
- Public claims must name only the v1 workflow that has been installed, executed, and approved. Anything else stays planned.
- Commercial cloud marketplace evidence must prove buyer acquisition,
entitlement/subscription state, tenant provisioning, plan change or
cancellation where applicable, support handoff, marketplace approval, and a
sanitized reference showing the verified provider event reached
BillingService.RecordMarketplaceProcurementEvent.
Evidence and approval tracker
Use the neutral marketplace program CLI for the full distribution program
tracker; do not add separate per-provider tracking scripts. Slack launch
handoffs use marketplace:slack, while the cross-marketplace operator surface
is marketplace:program.
The required lifecycle gates themselves are owned by the Rust marketplace
program registry, not by Slack-specific code.
Seed the gitignored evidence file before the first launch-control pass:
task marketplace:program -- evidence-status \
--evidence .deploy-evidence/marketplace-program-evidence.json \
--seed-out .deploy-evidence/marketplace-program-evidence.json \
--no-json \
--no-markdown
The seed command creates .deploy-evidence/marketplace-program-evidence.json
with every lifecycle gate marked missing and refuses to overwrite an existing
evidence input. Fill each marketplace gate with sanitized references only. Each
gate must be one of implemented, missing, or blocked. Implemented gates
require an evidence_ref; blocked gates require a blocker. Use Secret Manager
resource names, provider dashboard references, approval-ticket IDs, marketplace
submission IDs, or sanitized evidence-bundle IDs. Do not paste credentials,
cookies, raw exports, reviewer credentials, customer data, screenshots with
private tenant data, or private tenant payloads.
Generate a separate template only when an operator needs a disposable reference copy:
task marketplace:program -- evidence-status \
--template-out .deploy-evidence/marketplace-program-evidence-template.json \
--no-json \
--no-markdown
Assess the launch state:
task marketplace:program -- evidence-status \
--evidence .deploy-evidence/marketplace-program-evidence.json \
--json-out .deploy-evidence/marketplace-program-status.json \
--markdown-out .deploy-evidence/marketplace-program-status.md
The command fails closed until every required gate is implemented for Slack and
each active marketplace. Every required non-Slack marketplace must have a
launch-control marketplace.descriptor.json file discovered by the Rust-owned
deploy-tool marketplace-package inventory; a listing with complete evidence
still stays blocked if the descriptor is missing or not bound to a real runtime
IntegrationType or WebhookProvider. Runtime-bound descriptors must
also declare a *_RUNTIME_BINDING_REF readiness evidence key so enum/provider
claims are backed by deployment or smoke proof. The same status pass consumes
each descriptor’s readinessEvidence keys, so provider-specific account IDs,
app configuration, credential, runtime-binding proof, reviewer-smoke,
submission, and approval evidence must be present as sanitized evidence
references in the operator environment before any marketplace can report ready.
Its output is approval tracking and operator evidence, not public launch proof
by itself.
Generate the operator request packet before assigning provider owners:
task marketplace:program -- evidence-requests \
--evidence .deploy-evidence/marketplace-program-evidence.json \
--json-out .deploy-evidence/marketplace-program-evidence-requests.json \
--markdown-out .deploy-evidence/marketplace-program-evidence-requests.md
The request packet is safe to share internally with launch owners. It lists the
exact descriptor evidence environment keys, accepted sanitized reference formats,
missing lifecycle gates, runtime-binding blockers, and per-marketplace next
actions. It must not be edited into final evidence; use it to collect structured
refs, then update .deploy-evidence/marketplace-program-evidence.json and the
operator environment values consumed by readinessEvidence.
Seed the accountable program owner first, without pretending the marketplace role owners are known yet:
task marketplace:program -- owner-assignments \
--owners .deploy-evidence/marketplace-program-owner-assignments.json \
--evidence .deploy-evidence/marketplace-program-evidence.json \
--seed-out .deploy-evidence/marketplace-program-owner-assignments.json \
--program-owner-name "<name>" \
--program-owner-email "<name>@threada.ai" \
--program-owner-team "Marketplace Launch" \
--no-json \
--no-markdown
The seed file is gitignored, is created only when missing, and contains the
program owner plus role owner placeholders for every active marketplace. Fill
the account, runtime/config, evidence, submission, and maintenance owner keys
before attempting release readiness; placeholders are treated as unassigned.
Existing legacy <MARKETPLACE>_OWNER entries can still act as a
marketplace-wide fallback, but role-specific owner keys are preferred for public
launch work. programOwner, --default-owner, and MARKETPLACE_OWNER_DEFAULT
route missing-owner work queue tasks; they do not count as role-owner coverage
for release readiness.
Generate the full accountable owner-assignment template from the descriptor inventory when the role owners are ready, then merge the real Threada accountability addresses into the gitignored assignment file:
task marketplace:program -- owner-assignments \
--owners .deploy-evidence/marketplace-program-owner-assignments.json \
--evidence .deploy-evidence/marketplace-program-evidence.json \
--template-out .deploy-evidence/marketplace-program-owner-assignments-template.json \
--no-json \
--no-markdown
Validate owner coverage before assigning work or attempting release readiness:
task marketplace:program -- owner-assignments \
--owners .deploy-evidence/marketplace-program-owner-assignments.json \
--evidence .deploy-evidence/marketplace-program-evidence.json \
--json-out .deploy-evidence/marketplace-program-owner-assignments-status.json \
--markdown-out .deploy-evidence/marketplace-program-owner-assignments-status.md
The owner gate is intentionally separate from marketplace evidence: evidence proves the work happened, while owner assignments prove who is accountable for provider accounts, runtime/configuration, evidence, submission, and post-approval maintenance. Release readiness consumes both gates and will not advance the latest public-launch alias while any role owner assignment is incomplete.
Generate the owner-routed launch work queue after evidence requests and owner assignments are current:
task marketplace:program -- work-queue \
--owners .deploy-evidence/marketplace-program-owner-assignments.json \
--evidence .deploy-evidence/marketplace-program-evidence.json \
--json-out .deploy-evidence/marketplace-program-work-queue.json \
--markdown-out .deploy-evidence/marketplace-program-work-queue.md
The work queue is the day-to-day operator artifact. It composes the evidence status, evidence request packet, runtime-binding blockers, and owner-assignment status into stable task IDs routed to the accountable owner role. Missing owner assignments are routed to the program owner rather than to a non-existent marketplace owner. The queue is not final launch evidence; close each task by updating the evidence file, descriptor evidence environment, owner assignment file, runtime binding, or provider-side submission record, then regenerate the queue.
For a release that is intended to submit or publicly launch marketplace listings, run the release-owned program gate after the normal dev/prod release:
task deploy:release -- --yes --marketplace-program-readiness
That command consumes both
.deploy-evidence/marketplace-program-evidence.json and
.deploy-evidence/marketplace-program-owner-assignments.json. It writes the
immutable release snapshot to
.deploy-evidence/releases/<release-short>/marketplace-program-readiness.json,
writes the underlying status artifacts beside it, and advances
.deploy-evidence/marketplace-program-release-readiness-latest.json only after
the full program is ready. Ordinary product deploys should not use this flag;
marketplace submission and public-launch releases should, so the release record,
not an ad hoc operator rerun, becomes the launch authority.
For second-wave marketplaces without package-specific docs yet, use
Marketplace follow-on setup and support
as the public setup_support_docs reference. Replace that shared reference
with a provider-specific setup guide once the production app, listing, install
flow, and reviewer smoke evidence exist.
Source of truth
The generated roadmap from task marketplace:program -- store-roadmap
owns launch sequencing. It combines Slack evidence state with provider-specific
narrative gates in the Rust-owned marketplace program store-roadmap command.
The recommended public-launch sequence is resolved from descriptor inventory,
not from a hand-maintained roadmap list. The generated work queue from
task marketplace:program -- work-queue owns accountable task routing for
the current evidence, runtime, and owner blockers. Shared
scaffold mechanics live under the Rust-owned marketplace_ops deploy-tool
modules and remain exposed as deploy-tool marketplace-package, while
provider-specific descriptors own vendor policy, launch-program
rank/recommendation metadata, runtime-binding declarations, provider callback
routes, and submission evidence gates. The marketplace evidence status
implementation lives in
the Rust-owned marketplace program evidence status command. The command consumes
the launch-gates contract for the
account, app configuration, install flow, Secret Manager,
tenant mapping, docs, smoke, evidence bundle, submission materials, and
approval-tracking gates, then overlays provider-specific descriptor
readinessEvidence requirements from the same inventory. The evidence status
command and store roadmap both resolve the active public-launch inventory from
descriptor launchProgram metadata; adjacent descriptors such as ServiceNow
must be explicitly excluded instead of disappearing from launch tracking. The
runtime binding check discovers every launch-control scaffold under packages/
with marketplace.descriptor.json and
threada.marketplaceLaunchControl: true; conventional marketplace, store,
AppExchange, and OIN package names are also treated as launch-control packages
so missing metadata fails closed. The check fails if any discovered descriptor
package name drifts from package.json, or if a claimed runtime enum is not
present in
proto/runtime_automation/runtime_automation.proto. Runtime-bound descriptors
must also carry a *_RUNTIME_BINDING_REF readiness evidence requirement so the
operator evidence packet proves the binding is deployed or smoke-tested. Check
descriptor claims with:
task marketplace:runtime-bindings
This runbook explains the program-level rules; provider-specific package scaffolds and setup docs own their narrower implementation details.
References
- Intercom App Review and Publishing
- Okta OIN submission overview
- GitHub Marketplace app requirements
- Notion Marketplace listing guide
- Asana publish your app
- monday.com submit your app
- AWS Marketplace SaaS product guidelines
- Microsoft Marketplace SaaS offers
- Google Cloud Marketplace SaaS products
- Oracle Cloud Marketplace listings
- Datadog Marketplace offering
- PagerDuty developer documentation
- Discord App Directory intro