Skip to content
threada Docs

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 IntegrationType or WebhookProvider and declares a sanitized *_RUNTIME_BINDING_REF proof requirement, or the missing runtime binding is recorded as an explicit blocker.

Enterprise-safe v1 surfaces

Keep each first listing narrow:

MarketplaceFirst surface
Slack MarketplaceSlack command or mapped-channel intake creates governed WorkItems.
ZapierAction-only WorkItem create, append message, and update.
Microsoft TeamsTeams command/message-extension intake creates governed WorkItems.
Google Workspace MarketplaceGoogle Chat-to-WorkItem app before Gmail or broad Workspace scopes.
Jira / Atlassian MarketplaceForge Jira issue-context panel creates or links governed WorkItems.
Zendesk MarketplaceGoverned ticket creation, with ticket updates/comments as follow-ons.
HubSpot App MarketplaceOAuth-installed governed contact upsert before broader CRM surfaces.
Salesforce AppExchangeOAuth-installed governed Contact upsert before broader CRM surfaces.
Intercom App StoreOAuth-installed governed Intercom ticket creation.
Okta Integration NetworkGoverned directory action first; identity-provider listing remains blocked.
Freshworks Marketplace / FreshdeskGoverned Freshdesk ticket creation.
GitHub MarketplaceGitHub App links issues, pull requests, or repository events to WorkItems.
Notion MarketplacePublic Notion connection for selected page/database WorkItem flow.
Asana App DirectoryTask or project context creates or links governed WorkItems.
monday.com MarketplaceBoard item or workflow action creates or links governed WorkItems.
AWS MarketplaceSaaS subscription/contract acquisition routes to tenant provisioning.
Microsoft MarketplaceSaaS offer acquisition routes to tenant provisioning.
Google Cloud MarketplaceSaaS procurement routes to tenant provisioning.
Oracle Cloud MarketplaceApplication/service listing routes to sales-assisted tenant provisioning.
DatadogIntegration surfaces Threada metrics/events and links incidents or WorkItems.
PagerDutyService integration triggers or links governed PagerDuty incidents.
Discord App DirectorySlash 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