Default permissions
The starter permissions PulsVault creates with every project — what each one grants, why they exist, and when to write your own instead.
The first time you open a project's Permissions screen, PulsVault creates a small set of permissions for you. You didn't ask for them and nothing holds them yet — they are there so that granting a machine its access is a choice from a list, rather than a path pattern you have to invent on your first day.
This page explains what each one grants and when to replace it with your own.
What gets created, and where#
Two different sets, because the two projects answer different questions.
In every ordinary project#
Named after the project, so they stay distinct across your organization. For a project called acme-web:
| Permission | Grants | For |
|---|---|---|
acme-web-read-prod |
read, list on acme-web/prod/** |
A deploy job that needs production secrets but must never change them. The common case. |
acme-web-write-prod |
read, write, list on acme-web/prod/** |
A pipeline that also sets secrets — a rotation job, a migration that writes a new connection string. |
acme-web-manage-prod |
read, write, list, delete on acme-web/prod/** |
A job that also removes secrets — the only starter that can delete, undelete or mv. |
acme-web-read-shared |
read, list on shared/*/** |
Reading the organization-wide common secrets. See The Shared project. |
Two more are created wherever cross-environment grants are allowed — every personal space, and every organization that has not turned on approval for them:
| Permission | Grants | For |
|---|---|---|
acme-web-read-all |
read, list on acme-web/*/** |
Reading this project in every environment, production included. |
acme-web-write-all |
read, write, list on acme-web/*/** |
Writing in every environment. A * environment is also the only shape that reaches an environment you create later. |
acme-web-write-prod cannot delete a secret, and neither can write-all. The actions are separate on
purpose — a key that can update a credential but provably cannot destroy one is worth being able to hand
out. manage-prod is the starter that crosses that line, and delete is what pulsvault delete,
undelete and mv all need. See Access policies.
In the shared project#
shared gets its own set, because writing there is a genuinely different act:
| Permission | Grants |
|---|---|
shared-read-prod |
read, list on shared/prod/** |
shared-write-prod |
read, write, list on shared/prod/** — only a machine pinned to shared may hold this |
shared-read-nonprod |
read, list on every non-production environment in your space |
shared-read-all |
read, list on shared/*/**, production included |
shared-read-nonprod is built from the environments you actually have, not a fixed list. If you
renamed staging or added qa, the starter names your environments — a default permission pointing
at an environment that does not exist would show up as broken on the Health tab on day one.
Why these, and not more#
They cover the shapes almost every pipeline needs — read my production secrets, write them, remove them, read the common ones, and the same in every environment — and stop there deliberately. A longer list of starters is not more helpful; it is a longer list to read before you can pick, and it makes the library look busy before you have created anything of your own.
Everything else is a permission you write, because everything else is specific to you. In particular
there is no seeded manage for the shared project or for every environment at once: both are real
grants, but neither is a shape you should end up holding without having chosen it.
Things worth knowing#
They grant nothing until a machine holds them. A permission is a definition sitting in a library. It has no effect until you attach it to a machine identity — so an unused starter is inert, not a risk. This is also why they are safe to leave alone.
Seeding is per name, and it repeats. Opening the Permissions screen creates any starter whose name is not already taken, so a set that predates a new starter gains it on the next visit, and a starter you managed to remove comes back. A permission you wrote is never touched, even if it shares the name.
You can rename and re-describe them, but not delete them. Renaming is encouraged if your team has its own vocabulary. Deleting is refused, because a default is furniture: if you don't want it, leave it unattached and it costs you nothing.
They are not special once created. A starter behaves exactly like a permission you wrote yourself. There is no hidden privilege attached to being a default.
Who may see and change permissions#
The starters above are the permissions your machines hold. This section is the other thing the word means here: which people may look at that library and change it.
| You want to | You need |
|---|---|
| See the permission library, a machine's attached permissions, policy health, the pattern tester | secrets:secret:read or secrets:policy:manage |
| Create, rename, delete a permission, or attach / detach one from a machine | secrets:policy:manage |
| Create or change a space-wide (unpinned) permission | secrets:policy:manage and organization administrator |
| Grant a cross-environment permission while approval is required | secrets:policy:manage and organization administrator |
Seeing is deliberately a lower bar than changing. A permission is a statement about which machine reaches which secret path, and anyone who may read this space's secrets should be able to see who else reaches them — being shown an empty list because you lacked the management code reads as this machine has no access, which is the opposite of a safe thing to get wrong.
Which roles carry them#
| Role | Holds secrets:policy:manage? |
|---|---|
Organization administrator (BUSINESS_ADMIN) |
Yes — and every other secrets:* code |
| Finance Manager, Auditor | No |
| Team lead, Team contributor, Team viewer | No — a team role grants nothing on the secrets plane |
| A custom role you build | Only if you add the permission to it |
| Personal space (Developer plan) | The owner holds every secrets:* code implicitly |
Team roles carry no secrets:* permission on purpose: a team is granted a namespace through a
namespace grant, not by every team role reaching the whole
space. To give one person authority over permissions without making them an organization
administrator, build a custom role carrying secrets:policy:manage and assign it.
There is no per-project version. Holding secrets:policy:manage anywhere means holding it in every
project of the space — which is why an unpinned permission, the one kind that can name any project,
needs an organization administrator on top of it.
When to write your own instead#
Reach past the starters when you need to be narrower than they are — which is most of the time, once a project grows past its first pipeline:
- A single namespace, not the whole environment.
acme-web/prod/payments/**instead ofacme-web/prod/**, so a payments deploy cannot read the analytics credentials. - A non-production environment. The starters cover
prodand the common secrets; a permission foracme-web/dev/**is one you create. - One action only. A
rotate-only permission lets a rotation job re-key a secret without being able to write an arbitrary new value.
The quickest route to a good permission is usually to open a starter, look at its pattern, and write a narrower one next to it. The pattern tester will tell you exactly which existing secrets your version reaches before you save it.
Where to go next#
- Access policies — the full rules for actions, paths and patterns
- The Shared project — why
sharedis read-only for everyone else - Environments — and how one permission can span several of them
- Machine identity permissions — attaching a permission to a machine