Data & privacy
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.
When you submit, you answer one structural question: does any data handled by your poppy ever leave the user's 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.
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.
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.
| Field | What it describes | What the platform does with it |
|---|---|---|
egress | The 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. |
infrastructure | What 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. |
machine | Your 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. |
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.
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).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.
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:
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.
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.
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.
| Situation | Consequence |
|---|---|
| Undeclared flow found at review | Needs changes — declare it or remove it. |
| Undeclared flow found after listing | Immediate delisting; relisting only after a fixed release and a full declaration. |
| Deceptive declaration — data covertly read, copied, or transmitted | Permanent removal, developer account closed, and the poppy blocklisted so existing installs are warned. Where the law is implicated, we cooperate with it. |