Data & privacy

User data stays in the user's cloud

That sentence is the reason this platform exists — and the reason users will install your poppy next to their customer databases, mailing lists, and business records. The default is absolute: a poppy stores data in the user's own cloud account and sends none of it anywhere else. Anything different must be declared, justified, and reviewable.

The declaration — required on every submission

When you submit, you answer one structural question: does any data handled by your poppy ever leave the user's cloud?

Answer: no

“Data stays in your cloud”

Your listing carries the label users are looking for. Nothing more to do — this is the default architecture, and the strongest sales pitch a poppy can have.

Answer: yes

Declare every flow

For each flow: what data, where it goes (service/endpoint and who operates it), why — the concrete purpose, and whether you (the developer) collect or retain any of it. Plus a link to your privacy policy. All of it visible to review.

What counts as data leaving the cloud

  • Sending message contents, contact lists, documents, analytics, or metadata about them to any endpoint you or a third party operate.
  • Telemetry, crash reports, and usage analytics that include user-identifying content or business data.
  • Calling third-party APIs (LLMs, enrichment, email delivery) with user data in the request.
  • Licensing/entitlement checks are fine — they carry an identifier, not user content. The platform's own checkout and entitlement APIs are already declared for you.

Where your code connects — the network declaration

The flow declaration above is prose a reviewer reads. Its machine-readable half lives in your manifest, under permissionSet.network, and it has three doors because a poppy has three genuinely different places code can reach the internet from.

FieldWhat it describesWhat the platform does with it
egressThe code you deploy into the user's cloud — your Lambdas, your instances. "none" · "aws-only" · ["api.stripe.com"] · "user-directed".Shown on the permission screen as your statement. Required to list — on every poppy; declare "none" if you deploy no cloud code. AWS gives us no way to enforce it, and the screen says so rather than pretending.
infrastructureWhat you build for the user whose nature is to be online: "servers", "websites", "email".Stated as purpose, in our words, not yours — a VM exists to reach the network. The standing rule: it carries what the user puts on it, never their data routed out by you.
machineYour own frontend and backend, on the user's machine. Same four values as egress.Enforced. The host arms a gate inside your backend before your code loads and compiles the same list into your tab's Content-Security-Policy. Undeclared destination → refused and logged.
// the one that can break your poppy

Declare machine accurately or your features fail on the user's machine, not in your dev loop. Every socket connect and DNS lookup your backend makes is checked against it; your tab's fetches are checked by the browser engine itself. Two things are always allowed and you never declare them: loopback (your own backend's port) and the AgentsPoppy API from your frontend — we mandate the Feedback tab, and it calls us from your page, so refusing it would be us breaking our own contract. A backend that calls us names us like any other host.

Omitting machine is allowed and breaks nothing: the host observes instead — each external destination allowed, logged once, and shown to the user as somewhere your poppy connected. The trade is that your permission screen can never graduate to “Host-enforced”, and the log is what a reviewer will read your declaration against later. Use "user-directed" only where the user chooses the destination (a mail server they type, a page an agent visits on their instruction) — it earns no enforcement, and it is reviewed as the exception it is, not as a way to avoid naming your endpoints.

The compliance declaration — your poppy's audit package

Every listed poppy gets a generated vendor security package — audit-ready documentation an enterprise customer hands to their SOC 2 auditor or vendor-risk team, published at agentspoppy.com/poppies/<slug>/dossier with a machine-readable dossier.json beside it. Nearly all of it is generated from your manifest and the platform's enforced mechanisms; you declare exactly three fields, in a top-level compliance block:

  • dataHandled — what user data your poppy handles and where it lives, in a sentence or two.
  • subprocessors — every service user data can reach beyond the user's cloud ({name, operator, purpose, dataShared}). An empty array is the strongest label a poppy can carry — “no user data leaves your cloud” — and it must be stated, not omitted.
  • securityContact — where a security team reports a vulnerability (email or https URL).
// required to list — and a naming law

A manifest without the block is refused at review, new listing and update alike — the same rule as the network declaration, and reviewed against it: a named subprocessor should appear in your network declaration where your code calls it. And never write “SOC 2 compliant” in your own copy: only a licensed CPA firm attests, about an organization. What your poppy ships is audit-ready vendor documentation, and the dossier itself says exactly that.

External services we can't see — the audit clause

Your poppy's repo is open, so its code can be audited by anyone. But if your poppy talks to a service you operate — especially where you monetise an external client — that service's code is invisible to users and to us. So the rule is:

// if user data reaches your servers

You must declare the flow and maintain a real privacy policy covering it — and AgentsPoppy may require audit access to the receiving service's source code (privately, under confidentiality) as a condition of listing or of keeping the listing. If we can't establish what happens to user data on the other end, the poppy doesn't carry it there.

This is deliberately strict. A poppy that quietly reads a user's customer database or mailing list and transmits it to the developer is not a bug or a grey area — it is industrial espionage, and this platform will not be a vehicle for it.

Auditable by construction — code, not runtimes

The audit promise only works if there's something to audit. That's why a poppy ships your code, never a runtime or a bundled service binary: a compiled-in Node or a vendored Redis is opaque bytes nobody can trace back to your open repo — exactly the blind spot a data-exfiltrating dependency would hide in. Instead you declare what you need, and AgentsPoppy provides it from the official source, pinned by hash inside the signed app, only after the user approves it.

// declare, don't ship

The manifest names the runtime ("runtime": "node22"); the platform already includes it, so your package is a few MB of diffable JavaScript, not a few hundred MB of binary. A poppy that needs a database declares redis — the user approves it, AgentsPoppy fetches it from the official source and verifies it, and you never touch those bytes. Packages that embed a runtime are rejected at certification, at review, and at install.

Enforcement

SituationConsequence
Undeclared flow found at reviewNeeds changes — declare it or remove it.
Undeclared flow found after listingImmediate delisting; relisting only after a fixed release and a full declaration.
Deceptive declaration — data covertly read, copied, or transmittedPermanent removal, developer account closed, and the poppy blocklisted so existing installs are warned. Where the law is implicated, we cooperate with it.

Design guidance — stay on the easy side

  • Process in place. If your poppy needs to analyse the user's data, do it with compute in their cloud — that's the whole trick of the platform, and it costs you nothing.
  • Bring keys, not data. If a third-party API is unavoidable, prefer letting the user supply their own API key, so the relationship (and the data) is theirs, and say so in the flow declaration.
  • Aggregate, don't identify. If you want product telemetry, count events — never content, never identifiers you don't need.
  • When in doubt, declare. An over-declared flow costs you a paragraph; an undocumented one costs you the listing.