Invite by email, grant one environment, shut a leaver out in 60 seconds: roles and teams in dotvault
This is part 9 of the series "dotvault, Start to Finish: One Command from Your Laptop to CI, Your Team, and Your AI Agents." dotvault will be released free of charge when this series ends. In the demo, Remove from org d
This is part 9 of the series "dotvault, Start to Finish: One Command from Your Laptop to CI, Your Team, and Your AI Agents." dotvault will be released free of charge when this series ends.
In the demo, Remove from org did four things at once. It revoked the service token the person had created, deleted their project grants, took them out of their team, and stopped their pulls. Their token was refused about five seconds later, and their own login about fifteen seconds later.
That is the difference from handing .env files around in chat. Once a value has been pasted to someone, there is no way to take it back, and changing a shared password does nothing to the API keys and database URLs sitting in their .env. With dotvault, cutting someone off is one action in the console. The only work left is replacing the values they could read, because whatever they already pulled is still on their laptop.
This part walks through the whole team setup in a demo company, Acme Shop: converting a Personal org to a Company org, inviting people by email, granting roles per project and per environment, and then the order of steps when someone leaves.
This is part 9 of 12.
The short version
- Convert to a Company org, then invite. Convert under User Settings β Organization, then use + Invite member in Members with an email, a role and an optional first grant (project, role, environments).
- A project has four roles: owner, admin, writer and reader. Writer and reader can be limited to specific environments, so a person granted development only cannot pull production. Grant a team, and everyone in it gets the same access.
- When someone leaves: note their access, check the audit log, transfer ownership, Remove from org, confirm, replace values. Removing them also revokes their tokens, grants and team memberships. A project owner cannot be removed until ownership moves.
-
In the demo, both their token and their login were refused within fifteen seconds. The last step is replacing the values they could read with
dotvault set.
Before you read on
This builds on part 2 (pull) and part 7 (service tokens). Part 10 covers reading the audit log.
1. Convert your Personal org to a Company org
Your first login to dotvault creates an org that belongs to you alone, a Personal org. You cannot invite anyone into it. To work as a team, convert it to a Company org.
Three demo users appear in this part:
| Demo user | Org role | Part they play |
|---|---|---|
| dev-b | org_admin | Runs Acme Shop: invites people, grants access, removes people |
| dev-c | member | An employee who leaves in the second half |
| dev-d | guest | An outside collaborator |
The person who will run the org (dev-b) converts it under User Settings β Organization. Enter the company name and press Convert to Company, and the console asks for confirmation.
As it says, this cannot be undone; there is no way back to Personal. Projects and the values in them carry over. After Yes, convert, the console shows "Converted to a Company organization." and the sidebar gains My Organizations and Teams. The conversion made dev-b the owner of acme-shop, the project created before it.
2. Three org roles and four project roles
A Company org has two kinds of roles. The org role decides what someone can do in the org. The project role decides whether they can read or write the values of a given project. The Members page lists both:
| Role | What the console says |
|---|---|
owner |
Exactly one per project. Full access + can appoint/remove admins + transfer ownership. |
admin |
Manages this project's permissions (grant/revoke writer/reader) + read/write on all envs. Cannot appoint/remove owner or admin (owner only). |
writer |
Read + write (equivalent to a token's member role). Can be scoped to specific envs. |
reader |
Read only, i.e. pull (equivalent to a token's viewer role). Can be scoped to specific envs. |
org_admin |
Can always manage the org (members, owner transfers, project settings). Cannot read/write values β grant that to yourself if needed (audited). |
member |
Org role: a regular member who can see the workspace (project list, member list, Teams). Data access depends on project role. |
guest |
Org role: sees nothing except projects explicitly granted (list views are hidden too). For external collaborators. |
The first four are project roles; the last three are org roles. Note that org_admin manages the org but cannot read values by itself. To read them, an org_admin grants themselves a project role, and that grant is recorded in the audit log.
3. Invite by email and grant development only
dev-b invites dev-c with + Invite member in Members: dev-c's email address, Org role Member. Checking Add initial access (optional) lets you set the first grant in the same step. In the demo: Target acme-shop, Role writer, and Selected with development only.
After Send invitation, dev-c appears in the list as Invited, with acme-shop: writer (development) in the Access column: the access the invitation will grant.
Press Resend on that row and a fresh invite link appears, starting with https://app.dotvault.io/invite/. Copy it and send it to the person yourself, in chat or however your team talks.
The end of the link is different for every invitation, so it is blacked out here. Send it to the invitee only.
4. The invitee joins and can pull only what was granted
In the demo, dev-c logged in at app.dotvault.io before opening the link. At login, a banner across the top already said "You have 1 pending organization invitation(s). View β".
The link opens "Invitation to Acme Shop" with the role (Member) and a Join button. After Join, the page says "You joined Acme Shop", and Go to console opens Acme Shop. If the person will use the CLI, the same page links to "Using the CLI (dotvault pull)? Set a password first β", where they set the password for dotvault login.
dev-c logs in from the CLI and pulls.
dotvault whoami lists the newly joined Acme Shop (company, member) and dev-c's own Personal org. The pull of development, which was granted, works. The pull of production, which was not, stops with PERMISSION_DENIED and exit code 4. The lower half of the figure is from after dev-c joins a team in the next section.
5. Grant a team, and everyone in it gets the same access
Besides granting people one by one, you can grant a team. Create the team under Teams (in the demo, backend) and add org members to it by email with + Add member on the team page. On the free plan, an org can have one team. Creating a second one shows "Team limit reached for your plan (free): 1/1".
Grant the team on the project's Access page: choose Team under Grant to, pick a role and environments, and press Grant. With "All environments (including ones added later)", the grant also covers environments you add to the project later.
The note under the list explains what happens when someone has both a personal grant and a team grant. With different roles, the stronger role applies, along with that grant's environments. With the same role, the environments add up. dev-c has writer on development personally and writer on all environments through backend, so dev-c can read and write every environment. That is why the production and qa pulls in the lower half of the previous figure work.
6. Invite outside collaborators as guests
For someone outside the company, choose Guest as the Org role. In the demo, dev-d is a guest with reader on acme-shop, development only.
A guest sees only the projects granted to them. The sidebar has no Members, Teams, Service Tokens or Audit Log.
Acme Shop also has acme-batch, but dev-d's Projects page shows only acme-shop. Opening the Members page by URL shows "Guests cannot access this resource". The Keys page of acme-shop says "You have read-only access to this project. Editing actions are hidden (revealing a value is audit-logged)." and shows no editing buttons.
The CLI agrees. dev-d's dotvault project list shows only acme-shop. The development pull works, while the production pull and a write with dotvault set both stop with PERMISSION_DENIED (exit code 4).
7. Six steps when someone leaves
Now dev-c is leaving. The order:
| Step | What to do | Why |
|---|---|---|
| 1 | Note which projects and environments they could read, on their member page | Removing them deletes their grants and team memberships, so look first |
| 2 | Check what they did in the audit log | Find the tokens they created and any access they changed |
| 3 | Transfer any project they own | An owner cannot be removed until ownership moves |
| 4 | Press Remove from org | Their pulls stop, and their tokens, grants and team memberships go |
| 5 | Confirm in the lists and the audit log | Each of those changes can be checked afterwards |
| 6 | Replace the values they could read | Whatever they already pulled stays on their laptop |
Before this, dev-c created a service token named dev-c-laptop, the kind a CI job would use. Members can create tokens too, but only for projects and environments they have access to, with an expiry from 1 day to 1 year (90 days by default).
Step 1: Note what they could read
Press Details on dev-c's row in Members.
Projects shows the personal grants; TEAMS shows the access that comes through teams. Personally, dev-c had development only, but through backend dev-c could read every environment of acme-shop. Those are the values to replace in step 6. This page disappears with the removal, so note it first.
Step 2: Check what they did in the audit log
In Audit Log, put dev-c's email address in Actor (email / sub) and press Apply.
You get the tokens dev-c created (service_token.created) and the invitations dev-c accepted (rbac.invitation.accepted). dev-c was invited more than once during the demo, hence three acceptance rows. The token rows also include three created the day before, already revoked.
The Actor of rbac.invitation.accepted is dev-c's user ID (64782458-β¦), not the email. Some actions record the actor by email and others by user ID, but filtering by email returns both.
If the person leaving was an admin, the audit log also shows who they added to teams and which projects they created or deleted. Here is the same filter for the admin, dev-b:
The Change column on the right shows what changed. The email address after "+" on team.member.added is the person added to the team; "name: backend β backend-qa" on team.updated is the team's name before and after.
Step 3: Transfer any project they own
A project owner cannot be removed from the org as is. Move the ownership to someone else first.
Do it in the Projects panel of the member page. Press Transfer⦠on the owner row and pick the new owner from the org's members; a confirmation appears inside the row. Confirm transfer takes effect immediately.
In the demo, ownership of acme-shop had first gone from dev-b to dev-c (that is the screen above). Before removing dev-c, Transfer⦠on dev-c's page moved it back to dev-b. Each transfer is recorded in the audit log as rbac.assignment.owner_transferred.
A project created after the conversion to a Company org starts with no owner. Its Access page says "This project has no owner.", and an org_admin picks one with Designate owner.
Step 4: Press Remove from org
Remove from org is at the bottom of dev-c's page. It opens a confirmation:
The confirmation names each service token dev-c created (dev-c-laptop) with the start of its Token ID; removing dev-c revokes them too. Any CI job using those tokens stops, so this is the moment to check that nothing important depends on them.
Here is dev-c's login and the dev-c-laptop token, pulling before and after Remove:
After the removal, the token gets AUTH_REQUIRED (invalid, expired or revoked token) with exit code 3, and the login gets PERMISSION_DENIED with exit code 4. The token was tried about five seconds after the removal and the login about fifteen seconds after, and both were already cut off. A minute later, nothing had changed.
dotvault may keep using what it knows about who belongs to which org for up to 60 seconds, so a removal takes effect within a minute at most.
Step 5: Confirm in the lists and the audit log
dev-c's row is gone from Members. dev-c's row is also gone from the Access page of acme-shop, and the backend team now has only dev-b.
In Service Tokens, choose All (incl. revoked) to include revoked tokens.
dev-c-laptop is revoked. The Created by column shows who created each token.
In the audit log, the removal is three rows with the same timestamp. The Metadata column is at the right end of the table, so scroll the table right to read it (the bottom part of the figure).
| Action | What it records |
|---|---|
member.removed |
dev-c was removed from the org. "β role: member" in Change is the role dev-c had; revoked_token_ids in Metadata lists the tokens revoked with it |
member.grants_removed |
dev-c's project grants (env_permission) and team memberships (team_membership) were deleted |
service_token.revoked |
The token dev-c created, dev-c-laptop, was revoked |
The Metadata records which grants were deleted, so even if you forgot step 1, you can read them here.
Step 6: Replace the values they could read
Removing dev-c from dotvault does nothing to the .env files dev-c has already pulled; they stay on dev-c's laptop. To make those values useless, the values themselves have to change.
In the demo, dev-b replaced the two values in development of acme-shop:
dotvault set STRIPE_SECRET_KEY=<new value> -p acme-shop -E development
dotvault set DATABASE_URL=<new value> -p acme-shop -E development
Each printed a line such as set STRIPE_SECRET_KEY (v3) in .env [acme-shop/development], the third change to that key. dev-c could read every environment through the team, so in real use you would replace the production, staging and qa values the same way.
For an API key issued by another service, such as a payment provider, issue a new key in that service's dashboard and disable the old one, then store the new value with set. For a database password, change it in the database first. Changing the value in dotvault alone leaves the old value on dev-c's laptop still working against that service.
Wrapping up
Hand .env files around, and the values on a leaver's laptop cannot be taken back. Invite people into a Company org in dotvault, grant access per project and per environment, and when someone leaves, note what they could read, check the audit log, transfer their projects, and press Remove from org. Their tokens, project grants and team memberships go with them, and in the demo both their token and their login were refused within fifteen seconds. What remains is replacing the values they could read.
dotvault stores the secrets in your .env and config files server-side and hands them to any authorised developer, CI job or AI agent with a single command (https://dotvault.io). It will be released free of charge when this series ends, and the steps in these articles are the steps you will use on day one.
If you find this useful, please like and follow.
Our products are listed at https://www.eln.ne.jp/products
EarthLink Network builds its own products to run the whole company on AI β each one born from a need along the way. See the full index of what we build:
β The 18 products EarthLink Network builds in-house
For more about the company and each product, visit www.eln.ne.jp.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.












