Privacy Policy
Effective date [EFFECTIVE DATE]
What we collect, why we hold it, and how long it stays. The values you store are encrypted before they are written, each one under a key of its own.
1. Who we are
penv.cloud is a hosted place to keep the keys and settings your apps need. It is operated by [LEGAL ENTITY NAME], registered at [REGISTERED ADDRESS], company number [COMPANY REGISTRATION NUMBER]. This policy covers the website, the console, the API, and the command line tool.
For the personal data of the people who sign in, we are the controller. For the values you store in a workspace, we are the processor and the workspace owner is the controller. A Data Processing Agreement is offered separately and covers that second role. Ask at privacy@penv.cloud.
Our data protection contact is [DPO OR EU REPRESENTATIVE].
2. What we collect
2.1 Your account
Your email address, and a display name if a sign-in provider gives us one. If you set a password we keep a one-way hash of it (Argon2id) and never the password. If you turn on a second factor we keep the authenticator seed encrypted under a key tied to your account, and your backup codes as hashes. If you register a passkey we keep its public key, its identifier, a use counter, the transports it supports, its authenticator model, whether the key is synced to a cloud account, and the name you gave it. If you add a recovery address we keep it with the date it was verified.
We do not collect a profile photo, a phone number, or a date of birth, and we do not record your browser or device details on a session.
2.2 Sign-in with another service
If you sign in with Google, GitHub, or Microsoft we keep the identifier that provider uses for
you, whether it said the address was verified, and a copy of the email address it asserted. We ask
each provider only for openid, email, and profile.
If your company uses its own login (SAML single sign-on), we keep the identifier your identity provider asserts, the connection settings your admin entered, and the signing certificate. If your company syncs its directory to us (SCIM), we keep the user and group records it pushes, including the attributes it sends for each person.
2.3 Your workspace
The workspace name, the billing contact address, who is a member, what role each member holds, how each member arrived, who invited whom, and any domains the workspace has verified.
2.4 The values you store
Every value you store is encrypted before it is written. Section 6 explains how. The address of a value is not encrypted: the project, the environment, the path, and the name are stored in the clear so the service can find and list them. Do not put a secret in a name.
Every version of a value is kept. Writing a new value adds a version rather than replacing one, which is what makes rollback and history work.
2.5 Machines
Your CI and your servers sign in as machine identities. We keep the identity, its scope, and a hash of each credential with an expiry. For a build on GitHub Actions we also record what the build proved about itself: the repository, the workflow reference, the run identifier, the run attempt, and the GitHub account that started it.
2.6 The record of who did what
Every read, write, reveal, member change, and billing change is written to an append-only audit log. Each entry holds the workspace, the action, who did it, what they touched, the source IP address, the result, the time, and a small amount of context such as how long the operation took. For a member action the thing touched is an email address. An entry never holds a value. Reading the audit log is itself recorded.
Sign-ins, sign-outs, and refused sign-ins are recorded separately with the source IP address, the outcome, and a hash of the address that was tried. We keep the hash rather than the address so that a list of refused attempts cannot be read back as a list of who tried to get in.
2.7 Email we send you
We keep a queue row for every message we send: the recipient, the template, the values that filled it in, and whether delivery succeeded. This is how a failed send gets retried.
2.8 Billing
If you buy a plan we keep the customer identifier our payment processor issues, your plan, your seat count, your subscription status, and one row for each charge with its amount, currency, and outcome. Card numbers, bank details, and billing addresses go to the payment processor and never reach us.
2.9 Sales and support
If you contact sales we keep your email address, your name, your company, what you told us, and how many times you have asked.
2.10 Technical logs
We count request timing per route and per minute so we can see when the service is slow. The count is keyed to a route template rather than to an address, so it holds no identifier. We also keep short-lived counters that enforce rate limits, keyed to an account or to a source IP address.
We measure page visits with Google Analytics only after you accept the cookie notice, and a declined notice loads nothing from Google. No advertising tracker runs.
2.11 Cookies
Every cookie the site sets itself is needed to sign you in, keep you signed in, or finish something you started. All of them are HTTP-only and restricted to HTTPS, so no script on the page can read them and none of them travel in the clear. Google Analytics sets its own cookies only after you accept the notice; your answer is kept in this browser's local storage, not in a cookie.
| Cookie | Purpose | Lifetime |
|---|---|---|
__Host-penv_session | Keeps you signed in. Holds a random handle, never a claim about you. | Up to 7 days |
__Host-penv_pending | Remembers the sign-up this browser started, including the address you typed, while you fetch the emailed code. | 30 minutes |
__Host-penv_reset | Carries a password reset in progress. | 30 minutes |
__Host-penv_oauth | Ties a social sign-in to the browser that started it. | 10 minutes |
__Host-penv_saml | The same tie for a company sign-in. | 10 minutes |
__Host-penv_webauthn | The same tie for a passkey. | 5 minutes |
penv_oauth_state | Ties an integration connection to the browser that started it. | The connect window |
penv_gh_state | The same tie for a GitHub App install. | 15 minutes |
penv_azure_consent | The same tie for granting us access to an Azure key. | 15 minutes |
The first six are locked to the exact host that set them, so no other site and no subdomain can read or replace them. The last three are limited to the console path that uses them.
3. Why we use it, and our lawful basis
| What we do | Why | Lawful basis (GDPR Article 6) |
|---|---|---|
| Run your account and your workspace | You asked us to | Performance of a contract |
| Store your values, encrypt them, and hand them back on request | You asked us to | Performance of a contract |
| Send security email such as a verification code or a password change notice | So an account change is never silent | Performance of a contract |
| Keep the audit log and the sign-in record | So you can prove who reached what, and so we can spot an attack | Legitimate interests |
| Rate limits and abuse prevention | To keep the service up for everyone | Legitimate interests |
| Refuse throwaway mailboxes at sign-up | So an account cannot be taken over by whoever rents that inbox next | Legitimate interests |
| Bill you and keep the record of the charge | To take payment and meet tax rules | Contract, and legal obligation |
| Answer a sales or waitlist request | You asked us to | Legitimate interests, or steps before a contract |
| Product email you can turn off | To tell you about the service | Consent |
Where we rely on legitimate interests we balanced them against your rights and wrote the result down. Ask at privacy@penv.cloud and we will share the assessment.
We do not sell personal information, and we do not share it for cross-context behavioral advertising. We run no profiling and make no automated decision that has a legal effect on you.
4. Notice for California residents
In the last twelve months we collected the categories set out in section 2: identifiers, account credentials held in hashed or encrypted form, commercial information about your subscription, and internet activity such as the source IP address on an audit entry. We collect them for the purposes in section 3, from you and from the sign-in provider you chose. We disclose them only to the subprocessors in section 7, each under a contract that forbids using them for anything else.
We have not sold or shared personal information in the last twelve months, and we do not sell the personal information of anyone under 16.
You may ask us to tell you what we hold, to correct it, to delete it, and to limit how we use sensitive personal information. We will not treat you differently for asking. Section 9 says how.
5. Notice for other states with privacy laws
If you live in a state with a comprehensive privacy law you have the rights in section 9. Where that law gives you a right to appeal a refusal, write to privacy@penv.cloud with the word "appeal" in the subject and a different person will review it.
6. How the values you store are protected
This is the part most readers came for, so it is stated plainly.
Every value is encrypted, each one under its own key. In technical terms: envelope encryption with AES-256-GCM, a fresh data key for every version, wrapped by a key held in AWS Key Management Service. The identifier of the wrapping key is recorded on every version, so a rotation is provable. The workspace, project, environment, path, and name are bound into the encryption, so a copied ciphertext cannot be opened anywhere else.
Your workspace is separated inside the database. Every tenant row is guarded by PostgreSQL row-level security keyed on the workspace, set fresh on every transaction. A query that arrives with no workspace context returns nothing. The database enforces this, so it is identical on every plan.
The server can decrypt your values to serve your machines. That is what makes penv pull
work. This is not zero-knowledge encryption and we will not describe it as such. The consequence
is that the compute running the decrypt path holds a plaintext value in memory for as long as it
takes to answer a request. Section 7 names the one vendor this applies to.
Our staff do not read your values in the ordinary course of running the service. No console,
report, or support tool shows a customer value. Reading one takes an explicit call in the code,
and every reveal writes an audit entry you can see. Values are wrapped in a type whose serializers
print [redacted], so a value cannot reach a log or an error message by accident.
On Enterprise you can hold the key. Bring your own key works with AWS KMS, Google Cloud KMS, Azure Key Vault, and HashiCorp Vault Transit. Nothing is cached, so disabling that key ends our ability to open your values on the next call.
The audit log cannot be edited. The database grants allow insert and select on it and nothing else, to us as much as to you. The one thing that removes an entry is the retention job in section 8.
7. Subprocessors
These are the third parties in the path today. Each is bound by a contract that limits them to processing on our instructions.
| Subprocessor | Purpose | What it can access | Region |
|---|---|---|---|
| Amazon Web Services (KMS) | Wraps the keys that protect your values | Key material. No plaintext value. | us-east-1, United States |
| Neon | The main database | Ciphertext and metadata. No plaintext value. | [NEON REGION] |
| Vercel | Runs the application and the API | Request routing, a coarse country hint, and the compute that decrypts a value to serve it. Holds plaintext in memory. | [VERCEL REGION] |
| Resend | Sends transactional email | Your email address, the subject, and the body of the message. No plaintext value. | [RESEND REGION] |
| Upstash | Rate-limit counters and job locks | A counter and a key derived from an account or a source IP address. No plaintext value. | [UPSTASH REGION] |
| Stripe | Payments in most markets | Your billing email, the workspace name, and payment data you enter with them. No plaintext value. | Global |
| Paystack | Payments in African markets | The same. No plaintext value. | Global |
Error tracking and log shipping have configuration slots in the product and are switched off. Nothing is sent to them. They will be added to this table on the day they receive a first event.
We will publish a change here before a new subprocessor starts, with at least [SUBPROCESSOR NOTICE PERIOD] notice. Customers under a Data Processing Agreement may object in that window.
The login provider you choose. Signing in with Google, GitHub, or Microsoft sends your browser to them and brings back your identifier and email address. That exchange is between you and the provider you picked, under their privacy policy.
Places you send your own data. The console can sync your values out to platforms you choose, such as your own cloud account or your hosting provider. The GitHub App works the same way on the repositories you install it on. Those platforms are your own systems and not our subprocessors, and an export sync records who approved it before it runs. What happens to a value once it lands there is governed by your agreement with that platform.
8. How long we keep it
| Data | Kept for |
|---|---|
| Account and workspace records | While the workspace is live, then [ACCOUNT RETENTION AFTER CLOSURE] |
| Values you store, and their version history | While the workspace is live. Every version is kept, because rollback depends on it |
| A deleted workspace | Access ends the moment an owner deletes it. The rows survive 30 days so a mistake is recoverable, then everything belonging to that workspace is destroyed |
| Audit log | 7 days on Free and 90 days on Pro. A daily job deletes every entry older than that. On Enterprise the period is the one agreed in your contract, and nothing is deleted automatically. If you stream your log to your own endpoint, an entry we have not yet delivered is kept until it has been, however old it is, so the copy you receive has no gap in it |
| Sign-in record | [SIGN-IN RECORD RETENTION] |
| Sessions | 7 days at most, and less if you sign out |
| One-time codes and in-flight sign-in state | Minutes to hours. A spent code is kept as evidence that it was used |
| Expired machine credentials | Deleted by a daily job |
| Email queue | [EMAIL LOG RETENTION] |
| Billing records | [BILLING RECORD RETENTION], to meet tax and accounting rules |
| Waitlist and sales enquiries | [LEAD RETENTION] |
Deleting a workspace destroys its values and its email queue, and nothing else does. Its audit log goes the same way, and also loses entries to the daily retention job in the row above.
9. Your rights, and how to use them
You can ask us to give you a copy of your personal data, correct it, delete it, hand it to another provider, limit how we use it, or stop using it where we relied on legitimate interests. You can withdraw consent at any time, which does not undo what we did before.
Some of this you can do yourself. In the console you can change your email address, add and remove
a passkey, sign out other sessions, remove a member, and delete a workspace. Your values can be
read back at any time with penv pull or the API, which is the export path.
For anything else write to privacy@penv.cloud. We answer inside one month, and will tell you if a complicated request needs up to two months more. Where we are the processor rather than the controller, meaning the request concerns a workspace somebody else owns, we will pass you to that workspace's owner.
If you think we got it wrong you can complain to [SUPERVISORY AUTHORITY], or to the authority where you live.
10. Sending data abroad
The service runs in the United States. If you are in the European Economic Area, the United Kingdom, or Switzerland, using it means your data is transferred there. We rely on [TRANSFER MECHANISM] for that transfer, and every subprocessor in section 7 is covered by it. Ask at privacy@penv.cloud for a copy.
Our UK representative is [UK REPRESENTATIVE].
11. Children
The service is built for developers at work and is not for children. Do not use it if you are under [MINIMUM AGE]. If we learn we hold a child's data we delete it.
12. Security incidents
If a breach affects your personal data we will tell you and the relevant authority within the time the law allows. Report anything you find to security@penv.cloud.
13. Changes to this policy
We will post a new version here with a new effective date. If a change matters to you we will email the workspace contact before it takes effect. Using the service after that date means the new version applies.
14. Contact
Write to privacy@penv.cloud, or to [LEGAL ENTITY NAME] at [REGISTERED ADDRESS].