The Exchange
Packaging turns a set of canonical components into a signed, immutable, versioned artifact that installs into someone else’s tenant. The Exchange is where that artifact becomes a product: a listing other organizations discover, a review it must pass to be trusted, an offer they buy, and an entitlement that lets them install and run it. Packaging answers “can this move safely to a tenant I don’t control.” The Exchange answers “should a stranger trust it, and how do they pay for it.”
The load-bearing decision on this page: the security review is scoped to the diff of the package’s public surface and bound to the content hash of what it reviewed. A first submission is reviewed whole; every version after it is reviewed only over the components whose content hash changed, because an unchanged hash is unchanged bytes and carries its prior verdict forward. A verdict is an attestation against a closureHash and a surfaceSignature, so a component that was reviewed cannot later masquerade as reviewed after it changes, and a component that did not change is never paid for twice.
The second decision follows from the platform, not the process: most of what a security review hunts for, CAOS prevents by construction. CRUD/FLS enforcement — the single most common reason a Salesforce submission fails — is a read-time kernel guarantee, not something each package re-implements and a reviewer re-checks. Query injection has no surface in one typed expression language that never builds a query from a string. So the review does not shrink because it is laxer; it shrinks because the attack surface it must walk is smaller before anyone submits.
The model
Section titled “The model”| Concept | What it is | Mutable? |
|---|---|---|
| Listing | A published package version offered on the Exchange: its marketing surface, its pre-install manageability and capability contract, and a link to its review verdict | Yes — a package edits its own listing |
| Capability manifest | The declared external reach of a version: outbound endpoints, callouts, elevated permissions, secret access. The review’s attack surface | No — captured at build, part of the artifact |
| Review | The audit a version must pass before it may be listed publicly. Scoped to the changed closure; run against the same generation the artifact was built at | One-way per version: pending → passed | failed |
| Verdict | A signed attestation bound to a version’s closureHash + surfaceSignature: outcome, findings, the reviewer identity, the analyzers and their versions, published to the transparency log |
No — immutable, content-addressed |
| Offer | The sellable terms a publisher attaches to a listing: price, term, the version range covered, the entitlement template an order mints | Yes — it is source |
| Order | A subscriber’s purchase of an offer: it mints an entitlement against the tenant and records the revenue split | Tracks its entitlement |
A listing is not a fourth kind of artifact bolted onto packaging. It is a marketing-and-commerce record that points at a package version, its verdict, and an offer. The trust primitives it presents — the surface signature, the manageability table, the four signature-verification checks — are the ones packaging already produces. The Exchange adds the review, the offer, and the order; it invents no new notion of what a package is.
Verified 2026-09-10 — the four signature-verification checks named in that sentence are real as of CAOS-909. A published version carries a Sigstore signature that is verified at publish and again at install, as the packaging page describes. The 2026-08-27 notice here said nothing produced or verified a package signature, which was true until then.
The review is a stage in the promote pipeline, not a gate beside it
Section titled “The review is a stage in the promote pipeline, not a gate beside it”A package version already travels a pipeline: Develop → Build → Validate → Publish (environments). Listing on the Exchange inserts one stage — Review — between Validate and a new terminal state, Listed:
Develop → Build → Validate → Review → Publish → ListedReview runs against the immutable artifact the build already emitted, at the generation it was built at, so the thing reviewed and the thing installed are the same bytes. It is shown in the publisher’s Package Manager — a package-delivered surface, not an engine built-in — as another segment on the same PromotionPath the build and validate stages already render, not a separate portal a developer leaves the platform to visit. The review’s automated findings surface through the same DeployTimeline / ValidationSummary / OperationResultList components the deploy pipeline uses, because a review is a validation pass — one whose rules are security policy rather than schema correctness. Those components, like Package Manager itself, are delivered by a package; the review, closure, and verdict mechanics are kernel.
What the review actually inspects
Section titled “What the review actually inspects”Because the artifact carries the computed closure and the surface signature, the review never reconstructs scope by hand. It inspects three things, in order of how much human attention each needs:
- The capability manifest — the only genuinely novel attack surface. Every outbound endpoint, callout, elevated permission, and secret access a version declares. This is what a human reviewer spends their budget on, because it is the part the platform cannot prove safe from structure alone: a call to an external URL is a trust decision, not a type error.
- The changed closure — machine-analyzed. Every component whose content hash differs from the last passed version, run through the static analyzer the platform already owns. Package logic is typed expression-language components, not arbitrary imperative code, so the analysis is exhaustive over a small, analyzable grammar rather than heuristic over a Turing-complete one.
- The unchanged closure — not re-inspected. Components whose hash matches a previously-passed version inherit that version’s verdict. The review reads the prior attestation from the log rather than re-running analysis it already paid for.
The verdict is bound to the hash, and inheritance follows
Section titled “The verdict is bound to the hash, and inheritance follows”A verdict is an attestation, not a database flag:
{ "package": "pkg_billing_suite", "version": "3.3.0", "closureHash": "sha256:7f2a…", "surfaceSignature": "sha256:b103…", "outcome": "passed", "scope": "diff", // "full" on a first submission, "diff" thereafter "reviewedComponents": ["field:invoice.tax_basis", "calc_function:labor_hours"], "inheritedFrom": "3.2.0", // components whose hash was unchanged "analyzers": [{ "name": "caos-expr-analyzer", "version": "2026.3" }], "reviewer": "exchange-review@cloudatlantis", "findings": [], "signature": { "identity": "exchange-review@cloudatlantis", "log": "rekor:9144…" }}Because the outcome is bound to closureHash, three properties hold without a policy engine enforcing them: a version cannot be listed whose closure hash has no passing verdict; a component cannot be silently changed after review, because changing it changes the hash and voids the binding; and a new version that is 90% unchanged components pays for review of the 10% that moved, with the rest inherited by hash identity. This is the mechanism behind the load-bearing decision — continuous, incremental review rather than a periodic full re-run.
Authoring
Section titled “Authoring”A listing and its offer are canonical components with the standard key / label / type / body envelope. The publisher writes them once, in source, under review — the same posture as the package manifest.
{ "key": "listing_billing_suite", "label": "Billing Suite", "type": "listing", "body": { "package": "pkg_billing_suite", "summary": "Invoicing, approvals and collections on one pricing model.", "categories": ["manufacturing", "cpq"], "review": { "policy": "exchange-default", // the ruleset the automated pass applies "capabilities": [ { "kind": "outbound", "endpoint": "https://rates.dragonproducts.com", "reason": "GP rate sync" } ] }, "offers": [ { "key": "offer_annual", "price": { "amount": 1200000, "currency": "USD", "period": "P1Y" }, "versionRange": "^3.0", "entitlement": { "term": "P1Y", "noticeWindow": "P30D" } } ] }}package— the package this listing sells. The listing carries no members of its own; it points.review.capabilities— the declared external reach, each with a stated reason. A capability the manifest omits is a capability the runtime refuses — an undeclared outbound call fails closed, so the manifest is not documentation the reviewer trusts, it is the enforced boundary the review audits.offers— the sellable terms. Each names a price, a version range it covers, and the entitlement template an order mints. An order is a subscriber act; the offer is the publisher’s standing terms for it.
Semantics & evaluation
Section titled “Semantics & evaluation”Scoping the review to the diff, provably
Section titled “Scoping the review to the diff, provably”Salesforce already partially automates re-review: a version update of an approved package is auto-approved through a self-review wizard “in minutes” unless it introduces new objects, callouts, or significant architecture changes. That is a proof-by-existence that knowing what changed shrinks review — but the trigger is a coarse questionnaire the publisher answers, not a computed fact.
CAOS makes the same shrink exact. The build already emits the closure hash and the per-member surface signature, so “what changed since the last passed version” is a hash-set difference, not a declaration. The review’s scope is the set of components whose hash moved, plus any capability the manifest newly declares. A version that touches only protected and internal members with no public-surface delta and no new capability has, by construction, changed nothing a subscriber can reference and nothing that reaches outside the tenant — it is the strongest candidate for an automated pass, and it is a candidate because the signature proves the boundary, not because a form asserts it.
What the platform eliminates, so the review never hunts for it
Section titled “What the platform eliminates, so the review never hunts for it”The largest categories of finding in the incumbent’s review have no surface in CAOS:
- CRUD/FLS enforcement — the leading rejection cause on AppExchange — is a read-time kernel guarantee. A package does not enforce field security in its own logic and a reviewer does not verify that it did; access is resolved by the runtime from the field’s declared contract. The category is not reviewed; it is absent.
- Query injection has no analogue: the one typed expression language reads fields through a bound graph and never assembles a query from a string.
- Secrets in code is answered by the platform’s credential primitives — a secret is a referenced credential, not a literal a scanner has to catch in source.
- Sharing/permission escalation at install is bounded because install logic runs as a package service identity whose grants are the intersection of declared-and-approved, never the installing user and never
platform.root.
What is left for the review is the residue the platform genuinely cannot prevent: the external calls in the capability manifest, the semantics of new expression-language logic, and the trustworthiness of the publisher. That residue is real, and §Costs and risks does not pretend it away.
Provenance: the verdict is signed and logged, like the artifact
Section titled “Provenance: the verdict is signed and logged, like the artifact”The artifact is already content-addressed and signed with keyless signing over a transparency log. The verdict is signed and logged the same way, by the review identity, so a subscriber verifies trust as a chain rather than a claim: the artifact hash matches, the artifact signature is valid and chains to the publisher, and a passing verdict exists in the log against that exact closureHash from the Exchange review identity. An install whose artifact is genuine but carries no verdict for its hash is refused from a public listing exactly as a bad signature is — the verdict is a fourth verification check, not a database lookup that a compromised control plane could forge.
This is the “trust the build, not the reviewer” posture the supply-chain frameworks reach for — verifiable provenance rather than a one-time human blessing — applied to a marketplace: the review’s output is itself a signed, logged artifact, so “was this version reviewed, by whom, over what” is a query against the log, not an appeal to the Exchange’s good word.
The marketplace: offers, orders, and revenue
Section titled “The marketplace: offers, orders, and revenue”Selling reuses the entitlement model rather than inventing a billing plane inside packaging. An offer is the publisher’s standing terms; an order is a subscriber accepting them, and it does exactly one thing the platform did not already do: it mints an entitlement against the subscriber tenant in the offer’s version range and for its term, and records the revenue split. Everything after the order — install, upgrade, lapse, renewal, reinstatement — is the entitlement lifecycle packaging already defines, unchanged. A lapsed paid entitlement behaves identically to a lapsed granted one: reachability is removed, data is never touched, and reinstatement restores access without a reinstall.
The platform takes a revenue share on an order, and the honest design choice is to name it as one number, disclosed on the offer before purchase, rather than the tiered arrangement the incumbent layers on. Revenue is a control-plane record against the order; it does not gate the entitlement, because a billing dispute must not be able to corrupt a subscriber’s data — the same line packaging draws for a lapse.
Delisting, and what it does not do
Section titled “Delisting, and what it does not do”A listing can be withdrawn — by the publisher, or by the Exchange for cause. Delisting removes discoverability and new orders; it does not revoke existing entitlements or uninstall anything. A tenant that already bought a delisted package keeps its entitlement to its term, keeps its data, and keeps its installed version, because a marketplace that could reach into installed tenants and remove software on a listing decision would be a worse custodian of a customer’s system than the publisher it is policing. A security verdict that is revoked after the fact — a vulnerability found in a listed version — raises a dated notice on every installation of the affected hash and refuses new installs of it, but the decision to upgrade or uninstall stays the subscriber admin’s, because it is the subscriber’s tenant.
Limits, and the reasons behind them
Section titled “Limits, and the reasons behind them”| Concern | CAOS approach | Salesforce’s behavior (cited) | Why theirs exists |
|---|---|---|---|
| Review scope | Scoped to the surface-signature diff; unchanged hashes inherit their verdict | Self-review wizard auto-approves incremental updates unless new objects/callouts/architecture appear; otherwise a full manual review | The version diff is a coarse questionnaire, not a computed hash-set difference |
| Re-review trigger | A changed content hash or a new declared capability | “New objects, new callouts, or significant architecture changes” — a human judgment at submission | No surface signature exists to diff, so change is self-declared |
| Review latency | Automated over the diff; human attention only on new capability + new logic | Practitioner-reported 6–9 weeks for an initial review, 2–3 weeks per resubmission | A labor-intensive manual review of the whole submission, queued |
| Cost per attempt | A platform fee on a listing/order, not a per-attempt gate fee | Practitioner-reported $999 per submission attempt, paid again on each resubmission | The review is a discrete manual service billed per run |
| CRUD/FLS findings | Prevented by construction — a kernel read-time guarantee | The #1 rejection cause; every package re-implements and is re-checked | Access enforcement lives in package code, so it must be reviewed in package code |
| Injection findings | No surface — one typed expression language, no string-built queries | SOQL injection is a standing review category | Apex builds dynamic SOQL from strings |
| Provenance | Verdict is signed + logged against the content hash; a fourth verification check | The review is a one-time human pass; no per-version signed attestation a consumer verifies | The trust artifact is a listing status, not a logged attestation |
| Guarantee | The verdict states what was analyzed and by which analyzers; it does not warrant the code | “Salesforce makes no guarantees regarding the quality or security of any Partner Application” | A review reduces risk; it cannot certify absence of defects — a limit CAOS shares honestly |
How Salesforce does it
Section titled “How Salesforce does it”The AppExchange security review is the gate a managed package passes before it can be listed. It exists to “identify security vulnerabilities that a hacker, malware, or other threat can exploit,” while stating plainly that Salesforce “makes no guarantees regarding the quality or security of any Partner Application” (Security Review Overview). That disclaimer is the honest core of any review model and CAOS repeats it: a review reduces risk, it does not certify safety.
The process is submission through the Partner Community of a managed package (no beta, unmanaged, or unlocked packages; major/minor versions, not patches), with a test org whose credentials the reviewer uses, plus required scan artifacts and written justifications for any findings claimed to be false positives (Prepare Your App to Pass the AppExchange Security Review).
The scanning stack combines Salesforce’s own Code Analyzer (a bundle of PMD, ESLint, RetireJS, and a data-flow engine for CRUD/FLS), the mandatory Source Code Scanner (Checkmarx static analysis) for any submission containing a package, and — since Salesforce decommissioned its Chimera dynamic scanner in June 2025 — a partner-supplied DAST report (OWASP ZAP, Burp, or Qualys) for externally-hosted surfaces, followed by a manual human review against eight categories (authentication, authorization, input validation, output encoding, cryptography, communication, logging, secret storage) (Prepare Your App…; Chimera decommission announcement).
The leading rejection cause, by a wide margin, is missing or weak CRUD/FLS enforcement, followed by injection, missing with sharing, insecure endpoints, outdated JS libraries, XSS, and hardcoded secrets (The Top 20 Vulnerabilities Found in the AppExchange Security Review). This ranking is the whole reason CAOS’s “prevented by construction” argument matters: the incumbent’s single most common failure is a category CAOS’s kernel removes before submission.
Re-review is where Salesforce itself validates the diff-scoping idea: most version updates of an approved package auto-approve through a self-review wizard unless they cross coarse thresholds (new objects, callouts, architecture), and there is no fixed-schedule mandatory annual re-review, though Salesforce may flag a version for periodic re-review based on the significance of change and time since the last one (periodic reviews).
The figures practitioners cite most — a review fee of $999 per attempt (paid again on each resubmission; free apps exempt), an initial-review turnaround of 6–9 weeks, and a ~50% first-submission failure rate — come from ISV-consultancy guides, not a first-party Salesforce pricing or metrics page, and the failure rate is explicitly an unofficial PDO industry figure. They are consistent across independent sources and directionally reliable, but they are not asserted here as official numbers. Salesforce’s own docs acknowledge the labor-intensive, multi-week nature of the manual review and the false-positive justification burden.
Where CAOS is genuinely better:
- The review is scoped to a computed diff, not a self-declared one. “What changed” is a hash-set difference over the surface signature the build already produced, so re-review covers exactly the moved components and inherits the rest — where Salesforce’s incremental path rests on a publisher answering a threshold questionnaire.
- The most common failure category is prevented, not reviewed. CRUD/FLS is a kernel guarantee, injection has no string-query surface, and secrets are referenced credentials — so the incumbent’s top rejection causes have nothing to fail on.
- The verdict is a signed, logged attestation bound to the content hash. A subscriber verifies “reviewed, by whom, over what” against the transparency log as a fourth check alongside the artifact signature — rather than trusting a listing’s status flag.
- Selling reuses the entitlement lifecycle. An order mints an entitlement and nothing else is new; lapse, renewal, and reinstatement are the packaging behaviors already defined, so a paid package is not a second, parallel machine.
- Delisting and verdict-revocation never reach into an installed tenant. Discoverability is removed and new installs refused; existing entitlements, data, and installed versions are the subscriber’s, and an upgrade decision stays theirs.
Parity: a mandatory review before public listing; a stated no-guarantee posture; static analysis plus human review; a per-member IP-protection boundary the review respects; declared external endpoints as the audited surface; and a revenue share on distribution. These are the right primitives, copied deliberately.
Costs and risks:
- The signature captures shape, not semantics. A change that leaves the surface signature identical — a formula that now returns a different number for the same inputs — is out of the diff-scoped review’s automated scope, exactly as it is out of the derived-version bump. Behavioral review cannot be driven by a hash diff alone; the capability manifest and new-logic analysis catch new reach, not changed meaning behind a stable surface. Release notes and the execution trace carry what the signature cannot, and a publisher can request a full re-review when semantics moved under a stable surface.
- A review reduces risk; it does not certify safety. The no-guarantee statement is not a disclaimer to route around — it is true of every review, CAOS’s included. A passing verdict means “these analyzers found nothing over this scope,” not “this is safe.”
- The capability manifest is only as honest as its declaration is enforced. The runtime refusing undeclared reach is what makes the manifest auditable rather than aspirational; if that enforcement has a gap, the review is auditing a fiction. The manifest’s value rests entirely on fail-closed enforcement of undeclared capabilities.
- Human review is the bottleneck the platform cannot delete. New external endpoints and new privileged logic need a person, and a person is slower and scarcer than a scanner. Diff-scoping shrinks how much they review; it does not remove the need for them, and a surge of novel-capability submissions queues against human capacity exactly as the incumbent’s does.
- Marketplace curation is a policy surface, not just a technical one. Deciding what may be listed, what is delisted for cause, and how a revoked verdict is communicated are governance decisions with legal and reputational weight that no signature settles. The platform provides the mechanism; an operator still has to run the market.
Metadata & deploy representation
Section titled “Metadata & deploy representation”| Artifact | type |
Body |
|---|---|---|
| Listing | listing |
package, summary, categories, review (policy + capabilities), offers[] |
| Offer | part of a listing |
price, versionRange, entitlement template |
| Capability manifest | not a component — a build output | Declared outbound / callout / permission / secret reach, each with a reason |
| Review verdict | not a component — a signed attestation | closureHash, surfaceSignature, outcome, scope, reviewedComponents[], inheritedFrom, analyzers[], reviewer, findings[], signature |
| Order | not a component — a control-plane record | Tenant, offer, minted entitlement reference, revenue split |
The split mirrors packaging’s: the listing is source and is edited; the capability manifest and the verdict are produced — the manifest by the build, the verdict by the review — signed, and never edited. Changing a listing’s offer is an ordinary component diff that governs the next order, never one already placed. An order is record data, not metadata, the same treatment an installation and a permission-set assignment get.
Salesforce analogs, for migration mapping: the listing corresponds to an AppExchange listing plus its Package2 association; the review verdict has no first-party analog that a consumer can cryptographically verify — the closest is the listing’s “passed security review” status, which is a flag rather than a logged attestation; the offer and order correspond to AppExchange Checkout’s pricing and subscription records; and the capability manifest has no analog, being reconstructed manually by the reviewer from the submitted architecture document rather than declared and enforced.
Sources
Section titled “Sources”- Security Review Overview — Salesforce Developers — the review’s purpose and the explicit no-guarantee statement
- Prepare Your App to Pass the AppExchange Security Review — Salesforce Developers — Code Analyzer, Checkmarx Source Code Scanner, submission requirements, failure categories, the multi-week manual review, SessionID auto-fail
- The Top 20 Vulnerabilities Found in the AppExchange Security Review — Salesforce Developers — CRUD/FLS as the #1 rejection cause, and the ranked category list
- Salesforce Is Decommissioning the Chimera DAST Scanner — Salesforce Partner Community — Chimera decommissioned June 2025; partners now supply their own DAST report
- Periodic Reviews — Salesforce Developers — mandatory vs. voluntary re-review, risk-based flagging, version-upgrade exemption
- Salesforce AppExchange Security Review: The 2026 Guide — Appnigma — practitioner-sourced: the $999-per-attempt fee, 6–9-week / 2–3-week timelines, the self-review wizard, and the ~50% first-pass failure rate explicitly labeled an approximate PDO figure, not an official number
- SLSA v1.1 FAQ — slsa.dev — build provenance and reproducible builds as the basis for trusting an artifact by its verifiable origin rather than a one-time human pass, and the cost of verification at scale
- Sigstore Overview — keyless signing over the Rekor transparency log, the same mechanism the verdict is signed and logged with
- Packaging & distribution — the engine this page builds on: the computed closure, the surface signature, manageability, the entitlement lifecycle, and the four signature-verification checks