From b9f3920fc07130c3317863159d152fe7a7fcdef0 Mon Sep 17 00:00:00 2001 From: rohan Date: Fri, 3 Apr 2026 18:02:45 +0530 Subject: [PATCH 01/12] feat: add docs for teams and scim Signed-off-by: rohan --- src/components/Navigation.jsx | 5 + src/pages/access-control/index.mdx | 6 +- .../access-control/provisioning/scim.mdx | 197 ++++++++++++++++++ src/pages/access-control/teams.mdx | 157 ++++++++++++++ 4 files changed, 364 insertions(+), 1 deletion(-) create mode 100644 src/pages/access-control/provisioning/scim.mdx create mode 100644 src/pages/access-control/teams.mdx diff --git a/src/components/Navigation.jsx b/src/components/Navigation.jsx index 083c9c7b..46a35239 100644 --- a/src/components/Navigation.jsx +++ b/src/components/Navigation.jsx @@ -260,6 +260,11 @@ export const navigation = [ href: '/access-control/authentication/oidc-sso', }, { title: 'Tokens', href: '/access-control/authentication/tokens' }, + { + title: 'SCIM Provisioning', + href: '/access-control/provisioning/scim', + }, + { title: 'Teams', href: '/access-control/teams' }, { title: 'Service Accounts', href: '/access-control/service-accounts' }, { title: 'External Identities', diff --git a/src/pages/access-control/index.mdx b/src/pages/access-control/index.mdx index 52f2c6c0..08750f8c 100644 --- a/src/pages/access-control/index.mdx +++ b/src/pages/access-control/index.mdx @@ -34,9 +34,13 @@ User authentication in Phase is designed for seamless and secure access for huma Programmatic access to secrets in Phase is facilitated by Service Accounts. A Service Account is a special type of account that represents non-human users, such as applications, automation processes, or CI/CD pipelines, that need to interact with Phase programmatically through the API, SDK, or CLI. -[Read more](/access-control/service-accounts) about how service accounts work. +[Read more](/access-control/service-accounts) about how service accounts work. +## Teams +Teams let you group members and service accounts together and grant them scoped access to apps and environments. Instead of managing access individually, you assign access at the team level — when someone joins the team, they automatically receive the right encryption keys. Teams support optional role overrides and work with SCIM provisioning for automated group sync. + +[Read more](/access-control/teams) about how teams work. ## Access Control - Key Concepts diff --git a/src/pages/access-control/provisioning/scim.mdx b/src/pages/access-control/provisioning/scim.mdx new file mode 100644 index 00000000..a0f1e533 --- /dev/null +++ b/src/pages/access-control/provisioning/scim.mdx @@ -0,0 +1,197 @@ +import { Tag } from '@/components/Tag' +import { DocActions } from '@/components/DocActions' + +export const description = 'Set up SCIM v2 provisioning to automatically sync users and groups from your identity provider to Phase.' + +PROVISIONING + +# SCIM Provisioning + +SCIM (System for Cross-domain Identity Management) v2 enables automatic user and group provisioning from your identity provider (IdP) to Phase. When configured, your IdP can automatically create, update, and deactivate user accounts in Phase, eliminating the need for manual user management. + + + + + SCIM provisioning is available for organisations with an `Enterprise` tier subscription. See [Pricing](https://phase.dev/pricing). + + +## How it works + +When SCIM is enabled, your identity provider communicates with Phase's SCIM v2 API to: + +- **Provision users**: Automatically create Phase accounts when users are assigned to the application in your IdP. Users are created with a `Pending` status until they complete their first login and key ceremony. +- **Deprovision users**: Automatically deactivate Phase accounts when users are unassigned or disabled in your IdP. The user's environment keys are revoked and their org membership is soft-deleted. +- **Sync groups**: Map IdP groups to Phase Teams, automatically managing team membership as group assignments change. +- **Update user attributes**: Keep user details (name, email) in sync between your IdP and Phase. + +### User lifecycle + +1. **IdP assigns user** → SCIM creates a Phase user account with `Pending` status (SCIM + Pending badges shown in the console) +2. **User logs in via SSO** → Phase auto-links the SSO account to the SCIM-provisioned user +3. **User completes key ceremony** → User sets up their sudo password and recovery phrase, enabling them to decrypt secrets +4. **IdP unassigns user** → SCIM deactivates the user, revokes environment keys, and removes them from the organisation + +## Enable SCIM in Phase + +Before configuring your identity provider, enable SCIM in the Phase Console and create a provisioning token: + +1. Log into the Phase Console as an **Owner** or **Admin**. + +2. Navigate to **Access** > **SCIM** in the sidebar. + +3. Toggle **Enable SCIM** to on. + +4. Copy the **SCIM Base URL** shown on the page. It will look like: + + ``` + https://[YOUR_PHASE_HOST]/service/scim/v2/ + ``` + +5. Click **Create token** to generate a SCIM bearer token. Give it a descriptive name (e.g., "Azure Entra ID") and select an expiry period. + +6. Copy the generated token immediately — it will not be shown again. This token will be used as the **Secret Token** in your identity provider's SCIM configuration. + + + Treat the SCIM token like a password. Anyone with this token can provision and deprovision users in your Phase organisation. + + +## Microsoft Entra ID (Azure AD) + +Microsoft Entra ID supports SCIM-based provisioning through Enterprise Applications. Follow these steps to configure automatic user and group provisioning from Entra ID to Phase. + +### Prerequisites + +- A Microsoft Entra ID tenant with a P1 or P2 license (required for enterprise app provisioning) +- An existing Phase Enterprise organisation with SCIM enabled and a SCIM token (see above) +- OIDC SSO configured for Microsoft Entra ID (see [Entra ID OIDC setup](/access-control/authentication/oidc-sso#microsoft-entra-id--azure-ad)) + + + SCIM provisioning and OIDC SSO are complementary features. SCIM handles account lifecycle (creation, deactivation), while OIDC handles authentication (login). You should configure both for the best experience. + + +### Step 1: Create an Enterprise Application + +1. Sign in to the [Azure Portal](https://portal.azure.com). + +2. Navigate to **Microsoft Entra ID** > **Enterprise applications**. + +3. Click **+ New application** at the top. + +4. Click **+ Create your own application**. + +5. Enter a name for the application (e.g., "Phase Console SCIM"), select **Integrate any other application you find in the gallery (Non-gallery)**, and click **Create**. + +### Step 2: Configure Provisioning + +1. In your newly created Enterprise Application, select **Provisioning** from the left sidebar under *Manage*. + +2. Click **Get started** or set the **Provisioning Mode** to **Automatic**. + +3. Under **Admin Credentials**, enter: + - **Tenant URL**: The SCIM Base URL from Phase (e.g., `https://[YOUR_PHASE_HOST]/service/scim/v2/`) + - **Secret Token**: The SCIM token you generated in Phase + +4. Click **Test Connection** to verify connectivity. Azure should report "The supplied credentials are authorized to enable provisioning". + +5. Click **Save**. + +### Step 3: Configure Attribute Mappings + +After saving credentials, Azure will show the **Mappings** section. You need to configure both user and group mappings. + +#### User Attribute Mappings + +1. Click **Provision Microsoft Entra ID Users**. + +2. Ensure the following mappings are present (these are the minimum required by Phase's SCIM implementation): + + | Microsoft Entra ID Attribute | customappsso Attribute | Mapping Type | + |------|-------|------| + | `userPrincipalName` | `userName` | Direct | + | `Switch([IsSoftDeleted], , "False", "True", "True", "False")` | `active` | Expression | + | `mail` | `emails[type eq "work"].value` | Direct | + | `displayName` | `displayName` | Direct | + | `givenName` | `name.givenName` | Direct | + | `surname` | `name.familyName` | Direct | + + + The `mail` → `emails[type eq "work"].value` mapping is important. Phase uses this email to link the SCIM-provisioned account with the SSO login. If your users don't have the `mail` attribute populated in Entra ID, you can map `userPrincipalName` to `emails[type eq "work"].value` instead. + + +3. Click **Save**. + +#### Group Attribute Mappings + +1. Go back to the Provisioning page and click **Provision Microsoft Entra ID Groups**. + +2. Ensure the following mappings are present: + + | Microsoft Entra ID Attribute | customappsso Attribute | Mapping Type | + |------|-------|------| + | `displayName` | `displayName` | Direct | + | `objectId` | `externalId` | Direct | + | `members` | `members` | Direct | + +3. Click **Save**. + +### Step 4: Assign Users and Groups + +1. Navigate to **Users and groups** in the left sidebar of your Enterprise Application. + +2. Click **+ Add user/group**. + +3. Select the users and/or groups you want to provision to Phase, then click **Assign**. + + + Only users and groups explicitly assigned to the Enterprise Application will be provisioned. The default scope setting is "Sync only assigned users and groups". + + +### Step 5: Start Provisioning + +1. Go back to the **Provisioning** page. + +2. Click **Start provisioning** to begin the initial sync. + +3. The initial provisioning cycle may take a few minutes. You can monitor progress under **Provisioning logs** in Azure, or in the **SCIM > Provisioning Logs** section of the Phase Console. + +4. Once complete, provisioned users will appear on the Phase **Members** page with `SCIM` and `Pending` badges. Groups will appear as **Teams** in Phase. + +### Step 6: Test the Flow + +1. Verify that provisioned users appear in the Phase Console under **Access** > **Members** with the SCIM and Pending badges. + +2. Have a provisioned user log in via SSO (Entra ID OIDC). They will be redirected to the **key ceremony** page to set up their sudo password and recovery phrase. + +3. After completing the key ceremony, the user should be able to access secrets in any environments their team has access to. + +### Troubleshooting: Microsoft Entra ID + +#### Provisioning shows "quarantine" status + +This usually means Azure received multiple errors from the SCIM endpoint. Check: +- The SCIM token hasn't expired (check the Phase Console SCIM page) +- The Phase instance is accessible from Azure's IP ranges +- Review the provisioning logs in both Azure and the Phase Console for specific error messages + +#### User can't log in after SCIM provisioning + +Ensure that: +1. OIDC SSO is configured for Entra ID (SCIM handles provisioning, OIDC handles login) +2. The user's email in Entra ID matches between the SCIM provisioning and the OIDC token claims +3. The user is assigned to both the SCIM Enterprise Application and the OIDC App Registration (or the OIDC app allows all directory users) + +#### Re-provisioning a previously deactivated user + +If you remove a user from the application and then re-add them, Azure may skip provisioning with a `RedundantSoftDelete` error. To resolve this: + +1. Stop provisioning in the Enterprise Application +2. Ensure the user is assigned under **Users and groups** +3. Go to **Provisioning** > click **Restart provisioning** (this clears Azure's internal cycle state) +4. If the issue persists, use **Provision on demand** for the specific user after restarting provisioning + +#### Groups not syncing as Teams + +Ensure that: +- Group provisioning is enabled in the attribute mappings +- The groups are assigned to the Enterprise Application +- The `displayName` and `members` attributes are mapped correctly diff --git a/src/pages/access-control/teams.mdx b/src/pages/access-control/teams.mdx new file mode 100644 index 00000000..913f177c --- /dev/null +++ b/src/pages/access-control/teams.mdx @@ -0,0 +1,157 @@ +import { Tag } from '@/components/Tag' +import { DocActions } from '@/components/DocActions' + +export const description = 'Organize members and service accounts into Teams with scoped app access and optional role overrides.' + +ACCESS CONTROL + +# Teams + +Teams let you group members and service accounts together and grant them access to specific apps and environments. Instead of managing access for each individual, you assign access at the team level — when someone joins the team, they automatically get the right keys. + + + + + Teams require apps with [Server-Side Encryption (SSE)](/console/apps#encryption-mode) enabled, since the server provisions encryption keys on behalf of team members. + + +## How it works + +A Team is an organisation-level group that contains **members** (human users) and/or **service accounts**. Teams are granted access to one or more apps, scoped to specific environments within each app. + +When a team is added to an app: + +1. You select which environments the team should have access to (e.g. `Development`, `Staging`) +2. Phase's server automatically wraps `EnvironmentKey`s for every team member using the app's `ServerEnvironmentKey` +3. Team members can immediately decrypt secrets in those environments + +When a member is added to a team that already has app access, keys are provisioned automatically. When a member is removed, their team-granted keys are revoked — unless they also have individual access to the same environment. + +### Key concepts + +| Concept | Description | +|---------|-------------| +| **Team membership** | A user or service account belongs to one or more teams | +| **Team app access** | A team is granted access to an app, scoped to specific environments | +| **Role overrides** | Teams can optionally override the org role's app-level permissions for their members | +| **Union semantics** | If a user is in multiple teams with access to the same app, they get the **union** of all team role permissions | +| **Individual priority** | Individual (direct) app access always uses the org role, not team roles | +| **Grant tracking** | Phase tracks *why* each `EnvironmentKey` exists (individual vs team grant) so that removing team access doesn't accidentally revoke individually-granted keys | + +## Creating a Team + +1. Navigate to **Access** > **Teams** in the sidebar. + +2. Click **Create Team**. + +3. Enter a **name** and optional **description** for the team. + +4. Optionally set **role overrides** (see [Role overrides](#role-overrides) below). If you skip this, team members will use their org role for app-level permissions. + +5. Click **Create**. The team is created with no members or app access — you'll add those next. + +## Managing team members + +### Adding members + +1. Open the team detail page by clicking on the team name. + +2. Click **Add members** or **Add service accounts**. + +3. Select the members or service accounts you want to add from the list. Only org members who aren't already in the team are shown. + +4. Click **Add**. If the team already has app access, encryption keys are provisioned immediately for the new members. + +### Removing members + +1. On the team detail page, find the member you want to remove. + +2. Click the remove button next to their name. + +3. Confirm the removal. Phase will revoke the member's team-granted environment keys. If the member also has individual access to the same environments, those keys are preserved. + +## Managing team app access + +### Adding apps to a team + +1. On the team detail page, click **Add apps**. + +2. Select the app you want to add. Only SSE-enabled apps are shown — if an app doesn't appear, enable SSE on it first. + +3. Select which **environments** within the app the team should have access to. + +4. Click **Add**. Phase provisions environment keys for all team members with an active `identity_key`. Members who haven't completed their key ceremony yet (e.g. SCIM-provisioned users who haven't logged in) will receive keys on their first login. + +### Updating environment access + +After a team has been added to an app, you can change which environments it has access to: + +1. Click **Manage** next to the app on the team detail page. + +2. Toggle environments on or off. + +3. Save. Keys are provisioned for newly added environments and revoked for removed environments. + +### Removing an app from a team + +1. Click the remove button next to the app on the team detail page. + +2. Confirm the removal. All team-granted environment keys for that app are revoked for every team member. + +## Role overrides + +By default, team members use their **org role's app-level permissions** when accessing team-granted apps. For example, a `Developer` in a team uses the Developer role's app permissions (can read/write secrets, but can't delete environments). + +Teams support two optional role overrides that change what permissions members have when accessing apps through that team: + +| Override | Applies to | Description | +|----------|-----------|-------------| +| **Member role** | Human users | Overrides the org role's app-level permissions for all human members of this team | +| **Service account role** | Service accounts | Overrides the org role's app-level permissions for all service accounts in this team | + +When a role override is set, it replaces the org role's `app_permissions` for resources accessed through that team. Org-level permissions are unaffected. + +### Union semantics + +If a user belongs to multiple teams that all have access to the same app, Phase takes the **union** of permissions across all applicable team roles. If *any* team role grants a permission, the user has that permission. + +**Example:** Alice is in Team A (role: `Developer`) and Team B (role: `Manager`). Both teams have access to App X. Alice gets the union of Developer and Manager app-level permissions for App X. + +### Individual access takes priority + +If a user has both **individual** (direct) access and **team** access to the same app, the individual access path is used. This means the user's org role determines app-level permissions, regardless of any team role overrides. + +## SSE requirement + +Teams require [Server-Side Encryption (SSE)](/console/apps#encryption-mode) to be enabled on any app they access. This is because the server needs to provision encryption keys on behalf of team members — it unwraps the `ServerEnvironmentKey` and re-wraps the environment seed/salt for each member's public key. + +If an app has SSE disabled, it won't appear in the app selection dialog when adding apps to a team. You can enable SSE on an app from the app's settings page under **Encryption Mode**. + + + Enabling SSE changes the encryption model for the app — the server gains the ability to decrypt secrets. This is required for Teams, all third-party sync integrations, and REST API access. See [Encryption Mode](/console/apps#encryption-mode) for details. + + +## SCIM-managed teams + +When [SCIM provisioning](/access-control/provisioning/scim) is configured, your identity provider can create and manage teams automatically by syncing IdP groups to Phase teams. SCIM-managed teams have the following restrictions: + +- Cannot be renamed, deleted, or have members manually added/removed from the Phase Console +- Membership changes must be made in the identity provider +- A `SCIM` badge is shown next to the team name in the console +- Role overrides and app access can still be managed from Phase + +## Grant tracking + +Phase tracks the **reason** each `EnvironmentKey` exists using `EnvironmentKeyGrant` records. Each grant is tagged as either `individual` (direct app access) or `team` (via team membership), with a reference to the specific team. + +This prevents a common pitfall: if a user has both individual and team access to the same environment, removing the team access should *not* revoke the key. Phase only soft-deletes an `EnvironmentKey` when all of its grants have been removed. + +## Viewing team access on member and app pages + +### Member detail page + +Each member's detail page (under **Access** > **Members** > member name) shows a **Teams** section listing all teams the member belongs to, along with links to each team's detail page. + +### App access page + +Each app's **Access** > **Teams** tab shows all teams that have access to the app, the environments they can access, and their role overrides. You can add/remove teams and manage environment scoping directly from this page. From 19c9f082d4f4b8047e1aeb70f94b59965d02b54f Mon Sep 17 00:00:00 2001 From: rohan Date: Sat, 4 Apr 2026 16:04:17 +0530 Subject: [PATCH 02/12] feat: add rbac docs for new teams and scim permission classes Signed-off-by: rohan --- src/pages/access-control/roles.mdx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/pages/access-control/roles.mdx b/src/pages/access-control/roles.mdx index 04054392..ec4e497b 100644 --- a/src/pages/access-control/roles.mdx +++ b/src/pages/access-control/roles.mdx @@ -44,6 +44,8 @@ The organization owner. This role is automatically assigned when a user creates | **Roles** | Full access | ✅ | ✅ | ✅ | ✅ | | **Integration Credentials** | Full access | ✅ | ✅ | ✅ | ✅ | | **Network Access Policies** | Full access | ✅ | ✅ | ✅ | ✅ | +| **Teams** | Full access | ✅ | ✅ | ✅ | ✅ | +| **SCIM** | Full access | ✅ | ✅ | ✅ | ✅ | #### App-level permissions: @@ -79,6 +81,8 @@ Admin users have access to most resources and permissions, and have global acces | **Roles** | Full access | ✅ | ✅ | ✅ | ✅ | | **Integration Credentials** | Full access | ✅ | ✅ | ✅ | ✅ | | **Network Access Policies** | Full access | ✅ | ✅ | ✅ | ✅ | +| **Teams** | Full access | ✅ | ✅ | ✅ | ✅ | +| **SCIM** | Full access | ✅ | ✅ | ✅ | ✅ | #### App-level permissions: @@ -116,6 +120,8 @@ Management users with broad access to environments, secrets, and service account | **Roles** | Full access | ✅ | ✅ | ✅ | ✅ | | **Integration Credentials** | Full access | ✅ | ✅ | ✅ | ✅ | | **Network Access Policies** | Full access | ✅ | ✅ | ✅ | ✅ | +| **Teams** | Full access | ✅ | ✅ | ✅ | ✅ | +| **SCIM** | No access | ❌ | ❌ | ❌ | ❌ | #### App-level permissions: @@ -151,6 +157,8 @@ Default role for Service Accounts, providing programmatic access to secrets with | **Roles** | Read access | ✅ | ❌ | ❌ | ❌ | | **Integration Credentials** | Read access | ✅ | ❌ | ❌ | ❌ | | **Network Access Policies** | Read access | ✅ | ❌ | ❌ | ❌ | +| **Teams** | No access | ❌ | ❌ | ❌ | ❌ | +| **SCIM** | No access | ❌ | ❌ | ❌ | ❌ | #### App-level permissions: @@ -186,6 +194,8 @@ Developers have limited permissions at the organization level and must be given | **Roles** | Read access | ✅ | ❌ | ❌ | ❌ | | **Integration Credentials** | Custom access | ✅ | ✅ | ✅ | ❌ | | **Network Access Policies** | Read access | ✅ | ❌ | ❌ | ❌ | +| **Teams** | Read access | ✅ | ❌ | ❌ | ❌ | +| **SCIM** | No access | ❌ | ❌ | ❌ | ❌ | #### App-level permissions: From eeaf4d5433ff4dd2a3e21dfac61f56cc7f8ee86d Mon Sep 17 00:00:00 2001 From: rohan Date: Sat, 4 Apr 2026 16:04:26 +0530 Subject: [PATCH 03/12] feat: add docs for okta scim Signed-off-by: rohan --- .../access-control/provisioning/scim.mdx | 161 +++++++++++++++++- 1 file changed, 156 insertions(+), 5 deletions(-) diff --git a/src/pages/access-control/provisioning/scim.mdx b/src/pages/access-control/provisioning/scim.mdx index a0f1e533..2b358ea9 100644 --- a/src/pages/access-control/provisioning/scim.mdx +++ b/src/pages/access-control/provisioning/scim.mdx @@ -19,7 +19,7 @@ SCIM (System for Cross-domain Identity Management) v2 enables automatic user and When SCIM is enabled, your identity provider communicates with Phase's SCIM v2 API to: -- **Provision users**: Automatically create Phase accounts when users are assigned to the application in your IdP. Users are created with a `Pending` status until they complete their first login and key ceremony. +- **Provision users**: Automatically create Phase accounts when users are assigned to the application in your IdP. Users are created with a `Pending` status until they complete their first login and account setup. - **Deprovision users**: Automatically deactivate Phase accounts when users are unassigned or disabled in your IdP. The user's environment keys are revoked and their org membership is soft-deleted. - **Sync groups**: Map IdP groups to Phase Teams, automatically managing team membership as group assignments change. - **Update user attributes**: Keep user details (name, email) in sync between your IdP and Phase. @@ -28,7 +28,7 @@ When SCIM is enabled, your identity provider communicates with Phase's SCIM v2 A 1. **IdP assigns user** → SCIM creates a Phase user account with `Pending` status (SCIM + Pending badges shown in the console) 2. **User logs in via SSO** → Phase auto-links the SSO account to the SCIM-provisioned user -3. **User completes key ceremony** → User sets up their sudo password and recovery phrase, enabling them to decrypt secrets +3. **User completes account setup** → User sets up their sudo password and recovery phrase, enabling them to decrypt secrets 4. **IdP unassigns user** → SCIM deactivates the user, revokes environment keys, and removes them from the organisation ## Enable SCIM in Phase @@ -160,19 +160,30 @@ After saving credentials, Azure will show the **Mappings** section. You need to 1. Verify that provisioned users appear in the Phase Console under **Access** > **Members** with the SCIM and Pending badges. -2. Have a provisioned user log in via SSO (Entra ID OIDC). They will be redirected to the **key ceremony** page to set up their sudo password and recovery phrase. +2. Have a provisioned user log in via SSO (Entra ID OIDC). They will be redirected to the **account setup** page to set up their sudo password and recovery phrase. -3. After completing the key ceremony, the user should be able to access secrets in any environments their team has access to. +3. After completing account setup, the user should be able to access secrets in any environments their team has access to. ### Troubleshooting: Microsoft Entra ID #### Provisioning shows "quarantine" status -This usually means Azure received multiple errors from the SCIM endpoint. Check: +This usually means Azure received multiple errors from the SCIM endpoint. When quarantined, Azure exponentially backs off the retry interval (up to several hours between attempts). Check: - The SCIM token hasn't expired (check the Phase Console SCIM page) - The Phase instance is accessible from Azure's IP ranges - Review the provisioning logs in both Azure and the Phase Console for specific error messages +To clear a quarantine and resume normal provisioning: + +1. In the Azure Portal, go to your Enterprise Application > **Provisioning**. +2. Click **Stop provisioning** and wait for it to confirm. +3. Click **Start provisioning** — this clears the quarantine state and triggers a fresh initial sync. +4. Verify the **Provisioning Status** toggle is set to **On**, then click **Save**. + + + "Restart provisioning" clears the quarantine but does not always re-enable the provisioning toggle. Always verify the toggle is **On** and click **Save** after restarting. + + #### User can't log in after SCIM provisioning Ensure that: @@ -195,3 +206,143 @@ Ensure that: - Group provisioning is enabled in the attribute mappings - The groups are assigned to the Enterprise Application - The `displayName` and `members` attributes are mapped correctly + +## Okta + +Okta supports SCIM-based provisioning through its application integration platform. Follow these steps to configure automatic user and group provisioning from Okta to Phase. + +### Prerequisites + +- An Okta organisation with the ability to create custom SCIM integrations +- An existing Phase Enterprise organisation with SCIM enabled and a SCIM token (see [Enable SCIM in Phase](#enable-scim-in-phase)) +- OIDC SSO configured for Okta (see [Okta OIDC setup](/access-control/authentication/oidc-sso#okta)) + + + SCIM provisioning and OIDC SSO are complementary features. SCIM handles account lifecycle (creation, deactivation), while OIDC handles authentication (login). You should configure both for the best experience. + + +### Step 1: Create a SCIM Application in Okta + +If you already have an Okta OIDC app for Phase SSO, you can add SCIM provisioning to it. Otherwise, create a new app: + +1. Sign in to the [Okta Admin Console](https://admin.okta.com). + +2. Navigate to **Applications** > **Applications**. + +3. If adding SCIM to an existing app, click on your Phase OIDC app and skip to Step 2. Otherwise, click **Create App Integration**. + +4. Select **SWA - Secure Web Authentication** (this creates a bookmark app that supports SCIM provisioning), and click **Next**. + +5. Enter a name (e.g., "Phase Console") and the login URL for your Phase instance. Click **Finish**. + + + If you already have a separate OIDC app for SSO, you can use a SWA app purely for SCIM provisioning. Users will still authenticate via the OIDC app — the SWA app only handles user/group lifecycle. + + +### Step 2: Enable SCIM Provisioning + +1. In your application, go to the **General** tab. + +2. Click **Edit** on the App Settings panel. + +3. Under **Provisioning**, select **SCIM** and click **Save**. + +4. A new **Provisioning** tab will appear. Click on it. + +5. Under **SCIM Connection**, click **Edit** and enter: + - **SCIM connector base URL**: The SCIM Base URL from Phase (e.g., `https://[YOUR_PHASE_HOST]/service/scim/v2`) + - **Unique identifier field for users**: `userName` + - **Supported provisioning actions**: Check **Push New Users**, **Push Profile Updates**, and **Push Groups** + - **Authentication Mode**: `HTTP Header` + - **Authorization**: Paste the SCIM bearer token you generated in Phase (the token value only, without the `Bearer` prefix) + +6. Click **Test Connector Configuration** to verify connectivity. Okta should report success for the enabled actions. + +7. Click **Save**. + +### Step 3: Configure Provisioning Actions + +1. Still on the **Provisioning** tab, click **To App** in the left panel. + +2. Click **Edit** and enable: + - **Create Users** — Allows Okta to provision new users in Phase + - **Update User Attributes** — Keeps user details in sync + - **Deactivate Users** — Deactivates Phase accounts when users are unassigned in Okta + +3. Click **Save**. + +### Step 4: Verify Attribute Mappings + +1. Still under **Provisioning** > **To App**, scroll down to the **Attribute Mappings** section. + +2. Okta pre-populates a comprehensive set of default attribute mappings. No changes are required — the defaults already include everything Phase needs. Verify that the following key mappings are present: + + | Okta Attribute | App Attribute | Default Value | + |------|-------|------| + | `userName` | `userName` | Configured in Sign On settings | + | `givenName` | `name.givenName` | `user.firstName` | + | `familyName` | `name.familyName` | `user.lastName` | + | `email` | `emails[type eq "work"].value` | `user.email` | + | `displayName` | `displayName` | `user.displayName` | + + + Okta sends many additional attributes by default (phone, address, title, etc.). Phase safely ignores any attributes it doesn't need — you can leave them as-is or remove them if you prefer a minimal mapping. + + + + Okta uses `userName` (typically the user's email address) as the primary identifier. Ensure that the `userName` in Okta matches the email address used for SSO login, so Phase can link the SCIM-provisioned account with the OIDC identity. + + +### Step 5: Assign Users and Groups + +1. Go to the **Assignments** tab in your application. + +2. Click **Assign** and select either **Assign to People** or **Assign to Groups**. + +3. Select the users and/or groups you want to provision to Phase, then click **Assign** and **Save and Go Back**. + +4. If you assigned groups, go to the **Push Groups** tab: + - Click **Push Groups** > **Find groups by name** (or by rule) + - Select the groups you want to push to Phase + - Click **Save** + + + In Okta, assigning a group under **Assignments** grants group members access to the app (user provisioning). The **Push Groups** tab controls whether the group itself is synced to Phase as a Team. You typically need both: assign the group for user provisioning, and push the group for team creation. + + +### Step 6: Verify Provisioning + +1. Navigate to **Dashboard** > **Tasks** in the Okta Admin Console to monitor provisioning progress. + +2. Check the Phase Console under **Access** > **Members** — provisioned users should appear with `SCIM` and `Pending` badges. + +3. Check **Access** > **Teams** — pushed groups should appear as teams with a `SCIM` badge. + +4. Have a provisioned user log in via Okta SSO. They will be redirected to the account setup page to set up their sudo password and recovery phrase. + +### Troubleshooting: Okta + +#### "Error authenticating" when testing the connector + +- Verify the SCIM base URL ends with `/scim/v2` (no trailing slash) +- Verify the token is entered without the `Bearer` prefix — Okta adds it automatically +- Ensure the SCIM token hasn't expired in the Phase Console + +#### Users not being provisioned + +- Check that **Create Users** is enabled under **Provisioning** > **To App** +- Verify users are assigned to the application under the **Assignments** tab +- Check the **Tasks** page in Okta for specific error messages +- Review the SCIM provisioning logs in the Phase Console for request/response details + +#### Groups not syncing as Teams + +- Ensure the group is both **assigned** to the app (Assignments tab) and **pushed** (Push Groups tab) +- Check that the group push status shows "Active" — if it shows an error, click on it for details +- Verify that group push is enabled in the SCIM connector settings (**Push Groups** checkbox) + +#### User can't log in after SCIM provisioning + +- Ensure OIDC SSO is configured for Okta (SCIM handles provisioning, OIDC handles login) +- The user's email in Okta must match between the SCIM `userName` and the OIDC token `email` claim +- If using separate apps for SCIM and OIDC, the user must be assigned to both From 0419c47643b7c9d6e375024cf9f596a55a7d9fb7 Mon Sep 17 00:00:00 2001 From: rohan Date: Wed, 8 Apr 2026 13:24:03 +0530 Subject: [PATCH 04/12] fix: okta clarification Signed-off-by: rohan --- src/pages/access-control/provisioning/scim.mdx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/pages/access-control/provisioning/scim.mdx b/src/pages/access-control/provisioning/scim.mdx index 2b358ea9..7630dc81 100644 --- a/src/pages/access-control/provisioning/scim.mdx +++ b/src/pages/access-control/provisioning/scim.mdx @@ -341,6 +341,16 @@ If you already have an Okta OIDC app for Phase SSO, you can add SCIM provisionin - Check that the group push status shows "Active" — if it shows an error, click on it for details - Verify that group push is enabled in the SCIM connector settings (**Push Groups** checkbox) +#### User deprovisioned after removing direct assignment, despite being in a pushed group + +In Okta, **Push Groups** and **Assignments** are independent: +- **Assignments** controls user provisioning (who gets a Phase account) +- **Push Groups** controls group/team syncing (which groups appear as Phase Teams) + +If a user is only directly assigned (not via a group assignment), removing that direct assignment deprovisions them — even if they belong to a pushed group. Push Groups does not grant app assignment. + +**Fix**: Assign groups under the **Assignments** tab (not just Push Groups). This way, group membership is the single source of truth for both user provisioning and team sync. When a user is removed from the group in Okta, they are automatically deprovisioned and removed from the team. + #### User can't log in after SCIM provisioning - Ensure OIDC SSO is configured for Okta (SCIM handles provisioning, OIDC handles login) From c76d7b5b1ef006707c278173ef15a303a07d17ea Mon Sep 17 00:00:00 2001 From: rohan Date: Tue, 14 Apr 2026 19:47:34 +0530 Subject: [PATCH 05/12] feat: add docs for team-owned service accounts, role updates, etc Signed-off-by: rohan --- src/pages/access-control/index.mdx | 1 + src/pages/access-control/roles.mdx | 13 +++++- src/pages/access-control/service-accounts.mdx | 11 ++++- src/pages/access-control/teams.mdx | 40 +++++++++++++++++++ 4 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/pages/access-control/index.mdx b/src/pages/access-control/index.mdx index 08750f8c..da0d1aeb 100644 --- a/src/pages/access-control/index.mdx +++ b/src/pages/access-control/index.mdx @@ -82,6 +82,7 @@ Phase's RBAC system allows you to define permissions for Create, Read, Update, a | **Members** | Manage user access within the app | | **Integrations** | Control setup and management of app integrations | | **Encryption Mode** | Manage encryption settings for the app | +| **Teams** | Manage team-based access within the app | ## Global Access diff --git a/src/pages/access-control/roles.mdx b/src/pages/access-control/roles.mdx index ec4e497b..8bf6f4fb 100644 --- a/src/pages/access-control/roles.mdx +++ b/src/pages/access-control/roles.mdx @@ -61,6 +61,7 @@ The organization owner. This role is automatically assigned when a user creates | **Service Accounts** | Full access | ✅ | ✅ | ✅ | ✅ | | **Integrations** | Full access | ✅ | ✅ | ✅ | ✅ | | **Encryption Mode** | Full access | ✅ | | ✅ | | +| **Teams** | Full access | ✅ | ✅ | ✅ | ✅ | ### Admin @@ -98,6 +99,7 @@ Admin users have access to most resources and permissions, and have global acces | **Service Accounts** | Full access | ✅ | ✅ | ✅ | ✅ | | **Integrations** | Full access | ✅ | ✅ | ✅ | ✅ | | **Encryption Mode** | Custom access | ✅ | | ✅ | | +| **Teams** | Full access | ✅ | ✅ | ✅ | ✅ | The `Owner` and `Admin` roles have global access. Learn more about global access [here](/access-control#global-access). @@ -137,6 +139,7 @@ Management users with broad access to environments, secrets, and service account | **Service Accounts** | Full access | ✅ | ✅ | ✅ | ✅ | | **Integrations** | Full access | ✅ | ✅ | ✅ | ✅ | | **Encryption Mode** | Custom access | ✅ | ❌ | ✅ | ❌ | +| **Teams** | Full access | ✅ | ✅ | ✅ | ✅ | ### Service @@ -174,6 +177,7 @@ Default role for Service Accounts, providing programmatic access to secrets with | **Service Accounts** | Read access | ✅ | ❌ | ❌ | ❌ | | **Integrations** | Read access | ✅ | ❌ | ❌ | ❌ | | **Encryption Mode** | Read access | ✅ | ❌ | ❌ | ❌ | +| **Teams** | Read access | ✅ | ❌ | ❌ | ❌ | ### Developer @@ -208,9 +212,10 @@ Developers have limited permissions at the organization level and must be given | **Logs** | Read access | ✅ | ❌ | ❌ | ❌ | | **Tokens (Legacy)** | Custom access | ✅ | ✅ | ❌ | ❌ | | **Members** | Read access | ✅ | ❌ | ❌ | ❌ | -| **Service Accounts** | Read access | ✅ | ❌ | ❌ | ❌ | +| **Service Accounts** | Custom access | ❌ | ✅ | ❌ | ❌ | | **Integrations** | Full access | ✅ | ✅ | ✅ | ✅ | | **Encryption Mode** | Custom access | ✅ | | ✅ | | +| **Teams** | Read access | ✅ | ❌ | ❌ | ❌ | ## Custom Roles @@ -270,6 +275,12 @@ Some actions require a combination of permissions across multiple resources. Bel - To view and delete other users Personal Access Tokens: - `MemberPersonalAccessTokens:read` - `MemberPersonalAccessTokens:delete` +- Adding or removing a Team's access to an App: + - `Teams:create` or `Teams:delete` (app-level) + - `Teams:read` (organisation-level) +- Managing a Team's environment scope within an App: + - `Teams:update` (app-level) + - `Teams:read` (organisation-level) - To Manage Network Access Policies of a User or Service Account: - `Members:read` - `Members:update` diff --git a/src/pages/access-control/service-accounts.mdx b/src/pages/access-control/service-accounts.mdx index cc41d414..662eb233 100644 --- a/src/pages/access-control/service-accounts.mdx +++ b/src/pages/access-control/service-accounts.mdx @@ -9,7 +9,16 @@ Service Accounts provide a secure and controlled method for programmatic access Service accounts share many of the properties and behavior of human user accounts. Service Accounts follow an Access Policy that can be defined by [Managed Roles](/access-control/roles#managed-roles) or [Custom Roles](/access-control/roles#creating-custom-roles) based on the permissions required. Service accounts are secured with the same security and cryptographic architecture as user accounts, and must be manually provisioned access to Apps and Environments in order to access secrets. - + + +## Org-level vs Team-owned Service Accounts + +Service accounts exist in two categories: + +- **Org-level** (default): Visible to all organisation members with `ServiceAccounts.read` permission. Created from the organisation-level Service Accounts page. This is the default behavior and works on all plans. +- **Team-owned**: Created within a [Team](/access-control/teams), visible only to team members and users with global access (Owner/Admin). The service account's lifecycle is tied to the team — if the team is deleted, team-owned SAs are deleted too. + +Team-owned service accounts are useful when a team needs dedicated programmatic access for team resources, that is isolated from other teams and users. See [Team-owned service accounts](/access-control/teams#team-owned-service-accounts) for details on creating and managing them. ## Create a new Service Account diff --git a/src/pages/access-control/teams.mdx b/src/pages/access-control/teams.mdx index 913f177c..8b63fc8a 100644 --- a/src/pages/access-control/teams.mdx +++ b/src/pages/access-control/teams.mdx @@ -131,6 +131,46 @@ If an app has SSE disabled, it won't appear in the app selection dialog when add Enabling SSE changes the encryption model for the app — the server gains the ability to decrypt secrets. This is required for Teams, all third-party sync integrations, and REST API access. See [Encryption Mode](/console/apps#encryption-mode) for details. +## Team-owned service accounts + +Service accounts can be **owned by a team**, meaning their lifecycle and visibility are tied to that team. This is useful when a team needs dedicated service accounts for programmatic access that only team members can see and manage. + +### Creating a team-owned service account + +1. On the team detail page, click **Create Team Service Account** in the Service Accounts section. + +2. Enter a name for the account. + +3. If the team has a defined Service Account role, the role for this account will be fixed. If there is no defined role for service accounts in the team, select a role for this account. + +4. Click **Create**. The The service account is automatically added as a member of the team and can access all apps and environments that the team is added to. + +Team-owned service accounts are visually distinguished with a team badge on both the team detail page and the organisation-level service accounts list. + +### Visibility rules + +| Account type | Who can see it | Who can manage it | +|---------|---------------|-------------------| +| **Org-level** (no team) | Anyone with `ServiceAccounts.read` | Anyone with `ServiceAccounts.update/delete` | +| **Team-owned** | Team members + Owner/Admin | Team members + Owner/Admin | + +Users who are not members of the owning team will not see team-owned service accounts in the organisation-level service accounts list — unless they have global access (Owner/Admin). + +### Ownership transfer + +Owner and Admin users can transfer a service account between org-level and team ownership: + +- **Team → Org-level**: Clears the team ownership. The service account becomes visible org-wide. Existing tokens and team membership are preserved. +- **Org-level → Team**: Assigns the service account to a team. Visibility narrows to team members and global access users. + +### Team deletion + +When a team is deleted, all team-owned service accounts are deleted and their tokens are revoked. Org-level service accounts that were added to the team as members are unaffected — they lose team-based app access but remain visible org-wide. + +### Removing a team-owned SA from its team + +A team-owned service account cannot be removed from its owning team. To dissociate it from the team, either delete the service account or transfer its ownership to the organisation (Owner/Admin only). + ## SCIM-managed teams When [SCIM provisioning](/access-control/provisioning/scim) is configured, your identity provider can create and manage teams automatically by syncing IdP groups to Phase teams. SCIM-managed teams have the following restrictions: From b99c70389ef7bade9be46aaf8bfda9f0c6e0f967 Mon Sep 17 00:00:00 2001 From: rohan Date: Tue, 14 Apr 2026 19:47:55 +0530 Subject: [PATCH 06/12] chore: rebuild md files, sitemap, llms.txt Signed-off-by: rohan --- public/access-control.md | 7 +- public/access-control/external-identities.md | 79 +++- public/access-control/provisioning/scim.md | 358 +++++++++++++++++++ public/access-control/roles.md | 23 +- public/access-control/service-accounts.md | 11 +- public/access-control/teams.md | 197 ++++++++++ public/cli/commands.md | 48 ++- public/llms.txt | 2 + public/public-api/external-identities.md | 231 +++++++++++- public/sitemap.xml | 164 ++++----- 10 files changed, 1010 insertions(+), 110 deletions(-) create mode 100644 public/access-control/provisioning/scim.md create mode 100644 public/access-control/teams.md diff --git a/public/access-control.md b/public/access-control.md index 52f2c6c0..da0d1aeb 100644 --- a/public/access-control.md +++ b/public/access-control.md @@ -34,9 +34,13 @@ User authentication in Phase is designed for seamless and secure access for huma Programmatic access to secrets in Phase is facilitated by Service Accounts. A Service Account is a special type of account that represents non-human users, such as applications, automation processes, or CI/CD pipelines, that need to interact with Phase programmatically through the API, SDK, or CLI. -[Read more](/access-control/service-accounts) about how service accounts work. +[Read more](/access-control/service-accounts) about how service accounts work. +## Teams +Teams let you group members and service accounts together and grant them scoped access to apps and environments. Instead of managing access individually, you assign access at the team level — when someone joins the team, they automatically receive the right encryption keys. Teams support optional role overrides and work with SCIM provisioning for automated group sync. + +[Read more](/access-control/teams) about how teams work. ## Access Control - Key Concepts @@ -78,6 +82,7 @@ Phase's RBAC system allows you to define permissions for Create, Read, Update, a | **Members** | Manage user access within the app | | **Integrations** | Control setup and management of app integrations | | **Encryption Mode** | Manage encryption settings for the app | +| **Teams** | Manage team-based access within the app | ## Global Access diff --git a/public/access-control/external-identities.md b/public/access-control/external-identities.md index 3b511388..ec54eb39 100644 --- a/public/access-control/external-identities.md +++ b/public/access-control/external-identities.md @@ -13,7 +13,9 @@ External Identities allow you to use third-party platforms and services to serve -Example use case: Imagine you have a fleet of EC2 instances in an autoscaling group (ASG) that runs an instance of your application. The Phase CLI is configured to inject secrets into your applications at runtime. Instead of manually provisioning access tokens for each client on each machine, you can use External Identities to establish a trusted relationship with an instance profile attached to the ASG. +Example use cases: +- **AWS**: You have a fleet of EC2 instances in an autoscaling group (ASG). Instead of manually provisioning access tokens for each machine, you establish a trusted relationship with the instance profile attached to the ASG. +- **Azure**: You have workloads running on AKS or Azure VMs with Managed Identities. Instead of managing Service Account tokens, you trust the VM's system-assigned managed identity to authenticate automatically. The authentication flow will be as follows: @@ -55,7 +57,8 @@ Benefits: ## Supported External Identity Providers Phase currently supports the following external identity providers: -- [**AWS IAM**](#aws-iam): Bind an AWS IAM User to a phase Service Account +- [**AWS IAM**](#aws-iam): Bind an AWS IAM User to a Phase Service Account +- [**Azure**](#azure): Bind an Azure Managed Identity or Service Principal to a Phase Service Account ## Configure an External Identity @@ -103,6 +106,59 @@ For AWS IAM, you will need to provide the following information: ![configure new identity](/assets/images/console/access-control/external-identities/configure-new-identity.png) +### Azure + +For Azure, you will need to provide the following information: + + + + Your Azure AD tenant ID (UUID format). Used to validate the `tid` claim in the JWT and to construct the OIDC discovery URL for key verification. + + + The App ID URI that maps to the IMDS `?resource=` parameter and the JWT `aud` claim. Default: `https://management.azure.com/`. This ensures tokens issued for other Azure resources cannot be reused. + + + Azure AD service principal object IDs allowed to authenticate. Matched against the `oid` claim in the JWT. Separate multiple IDs with commas. These are the object IDs of Managed Identities or Service Principals. + + + + +To find a **Service Principal's** object ID, run: `az ad sp show --id --query id -o tsv`. + +For **Managed Identities** (VMs, AKS, Functions), the principal ID is returned when you enable the identity: +```bash +az vm identity assign --resource-group --name +# Returns: { "principalId": "dcc518e4-...", ... } +``` +You can also find it in the Azure Portal under the resource's Identity blade. + + + +{` +sequenceDiagram + participant Client as Client + participant Phase as Phase + participant Azure as Azure AD + + Note over Client,Azure: 1. Get Azure AD Access Token + Client->>Azure: Request access token (IMDS / Service Principal / az login) + Azure-->>Client: Return JWT access token + + Note over Client,Phase: 2. Authenticate + Client->>Phase: POST JWT to /identities/external/v1/azure/entra/auth/ + + Note over Phase,Azure: 3. Validate JWT + Phase->>Azure: Fetch JWKS public keys (cached) + Azure-->>Phase: Return signing keys + + Note over Phase: 4. Verify signature, audience, tenant, and allowed service principal ID + Phase->>Client: Return Access Token with a specified TTL + + Note over Client,Phase: 5. Authenticate to API with Access Token + Client->>Phase: Make authenticated requests using the Access Token +`} + + ## Manage External Identities @@ -126,32 +182,25 @@ From the dialog, select the External Identity you want to bind to this Service A ## Authenticate with External Identities -Once you have configured an External Identity and bound it to a Service Account, you can authenticate using the Phase CLI with your AWS credentials. +Once you have configured an External Identity and bound it to a Service Account, you can authenticate using the Phase CLI or the API. ### CLI Authentication -To authenticate using an External Identity, use the `phase auth` command with the `--mode aws-iam` option: +To authenticate using an External Identity, use the `phase auth` command with the appropriate `--mode` option: ```fish -# Authenticate using your current AWS identity +# AWS IAM phase auth --mode aws-iam --service-account-id 0f1a2b3c-4d5e-6789-abcd-ef0123456789 -``` - -You can also specify additional options: -```fish -# Authenticate with a custom TTL and print token to STDOUT -phase auth --mode aws-iam --service-account-id 0f1a2b3c-4d5e-6789-abcd-ef0123456789 --ttl 3600 --no-store +# Azure (Managed Identity, Service Principal, or az login) +phase auth --mode azure --service-account-id 0f1a2b3c-4d5e-6789-abcd-ef0123456789 ``` **Options:** - `--service-account-id` (Required): The ID of the Service Account that has the External Identity bound to it - `--ttl` (Optional): Token TTL in seconds. Defaults to the configured Default TTL of the external identity - `--no-store` (Optional): Print the access token & metadata to STDOUT without logging in - - -The CLI will auto detect the AWS region you are in and use it to authenticate with the AWS API. You can also use `aws configure` to set the region. - +- `--azure-resource` (Optional, Azure only): Azure AD resource/audience for the token request. Default: `https://management.azure.com/` ### API Authentication diff --git a/public/access-control/provisioning/scim.md b/public/access-control/provisioning/scim.md new file mode 100644 index 00000000..7630dc81 --- /dev/null +++ b/public/access-control/provisioning/scim.md @@ -0,0 +1,358 @@ +import { Tag } from '@/components/Tag' +import { DocActions } from '@/components/DocActions' + +export const description = 'Set up SCIM v2 provisioning to automatically sync users and groups from your identity provider to Phase.' + +PROVISIONING + +# SCIM Provisioning + +SCIM (System for Cross-domain Identity Management) v2 enables automatic user and group provisioning from your identity provider (IdP) to Phase. When configured, your IdP can automatically create, update, and deactivate user accounts in Phase, eliminating the need for manual user management. + + + + + SCIM provisioning is available for organisations with an `Enterprise` tier subscription. See [Pricing](https://phase.dev/pricing). + + +## How it works + +When SCIM is enabled, your identity provider communicates with Phase's SCIM v2 API to: + +- **Provision users**: Automatically create Phase accounts when users are assigned to the application in your IdP. Users are created with a `Pending` status until they complete their first login and account setup. +- **Deprovision users**: Automatically deactivate Phase accounts when users are unassigned or disabled in your IdP. The user's environment keys are revoked and their org membership is soft-deleted. +- **Sync groups**: Map IdP groups to Phase Teams, automatically managing team membership as group assignments change. +- **Update user attributes**: Keep user details (name, email) in sync between your IdP and Phase. + +### User lifecycle + +1. **IdP assigns user** → SCIM creates a Phase user account with `Pending` status (SCIM + Pending badges shown in the console) +2. **User logs in via SSO** → Phase auto-links the SSO account to the SCIM-provisioned user +3. **User completes account setup** → User sets up their sudo password and recovery phrase, enabling them to decrypt secrets +4. **IdP unassigns user** → SCIM deactivates the user, revokes environment keys, and removes them from the organisation + +## Enable SCIM in Phase + +Before configuring your identity provider, enable SCIM in the Phase Console and create a provisioning token: + +1. Log into the Phase Console as an **Owner** or **Admin**. + +2. Navigate to **Access** > **SCIM** in the sidebar. + +3. Toggle **Enable SCIM** to on. + +4. Copy the **SCIM Base URL** shown on the page. It will look like: + + ``` + https://[YOUR_PHASE_HOST]/service/scim/v2/ + ``` + +5. Click **Create token** to generate a SCIM bearer token. Give it a descriptive name (e.g., "Azure Entra ID") and select an expiry period. + +6. Copy the generated token immediately — it will not be shown again. This token will be used as the **Secret Token** in your identity provider's SCIM configuration. + + + Treat the SCIM token like a password. Anyone with this token can provision and deprovision users in your Phase organisation. + + +## Microsoft Entra ID (Azure AD) + +Microsoft Entra ID supports SCIM-based provisioning through Enterprise Applications. Follow these steps to configure automatic user and group provisioning from Entra ID to Phase. + +### Prerequisites + +- A Microsoft Entra ID tenant with a P1 or P2 license (required for enterprise app provisioning) +- An existing Phase Enterprise organisation with SCIM enabled and a SCIM token (see above) +- OIDC SSO configured for Microsoft Entra ID (see [Entra ID OIDC setup](/access-control/authentication/oidc-sso#microsoft-entra-id--azure-ad)) + + + SCIM provisioning and OIDC SSO are complementary features. SCIM handles account lifecycle (creation, deactivation), while OIDC handles authentication (login). You should configure both for the best experience. + + +### Step 1: Create an Enterprise Application + +1. Sign in to the [Azure Portal](https://portal.azure.com). + +2. Navigate to **Microsoft Entra ID** > **Enterprise applications**. + +3. Click **+ New application** at the top. + +4. Click **+ Create your own application**. + +5. Enter a name for the application (e.g., "Phase Console SCIM"), select **Integrate any other application you find in the gallery (Non-gallery)**, and click **Create**. + +### Step 2: Configure Provisioning + +1. In your newly created Enterprise Application, select **Provisioning** from the left sidebar under *Manage*. + +2. Click **Get started** or set the **Provisioning Mode** to **Automatic**. + +3. Under **Admin Credentials**, enter: + - **Tenant URL**: The SCIM Base URL from Phase (e.g., `https://[YOUR_PHASE_HOST]/service/scim/v2/`) + - **Secret Token**: The SCIM token you generated in Phase + +4. Click **Test Connection** to verify connectivity. Azure should report "The supplied credentials are authorized to enable provisioning". + +5. Click **Save**. + +### Step 3: Configure Attribute Mappings + +After saving credentials, Azure will show the **Mappings** section. You need to configure both user and group mappings. + +#### User Attribute Mappings + +1. Click **Provision Microsoft Entra ID Users**. + +2. Ensure the following mappings are present (these are the minimum required by Phase's SCIM implementation): + + | Microsoft Entra ID Attribute | customappsso Attribute | Mapping Type | + |------|-------|------| + | `userPrincipalName` | `userName` | Direct | + | `Switch([IsSoftDeleted], , "False", "True", "True", "False")` | `active` | Expression | + | `mail` | `emails[type eq "work"].value` | Direct | + | `displayName` | `displayName` | Direct | + | `givenName` | `name.givenName` | Direct | + | `surname` | `name.familyName` | Direct | + + + The `mail` → `emails[type eq "work"].value` mapping is important. Phase uses this email to link the SCIM-provisioned account with the SSO login. If your users don't have the `mail` attribute populated in Entra ID, you can map `userPrincipalName` to `emails[type eq "work"].value` instead. + + +3. Click **Save**. + +#### Group Attribute Mappings + +1. Go back to the Provisioning page and click **Provision Microsoft Entra ID Groups**. + +2. Ensure the following mappings are present: + + | Microsoft Entra ID Attribute | customappsso Attribute | Mapping Type | + |------|-------|------| + | `displayName` | `displayName` | Direct | + | `objectId` | `externalId` | Direct | + | `members` | `members` | Direct | + +3. Click **Save**. + +### Step 4: Assign Users and Groups + +1. Navigate to **Users and groups** in the left sidebar of your Enterprise Application. + +2. Click **+ Add user/group**. + +3. Select the users and/or groups you want to provision to Phase, then click **Assign**. + + + Only users and groups explicitly assigned to the Enterprise Application will be provisioned. The default scope setting is "Sync only assigned users and groups". + + +### Step 5: Start Provisioning + +1. Go back to the **Provisioning** page. + +2. Click **Start provisioning** to begin the initial sync. + +3. The initial provisioning cycle may take a few minutes. You can monitor progress under **Provisioning logs** in Azure, or in the **SCIM > Provisioning Logs** section of the Phase Console. + +4. Once complete, provisioned users will appear on the Phase **Members** page with `SCIM` and `Pending` badges. Groups will appear as **Teams** in Phase. + +### Step 6: Test the Flow + +1. Verify that provisioned users appear in the Phase Console under **Access** > **Members** with the SCIM and Pending badges. + +2. Have a provisioned user log in via SSO (Entra ID OIDC). They will be redirected to the **account setup** page to set up their sudo password and recovery phrase. + +3. After completing account setup, the user should be able to access secrets in any environments their team has access to. + +### Troubleshooting: Microsoft Entra ID + +#### Provisioning shows "quarantine" status + +This usually means Azure received multiple errors from the SCIM endpoint. When quarantined, Azure exponentially backs off the retry interval (up to several hours between attempts). Check: +- The SCIM token hasn't expired (check the Phase Console SCIM page) +- The Phase instance is accessible from Azure's IP ranges +- Review the provisioning logs in both Azure and the Phase Console for specific error messages + +To clear a quarantine and resume normal provisioning: + +1. In the Azure Portal, go to your Enterprise Application > **Provisioning**. +2. Click **Stop provisioning** and wait for it to confirm. +3. Click **Start provisioning** — this clears the quarantine state and triggers a fresh initial sync. +4. Verify the **Provisioning Status** toggle is set to **On**, then click **Save**. + + + "Restart provisioning" clears the quarantine but does not always re-enable the provisioning toggle. Always verify the toggle is **On** and click **Save** after restarting. + + +#### User can't log in after SCIM provisioning + +Ensure that: +1. OIDC SSO is configured for Entra ID (SCIM handles provisioning, OIDC handles login) +2. The user's email in Entra ID matches between the SCIM provisioning and the OIDC token claims +3. The user is assigned to both the SCIM Enterprise Application and the OIDC App Registration (or the OIDC app allows all directory users) + +#### Re-provisioning a previously deactivated user + +If you remove a user from the application and then re-add them, Azure may skip provisioning with a `RedundantSoftDelete` error. To resolve this: + +1. Stop provisioning in the Enterprise Application +2. Ensure the user is assigned under **Users and groups** +3. Go to **Provisioning** > click **Restart provisioning** (this clears Azure's internal cycle state) +4. If the issue persists, use **Provision on demand** for the specific user after restarting provisioning + +#### Groups not syncing as Teams + +Ensure that: +- Group provisioning is enabled in the attribute mappings +- The groups are assigned to the Enterprise Application +- The `displayName` and `members` attributes are mapped correctly + +## Okta + +Okta supports SCIM-based provisioning through its application integration platform. Follow these steps to configure automatic user and group provisioning from Okta to Phase. + +### Prerequisites + +- An Okta organisation with the ability to create custom SCIM integrations +- An existing Phase Enterprise organisation with SCIM enabled and a SCIM token (see [Enable SCIM in Phase](#enable-scim-in-phase)) +- OIDC SSO configured for Okta (see [Okta OIDC setup](/access-control/authentication/oidc-sso#okta)) + + + SCIM provisioning and OIDC SSO are complementary features. SCIM handles account lifecycle (creation, deactivation), while OIDC handles authentication (login). You should configure both for the best experience. + + +### Step 1: Create a SCIM Application in Okta + +If you already have an Okta OIDC app for Phase SSO, you can add SCIM provisioning to it. Otherwise, create a new app: + +1. Sign in to the [Okta Admin Console](https://admin.okta.com). + +2. Navigate to **Applications** > **Applications**. + +3. If adding SCIM to an existing app, click on your Phase OIDC app and skip to Step 2. Otherwise, click **Create App Integration**. + +4. Select **SWA - Secure Web Authentication** (this creates a bookmark app that supports SCIM provisioning), and click **Next**. + +5. Enter a name (e.g., "Phase Console") and the login URL for your Phase instance. Click **Finish**. + + + If you already have a separate OIDC app for SSO, you can use a SWA app purely for SCIM provisioning. Users will still authenticate via the OIDC app — the SWA app only handles user/group lifecycle. + + +### Step 2: Enable SCIM Provisioning + +1. In your application, go to the **General** tab. + +2. Click **Edit** on the App Settings panel. + +3. Under **Provisioning**, select **SCIM** and click **Save**. + +4. A new **Provisioning** tab will appear. Click on it. + +5. Under **SCIM Connection**, click **Edit** and enter: + - **SCIM connector base URL**: The SCIM Base URL from Phase (e.g., `https://[YOUR_PHASE_HOST]/service/scim/v2`) + - **Unique identifier field for users**: `userName` + - **Supported provisioning actions**: Check **Push New Users**, **Push Profile Updates**, and **Push Groups** + - **Authentication Mode**: `HTTP Header` + - **Authorization**: Paste the SCIM bearer token you generated in Phase (the token value only, without the `Bearer` prefix) + +6. Click **Test Connector Configuration** to verify connectivity. Okta should report success for the enabled actions. + +7. Click **Save**. + +### Step 3: Configure Provisioning Actions + +1. Still on the **Provisioning** tab, click **To App** in the left panel. + +2. Click **Edit** and enable: + - **Create Users** — Allows Okta to provision new users in Phase + - **Update User Attributes** — Keeps user details in sync + - **Deactivate Users** — Deactivates Phase accounts when users are unassigned in Okta + +3. Click **Save**. + +### Step 4: Verify Attribute Mappings + +1. Still under **Provisioning** > **To App**, scroll down to the **Attribute Mappings** section. + +2. Okta pre-populates a comprehensive set of default attribute mappings. No changes are required — the defaults already include everything Phase needs. Verify that the following key mappings are present: + + | Okta Attribute | App Attribute | Default Value | + |------|-------|------| + | `userName` | `userName` | Configured in Sign On settings | + | `givenName` | `name.givenName` | `user.firstName` | + | `familyName` | `name.familyName` | `user.lastName` | + | `email` | `emails[type eq "work"].value` | `user.email` | + | `displayName` | `displayName` | `user.displayName` | + + + Okta sends many additional attributes by default (phone, address, title, etc.). Phase safely ignores any attributes it doesn't need — you can leave them as-is or remove them if you prefer a minimal mapping. + + + + Okta uses `userName` (typically the user's email address) as the primary identifier. Ensure that the `userName` in Okta matches the email address used for SSO login, so Phase can link the SCIM-provisioned account with the OIDC identity. + + +### Step 5: Assign Users and Groups + +1. Go to the **Assignments** tab in your application. + +2. Click **Assign** and select either **Assign to People** or **Assign to Groups**. + +3. Select the users and/or groups you want to provision to Phase, then click **Assign** and **Save and Go Back**. + +4. If you assigned groups, go to the **Push Groups** tab: + - Click **Push Groups** > **Find groups by name** (or by rule) + - Select the groups you want to push to Phase + - Click **Save** + + + In Okta, assigning a group under **Assignments** grants group members access to the app (user provisioning). The **Push Groups** tab controls whether the group itself is synced to Phase as a Team. You typically need both: assign the group for user provisioning, and push the group for team creation. + + +### Step 6: Verify Provisioning + +1. Navigate to **Dashboard** > **Tasks** in the Okta Admin Console to monitor provisioning progress. + +2. Check the Phase Console under **Access** > **Members** — provisioned users should appear with `SCIM` and `Pending` badges. + +3. Check **Access** > **Teams** — pushed groups should appear as teams with a `SCIM` badge. + +4. Have a provisioned user log in via Okta SSO. They will be redirected to the account setup page to set up their sudo password and recovery phrase. + +### Troubleshooting: Okta + +#### "Error authenticating" when testing the connector + +- Verify the SCIM base URL ends with `/scim/v2` (no trailing slash) +- Verify the token is entered without the `Bearer` prefix — Okta adds it automatically +- Ensure the SCIM token hasn't expired in the Phase Console + +#### Users not being provisioned + +- Check that **Create Users** is enabled under **Provisioning** > **To App** +- Verify users are assigned to the application under the **Assignments** tab +- Check the **Tasks** page in Okta for specific error messages +- Review the SCIM provisioning logs in the Phase Console for request/response details + +#### Groups not syncing as Teams + +- Ensure the group is both **assigned** to the app (Assignments tab) and **pushed** (Push Groups tab) +- Check that the group push status shows "Active" — if it shows an error, click on it for details +- Verify that group push is enabled in the SCIM connector settings (**Push Groups** checkbox) + +#### User deprovisioned after removing direct assignment, despite being in a pushed group + +In Okta, **Push Groups** and **Assignments** are independent: +- **Assignments** controls user provisioning (who gets a Phase account) +- **Push Groups** controls group/team syncing (which groups appear as Phase Teams) + +If a user is only directly assigned (not via a group assignment), removing that direct assignment deprovisions them — even if they belong to a pushed group. Push Groups does not grant app assignment. + +**Fix**: Assign groups under the **Assignments** tab (not just Push Groups). This way, group membership is the single source of truth for both user provisioning and team sync. When a user is removed from the group in Okta, they are automatically deprovisioned and removed from the team. + +#### User can't log in after SCIM provisioning + +- Ensure OIDC SSO is configured for Okta (SCIM handles provisioning, OIDC handles login) +- The user's email in Okta must match between the SCIM `userName` and the OIDC token `email` claim +- If using separate apps for SCIM and OIDC, the user must be assigned to both diff --git a/public/access-control/roles.md b/public/access-control/roles.md index 04054392..8bf6f4fb 100644 --- a/public/access-control/roles.md +++ b/public/access-control/roles.md @@ -44,6 +44,8 @@ The organization owner. This role is automatically assigned when a user creates | **Roles** | Full access | ✅ | ✅ | ✅ | ✅ | | **Integration Credentials** | Full access | ✅ | ✅ | ✅ | ✅ | | **Network Access Policies** | Full access | ✅ | ✅ | ✅ | ✅ | +| **Teams** | Full access | ✅ | ✅ | ✅ | ✅ | +| **SCIM** | Full access | ✅ | ✅ | ✅ | ✅ | #### App-level permissions: @@ -59,6 +61,7 @@ The organization owner. This role is automatically assigned when a user creates | **Service Accounts** | Full access | ✅ | ✅ | ✅ | ✅ | | **Integrations** | Full access | ✅ | ✅ | ✅ | ✅ | | **Encryption Mode** | Full access | ✅ | | ✅ | | +| **Teams** | Full access | ✅ | ✅ | ✅ | ✅ | ### Admin @@ -79,6 +82,8 @@ Admin users have access to most resources and permissions, and have global acces | **Roles** | Full access | ✅ | ✅ | ✅ | ✅ | | **Integration Credentials** | Full access | ✅ | ✅ | ✅ | ✅ | | **Network Access Policies** | Full access | ✅ | ✅ | ✅ | ✅ | +| **Teams** | Full access | ✅ | ✅ | ✅ | ✅ | +| **SCIM** | Full access | ✅ | ✅ | ✅ | ✅ | #### App-level permissions: @@ -94,6 +99,7 @@ Admin users have access to most resources and permissions, and have global acces | **Service Accounts** | Full access | ✅ | ✅ | ✅ | ✅ | | **Integrations** | Full access | ✅ | ✅ | ✅ | ✅ | | **Encryption Mode** | Custom access | ✅ | | ✅ | | +| **Teams** | Full access | ✅ | ✅ | ✅ | ✅ | The `Owner` and `Admin` roles have global access. Learn more about global access [here](/access-control#global-access). @@ -116,6 +122,8 @@ Management users with broad access to environments, secrets, and service account | **Roles** | Full access | ✅ | ✅ | ✅ | ✅ | | **Integration Credentials** | Full access | ✅ | ✅ | ✅ | ✅ | | **Network Access Policies** | Full access | ✅ | ✅ | ✅ | ✅ | +| **Teams** | Full access | ✅ | ✅ | ✅ | ✅ | +| **SCIM** | No access | ❌ | ❌ | ❌ | ❌ | #### App-level permissions: @@ -131,6 +139,7 @@ Management users with broad access to environments, secrets, and service account | **Service Accounts** | Full access | ✅ | ✅ | ✅ | ✅ | | **Integrations** | Full access | ✅ | ✅ | ✅ | ✅ | | **Encryption Mode** | Custom access | ✅ | ❌ | ✅ | ❌ | +| **Teams** | Full access | ✅ | ✅ | ✅ | ✅ | ### Service @@ -151,6 +160,8 @@ Default role for Service Accounts, providing programmatic access to secrets with | **Roles** | Read access | ✅ | ❌ | ❌ | ❌ | | **Integration Credentials** | Read access | ✅ | ❌ | ❌ | ❌ | | **Network Access Policies** | Read access | ✅ | ❌ | ❌ | ❌ | +| **Teams** | No access | ❌ | ❌ | ❌ | ❌ | +| **SCIM** | No access | ❌ | ❌ | ❌ | ❌ | #### App-level permissions: @@ -166,6 +177,7 @@ Default role for Service Accounts, providing programmatic access to secrets with | **Service Accounts** | Read access | ✅ | ❌ | ❌ | ❌ | | **Integrations** | Read access | ✅ | ❌ | ❌ | ❌ | | **Encryption Mode** | Read access | ✅ | ❌ | ❌ | ❌ | +| **Teams** | Read access | ✅ | ❌ | ❌ | ❌ | ### Developer @@ -186,6 +198,8 @@ Developers have limited permissions at the organization level and must be given | **Roles** | Read access | ✅ | ❌ | ❌ | ❌ | | **Integration Credentials** | Custom access | ✅ | ✅ | ✅ | ❌ | | **Network Access Policies** | Read access | ✅ | ❌ | ❌ | ❌ | +| **Teams** | Read access | ✅ | ❌ | ❌ | ❌ | +| **SCIM** | No access | ❌ | ❌ | ❌ | ❌ | #### App-level permissions: @@ -198,9 +212,10 @@ Developers have limited permissions at the organization level and must be given | **Logs** | Read access | ✅ | ❌ | ❌ | ❌ | | **Tokens (Legacy)** | Custom access | ✅ | ✅ | ❌ | ❌ | | **Members** | Read access | ✅ | ❌ | ❌ | ❌ | -| **Service Accounts** | Read access | ✅ | ❌ | ❌ | ❌ | +| **Service Accounts** | Custom access | ❌ | ✅ | ❌ | ❌ | | **Integrations** | Full access | ✅ | ✅ | ✅ | ✅ | | **Encryption Mode** | Custom access | ✅ | | ✅ | | +| **Teams** | Read access | ✅ | ❌ | ❌ | ❌ | ## Custom Roles @@ -260,6 +275,12 @@ Some actions require a combination of permissions across multiple resources. Bel - To view and delete other users Personal Access Tokens: - `MemberPersonalAccessTokens:read` - `MemberPersonalAccessTokens:delete` +- Adding or removing a Team's access to an App: + - `Teams:create` or `Teams:delete` (app-level) + - `Teams:read` (organisation-level) +- Managing a Team's environment scope within an App: + - `Teams:update` (app-level) + - `Teams:read` (organisation-level) - To Manage Network Access Policies of a User or Service Account: - `Members:read` - `Members:update` diff --git a/public/access-control/service-accounts.md b/public/access-control/service-accounts.md index cc41d414..662eb233 100644 --- a/public/access-control/service-accounts.md +++ b/public/access-control/service-accounts.md @@ -9,7 +9,16 @@ Service Accounts provide a secure and controlled method for programmatic access Service accounts share many of the properties and behavior of human user accounts. Service Accounts follow an Access Policy that can be defined by [Managed Roles](/access-control/roles#managed-roles) or [Custom Roles](/access-control/roles#creating-custom-roles) based on the permissions required. Service accounts are secured with the same security and cryptographic architecture as user accounts, and must be manually provisioned access to Apps and Environments in order to access secrets. - + + +## Org-level vs Team-owned Service Accounts + +Service accounts exist in two categories: + +- **Org-level** (default): Visible to all organisation members with `ServiceAccounts.read` permission. Created from the organisation-level Service Accounts page. This is the default behavior and works on all plans. +- **Team-owned**: Created within a [Team](/access-control/teams), visible only to team members and users with global access (Owner/Admin). The service account's lifecycle is tied to the team — if the team is deleted, team-owned SAs are deleted too. + +Team-owned service accounts are useful when a team needs dedicated programmatic access for team resources, that is isolated from other teams and users. See [Team-owned service accounts](/access-control/teams#team-owned-service-accounts) for details on creating and managing them. ## Create a new Service Account diff --git a/public/access-control/teams.md b/public/access-control/teams.md new file mode 100644 index 00000000..3fa8f665 --- /dev/null +++ b/public/access-control/teams.md @@ -0,0 +1,197 @@ +import { Tag } from '@/components/Tag' +import { DocActions } from '@/components/DocActions' + +export const description = 'Organize members and service accounts into Teams with scoped app access and optional role overrides.' + +ACCESS CONTROL + +# Teams + +Teams let you group members and service accounts together and grant them access to specific apps and environments. Instead of managing access for each individual, you assign access at the team level — when someone joins the team, they automatically get the right keys. + + + + + Teams require apps with [Server-Side Encryption (SSE)](/console/apps#encryption-mode) enabled, since the server provisions encryption keys on behalf of team members. + + +## How it works + +A Team is an organisation-level group that contains **members** (human users) and/or **service accounts**. Teams are granted access to one or more apps, scoped to specific environments within each app. + +When a team is added to an app: + +1. You select which environments the team should have access to (e.g. `Development`, `Staging`) +2. Phase's server automatically wraps `EnvironmentKey`s for every team member using the app's `ServerEnvironmentKey` +3. Team members can immediately decrypt secrets in those environments + +When a member is added to a team that already has app access, keys are provisioned automatically. When a member is removed, their team-granted keys are revoked — unless they also have individual access to the same environment. + +### Key concepts + +| Concept | Description | +|---------|-------------| +| **Team membership** | A user or service account belongs to one or more teams | +| **Team app access** | A team is granted access to an app, scoped to specific environments | +| **Role overrides** | Teams can optionally override the org role's app-level permissions for their members | +| **Union semantics** | If a user is in multiple teams with access to the same app, they get the **union** of all team role permissions | +| **Individual priority** | Individual (direct) app access always uses the org role, not team roles | +| **Grant tracking** | Phase tracks *why* each `EnvironmentKey` exists (individual vs team grant) so that removing team access doesn't accidentally revoke individually-granted keys | + +## Creating a Team + +1. Navigate to **Access** > **Teams** in the sidebar. + +2. Click **Create Team**. + +3. Enter a **name** and optional **description** for the team. + +4. Optionally set **role overrides** (see [Role overrides](#role-overrides) below). If you skip this, team members will use their org role for app-level permissions. + +5. Click **Create**. The team is created with no members or app access — you'll add those next. + +## Managing team members + +### Adding members + +1. Open the team detail page by clicking on the team name. + +2. Click **Add members** or **Add service accounts**. + +3. Select the members or service accounts you want to add from the list. Only org members who aren't already in the team are shown. + +4. Click **Add**. If the team already has app access, encryption keys are provisioned immediately for the new members. + +### Removing members + +1. On the team detail page, find the member you want to remove. + +2. Click the remove button next to their name. + +3. Confirm the removal. Phase will revoke the member's team-granted environment keys. If the member also has individual access to the same environments, those keys are preserved. + +## Managing team app access + +### Adding apps to a team + +1. On the team detail page, click **Add apps**. + +2. Select the app you want to add. Only SSE-enabled apps are shown — if an app doesn't appear, enable SSE on it first. + +3. Select which **environments** within the app the team should have access to. + +4. Click **Add**. Phase provisions environment keys for all team members with an active `identity_key`. Members who haven't completed their key ceremony yet (e.g. SCIM-provisioned users who haven't logged in) will receive keys on their first login. + +### Updating environment access + +After a team has been added to an app, you can change which environments it has access to: + +1. Click **Manage** next to the app on the team detail page. + +2. Toggle environments on or off. + +3. Save. Keys are provisioned for newly added environments and revoked for removed environments. + +### Removing an app from a team + +1. Click the remove button next to the app on the team detail page. + +2. Confirm the removal. All team-granted environment keys for that app are revoked for every team member. + +## Role overrides + +By default, team members use their **org role's app-level permissions** when accessing team-granted apps. For example, a `Developer` in a team uses the Developer role's app permissions (can read/write secrets, but can't delete environments). + +Teams support two optional role overrides that change what permissions members have when accessing apps through that team: + +| Override | Applies to | Description | +|----------|-----------|-------------| +| **Member role** | Human users | Overrides the org role's app-level permissions for all human members of this team | +| **Service account role** | Service accounts | Overrides the org role's app-level permissions for all service accounts in this team | + +When a role override is set, it replaces the org role's `app_permissions` for resources accessed through that team. Org-level permissions are unaffected. + +### Union semantics + +If a user belongs to multiple teams that all have access to the same app, Phase takes the **union** of permissions across all applicable team roles. If *any* team role grants a permission, the user has that permission. + +**Example:** Alice is in Team A (role: `Developer`) and Team B (role: `Manager`). Both teams have access to App X. Alice gets the union of Developer and Manager app-level permissions for App X. + +### Individual access takes priority + +If a user has both **individual** (direct) access and **team** access to the same app, the individual access path is used. This means the user's org role determines app-level permissions, regardless of any team role overrides. + +## SSE requirement + +Teams require [Server-Side Encryption (SSE)](/console/apps#encryption-mode) to be enabled on any app they access. This is because the server needs to provision encryption keys on behalf of team members — it unwraps the `ServerEnvironmentKey` and re-wraps the environment seed/salt for each member's public key. + +If an app has SSE disabled, it won't appear in the app selection dialog when adding apps to a team. You can enable SSE on an app from the app's settings page under **Encryption Mode**. + + + Enabling SSE changes the encryption model for the app — the server gains the ability to decrypt secrets. This is required for Teams, all third-party sync integrations, and REST API access. See [Encryption Mode](/console/apps#encryption-mode) for details. + + +## Team-owned service accounts + +Service accounts can be **owned by a team**, meaning their lifecycle and visibility are tied to that team. This is useful when a team needs dedicated service accounts for programmatic access that only team members can see and manage. + +### Creating a team-owned service account + +1. On the team detail page, click **Create Team Service Account** in the Service Accounts section. + +2. Enter a name for the account. + +3. If the team has a defined Service Account role, the role for this account will be fixed. If there is no defined role for service accounts in the team, select a role for this account. + +4. Click **Create**. The The service account is automatically added as a member of the team and can access all apps and environments that the team is added to. + +Team-owned service accounts are visually distinguished with a team badge on both the team detail page and the organisation-level service accounts list. + +### Visibility rules + +| SA type | Who can see it | Who can manage it | +|---------|---------------|-------------------| +| **Org-level** (no team) | Anyone with `ServiceAccounts.read` | Anyone with `ServiceAccounts.update/delete` | +| **Team-owned** | Team members + Owner/Admin | Team members + Owner/Admin | + +Users who are not members of the owning team will not see team-owned service accounts in the organisation-level service accounts list — unless they have global access (Owner/Admin). + +### Ownership transfer + +Owner and Admin users can transfer a service account between org-level and team ownership: + +- **Team → Org-level**: Clears the team association. The service account becomes visible org-wide. Existing tokens and app access are preserved. +- **Org-level → Team**: Assigns the service account to a team. Visibility narrows to team members and global access users. + +### Team deletion + +When a team is deleted, all team-owned service accounts are soft-deleted and their tokens are revoked. Org-level service accounts that were added to the team as members are unaffected — they lose team-based app access but remain visible org-wide. + +### Removing a team-owned SA from its team + +A team-owned service account cannot be removed from its owning team. To dissociate it from the team, either delete the service account or transfer its ownership to the organisation (Owner/Admin only). + +## SCIM-managed teams + +When [SCIM provisioning](/access-control/provisioning/scim) is configured, your identity provider can create and manage teams automatically by syncing IdP groups to Phase teams. SCIM-managed teams have the following restrictions: + +- Cannot be renamed, deleted, or have members manually added/removed from the Phase Console +- Membership changes must be made in the identity provider +- A `SCIM` badge is shown next to the team name in the console +- Role overrides and app access can still be managed from Phase + +## Grant tracking + +Phase tracks the **reason** each `EnvironmentKey` exists using `EnvironmentKeyGrant` records. Each grant is tagged as either `individual` (direct app access) or `team` (via team membership), with a reference to the specific team. + +This prevents a common pitfall: if a user has both individual and team access to the same environment, removing the team access should *not* revoke the key. Phase only soft-deletes an `EnvironmentKey` when all of its grants have been removed. + +## Viewing team access on member and app pages + +### Member detail page + +Each member's detail page (under **Access** > **Members** > member name) shows a **Teams** section listing all teams the member belongs to, along with links to each team's detail page. + +### App access page + +Each app's **Access** > **Teams** tab shows all teams that have access to the app, the environments they can access, and their role overrides. You can add/remove teams and manage environment scoping directly from this page. diff --git a/public/cli/commands.md b/public/cli/commands.md index 4e00ce41..7b9c212f 100644 --- a/public/cli/commands.md +++ b/public/cli/commands.md @@ -121,7 +121,7 @@ For `token` mode, provide the following: Obtain a Personal Access Token (PAT) from the [Phase Console](https://console.phase.dev) by going to Access Control -> Authentication -> Personal Access Tokens -> + `Create Token`. -3. **AWS IAM**: Authenticate using your current AWS identity from the standard AWS credential chain (env vars, shared config/credentials, SSO, role assumption, instance profile, etc). Optionally bind the external identity to a Phase Service Account and set a TTL for the issued token. You'll need to have configured an external identity to a service account in the Phase Console first. +3. **AWS IAM**: Authenticate using your current AWS identity from the standard AWS credential chain (env vars, shared config/credentials, SSO, role assumption, instance profile, etc). Optionally bind the external identity to a Phase Service Account and set a TTL for the issued token. You'll need to have configured an external identity to a service account in the Phase Console first. See [External Identities](/access-control/external-identities) for more details. @@ -158,15 +158,51 @@ phase auth --mode aws-iam --service-account=2115a1fc-0a78-4a7b-ad8c-6fa6cc15f489 } ``` -- `mode`: Choose the mode of authentication (`token`, `webauth`, `aws-iam`). Default: `webauth` -- `service-account-id` (Required for external identities): Bind external identity to a Phase Service Account. -- `ttl` (Optional): Only applicable for when using external identities for authentication (e.g., `aws-iam` mode). TTL in seconds for the issued token. -- `no-store` (Optional): Only applicable for when using external identities for authentication (e.g., `aws-iam` mode). Print the authentication token response to STDOUT without storing credentials. - The CLI will auto detect the AWS region you are in and use it to authenticate with the AWS API. You can also use `aws configure` to set the region. +4. **Azure**: Authenticate using your current Azure identity via `DefaultAzureCredential` (Managed Identity, Service Principal, Workload Identity, Azure CLI, etc). You'll need to have configured an Azure external identity on a service account in the Phase Console first. + +See [External Identities](/access-control/external-identities#azure) for more details. + +Usage: + +```fish +> phase auth --mode azure [--service-account-id SERVICE_ACCOUNT_ID] [--azure-resource RESOURCE] [--ttl SECONDS] [--no-store] +``` + +Options: + +- `--service-account-id` (Required): Service Account ID to map this external Azure identity to a Phase Service Account. +- `--azure-resource` (Optional): Azure AD resource/audience for the token request. Must match the "Resource / Audience" configured on the Phase identity. Default: `https://management.azure.com/`. +- `--ttl` (Optional): Token TTL in seconds. Defaults to the configured Default TTL of the external identity. +- `--no-store` (Optional): Print the authentication token to STDOUT without storing credentials in the keyring. + +Examples: + +```fish +# Log in using your current Azure identity and persist credentials +> phase auth --mode azure --service-account-id 0f1a2b3c-4d5e-6789-abcd-ef0123456789 +``` + +```fish +# Authenticate with a custom resource and print token to STDOUT +> phase auth --mode azure --service-account-id 0f1a2b3c-4d5e-6789-abcd-ef0123456789 --azure-resource "https://management.azure.com/" --ttl 3600 --no-store +``` + + +`DefaultAzureCredential` automatically tries (in order): environment variables (`AZURE_TENANT_ID`, `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`), Workload Identity (Kubernetes), Managed Identity (IMDS), Azure CLI (`az login`), and Azure Developer CLI (`azd login`). + + +#### Auth Options Summary + +- `mode`: Choose the mode of authentication (`token`, `webauth`, `aws-iam`, `azure`). Default: `webauth` +- `service-account-id` (Required for external identities): Bind external identity to a Phase Service Account. +- `ttl` (Optional): Only applicable when using external identities for authentication. TTL in seconds for the issued token. +- `no-store` (Optional): Only applicable when using external identities for authentication. Print the authentication token response to STDOUT without storing credentials. +- `azure-resource` (Optional, Azure only): Azure AD resource/audience. Default: `https://management.azure.com/`. + --- ## 🔗 `init` diff --git a/public/llms.txt b/public/llms.txt index fae3df89..08e62e8b 100644 --- a/public/llms.txt +++ b/public/llms.txt @@ -27,6 +27,8 @@ - [access-control/authentication/oauth-sso](https://docs.phase.dev/access-control/authentication/oauth-sso.md) - [access-control/authentication/oidc-sso](https://docs.phase.dev/access-control/authentication/oidc-sso.md) - [access-control/authentication/tokens](https://docs.phase.dev/access-control/authentication/tokens.md) +- [access-control/provisioning/scim](https://docs.phase.dev/access-control/provisioning/scim.md) +- [access-control/teams](https://docs.phase.dev/access-control/teams.md) - [access-control/service-accounts](https://docs.phase.dev/access-control/service-accounts.md) - [access-control/external-identities](https://docs.phase.dev/access-control/external-identities.md) - [access-control/roles](https://docs.phase.dev/access-control/roles.md) diff --git a/public/public-api/external-identities.md b/public/public-api/external-identities.md index 4e8f0315..eb4fbeac 100644 --- a/public/public-api/external-identities.md +++ b/public/public-api/external-identities.md @@ -4,21 +4,23 @@ import { DocActions } from '@/components/DocActions' export const metadata = { title: 'External Identities API', description: - 'Authenticate with Phase using external identity providers (AWS IAM).', + 'Authenticate with Phase using external identity providers (AWS IAM, Azure).', } API -# External Identities (AWS IAM) +# External Identities -Authenticate to Phase using AWS IAM via a SigV4-signed STS GetCallerIdentity request. This flow returns a Phase authentication token scoped to the specified Service Account, with an optional TTL. {{ className: 'lead' }} +Authenticate to Phase using external identity providers. Each provider returns a Phase authentication token scoped to the specified Service Account, with an optional TTL. {{ className: 'lead' }} - + --- -## Authenticate with AWS IAM {{ tag: 'POST', label: '/identities/external/v1/aws/iam/auth/' }} +## AWS IAM + +### Authenticate with AWS IAM {{ tag: 'POST', label: '/identities/external/v1/aws/iam/auth/' }} @@ -316,4 +318,223 @@ Authenticate to Phase using AWS IAM via a SigV4-signed STS GetCallerIdentity req +--- + +## Azure + +### Authenticate with Azure {{ tag: 'POST', label: '/identities/external/v1/azure/entra/auth/' }} + + + + + Exchange an Azure AD JWT for a Phase token. The JWT is validated statelessly using Azure AD's public OIDC signing keys — no Azure credentials are stored on the Phase backend. + + ### JSON Body + + Supply the Service Account to authenticate and the base64-encoded Azure AD JWT. + + #### **Required fields** + + + + Service Account ID (UUID) to authenticate. + + + Base64-encoded Azure AD JWT access token. + + + + #### **Optional fields** + + + + Defaults to service. Only service is supported currently. + + + Requested token TTL in seconds. If omitted, the default identity TTL is used. + + + + + The JWT must be obtained from Azure AD with a resource / audience that matches the value configured on the Phase identity (default: https://management.azure.com/). The oid claim in the JWT (the service principal's object ID) must be in the identity's allowed service principal IDs list. + + + + + + + + ```json {{ title: 'JSON body' }} + { + "account": { + "type": "service", + "id": "00000000-0000-0000-0000-000000000000" + }, + "azureEntra": { + "jwt": "" + }, + "tokenRequest": { + "ttl": 3600 + } + } + ``` + + ```js + import { DefaultAzureCredential } from '@azure/identity' + + const HOST = 'https://api.phase.dev' + const SERVICE_ACCOUNT_ID = '00000000-0000-0000-0000-000000000000' + const RESOURCE = 'https://management.azure.com/' + + ;(async () => { + const credential = new DefaultAzureCredential() + const token = await credential.getToken(RESOURCE + '.default') + const encodedJWT = Buffer.from(token.token).toString('base64') + + const payload = { + account: { type: 'service', id: SERVICE_ACCOUNT_ID }, + azureEntra: { jwt: encodedJWT }, + } + + const res = await fetch(`${HOST}/service/public/identities/external/v1/azure/entra/auth/`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }) + if (!res.ok) throw new Error(`HTTP ${res.status}`) + console.log(await res.json()) + })() + ``` + + ```python + import base64, json + import requests + from azure.identity import DefaultAzureCredential + + HOST = "https://api.phase.dev" + SERVICE_ACCOUNT_ID = "00000000-0000-0000-0000-000000000000" + RESOURCE = "https://management.azure.com/" + + credential = DefaultAzureCredential() + token = credential.get_token(RESOURCE + ".default") + encoded_jwt = base64.b64encode(token.token.encode()).decode() + + payload = { + "account": {"type": "service", "id": SERVICE_ACCOUNT_ID}, + "azureEntra": {"jwt": encoded_jwt}, + } + + r = requests.post( + f"{HOST}/service/public/identities/external/v1/azure/entra/auth/", + json=payload, + headers={"Content-Type": "application/json"}, + timeout=30, + ) + r.raise_for_status() + print(r.json()) + ``` + + ```go + package main + + import ( + "bytes" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "net/http" + "os" + "context" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + ) + + func main() { + host := "https://api.phase.dev" + serviceAccount := "00000000-0000-0000-0000-000000000000" + resource := "https://management.azure.com/" + + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { panic(err) } + + token, err := cred.GetToken(context.Background(), policy.TokenRequestOptions{ + Scopes: []string{resource + ".default"}, + }) + if err != nil { panic(err) } + + encodedJWT := base64.StdEncoding.EncodeToString([]byte(token.Token)) + + payload := map[string]any{ + "account": map[string]string{"type": "service", "id": serviceAccount}, + "azureEntra": map[string]string{"jwt": encodedJWT}, + } + + b, _ := json.Marshal(payload) + res, err := http.Post(host+"/service/public/identities/external/v1/azure/entra/auth/", "application/json", bytes.NewReader(b)) + if err != nil { panic(err) } + defer res.Body.Close() + io.Copy(os.Stdout, res.Body) + } + ``` + + ```bash {{ title: 'curl' }} + # Get token via Azure CLI (as logged-in user or service principal) + TOKEN=$(az account get-access-token \ + --resource https://management.azure.com/ \ + --query accessToken -o tsv) + ENCODED=$(echo -n "$TOKEN" | base64) + + curl -X POST https://api.phase.dev/service/public/identities/external/v1/azure/entra/auth/ \ + -H "Content-Type: application/json" \ + -d "{ + \"account\": {\"type\": \"service\", \"id\": \"00000000-0000-0000-0000-000000000000\"}, + \"azureEntra\": {\"jwt\": \"$ENCODED\"}, + \"tokenRequest\": {\"ttl\": 3600} + }" + ``` + + + + ```json {{ title: 'Response' }} + { + "authentication": { + "tokenType": "ServiceAccount", + "token": "pss_service:v2:...", + "bearerToken": "ServiceAccount baca69c634d84e5d3d04d31a487eb1c4c5f2a3ef2a6683f77cf965d3ad7633d3", + "TTL": 3600, + "maxTTL": 86400 + } + } + ``` + + + + +--- + +## Notes on Azure JWT tokens + + + + + Azure AD issues two token versions. The version is determined by the `accessTokenAcceptedVersion` on the **resource** app registration, not the client. + + + + Used for https://management.azure.com/. Issuer: https://sts.windows.net/{'{'}tenantId{'}'}/. Audience: resource URI string. + + + Used for custom app registrations with accessTokenAcceptedVersion: 2. Issuer: https://login.microsoftonline.com/{'{'}tenantId{'}'}/v2.0. Audience: client ID GUID. + + + DefaultAzureCredential tries (in order): environment variables (Service Principal), Workload Identity (Kubernetes), Managed Identity (IMDS), Azure CLI, Azure Developer CLI. + + + + Phase automatically detects the token version and validates accordingly. No configuration is needed. + + + diff --git a/public/sitemap.xml b/public/sitemap.xml index cf1b5058..7a0181be 100644 --- a/public/sitemap.xml +++ b/public/sitemap.xml @@ -1,84 +1,86 @@ -https://docs.phase.dev2026-03-27T06:24:29.025Zdaily0.7 -https://docs.phase.dev/access-control2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/access-control/authentication2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/access-control/authentication/oauth-sso2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/access-control/authentication/oidc-sso2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/access-control/authentication/tokens2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/access-control/external-identities2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/access-control/network2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/access-control/roles2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/access-control/service-accounts2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/cli2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/cli/commands2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/cli/install2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/cli/usage2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/console2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/console/apps2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/console/dynamic-secrets2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/console/environments2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/console/organisation2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/console/secrets2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/console/users2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/agents/claude-code2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/agents/codex2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/agents/cursor2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/agents/opencode2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/agents/vscode-copilot2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/frameworks2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/aws-codebuild2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/aws-elastic-container-service2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/aws-iam2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/aws-secrets-manager2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/azure-key-vault2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/azure-pipelines2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/bitbucket-pipelines2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/buildkite2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/circleci2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/cloudflare-pages2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/cloudflare-workers2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/docker2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/docker-compose2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/drone-ci2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/github-actions2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/github-dependabot2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/gitlab-ci2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/hashicorp-nomad2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/hashicorp-terraform2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/hashicorp-vault2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/jenkins2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/kubernetes2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/railway2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/render2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/teamcity2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/travis-ci2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/integrations/platforms/vercel2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/public-api2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/public-api/dynamic-secrets2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/public-api/errors2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/public-api/external-identities2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/public-api/secrets2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/quickstart2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/sdks2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/sdks/go2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/sdks/js2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/sdks/node2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/sdks/python2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/security2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/security/architecture2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/security/cryptography2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/self-hosting2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/self-hosting/aws2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/self-hosting/aws-eks2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/self-hosting/azure2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/self-hosting/configuration/envars2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/self-hosting/digitalocean2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/self-hosting/docker-compose2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/self-hosting/gcp2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/self-hosting/kubernetes2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/self-hosting/maintenance2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/self-hosting/railway2026-03-27T06:24:29.026Zdaily0.7 -https://docs.phase.dev/self-hosting/raspberrypi2026-03-27T06:24:29.026Zdaily0.7 +https://docs.phase.dev2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/access-control2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/access-control/authentication2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/access-control/authentication/oauth-sso2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/access-control/authentication/oidc-sso2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/access-control/authentication/tokens2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/access-control/external-identities2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/access-control/network2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/access-control/provisioning/scim2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/access-control/roles2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/access-control/service-accounts2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/access-control/teams2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/cli2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/cli/commands2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/cli/install2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/cli/usage2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/console2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/console/apps2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/console/dynamic-secrets2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/console/environments2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/console/organisation2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/console/secrets2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/console/users2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/agents/claude-code2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/agents/codex2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/agents/cursor2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/agents/opencode2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/agents/vscode-copilot2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/frameworks2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/platforms/aws-codebuild2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/platforms/aws-elastic-container-service2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/platforms/aws-iam2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/platforms/aws-secrets-manager2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/platforms/azure-key-vault2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/platforms/azure-pipelines2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/platforms/bitbucket-pipelines2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/platforms/buildkite2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/platforms/circleci2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/platforms/cloudflare-pages2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/platforms/cloudflare-workers2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/platforms/docker2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/platforms/docker-compose2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/platforms/drone-ci2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/platforms/github-actions2026-04-14T14:13:03.319Zdaily0.7 +https://docs.phase.dev/integrations/platforms/github-dependabot2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/integrations/platforms/gitlab-ci2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/integrations/platforms/hashicorp-nomad2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/integrations/platforms/hashicorp-terraform2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/integrations/platforms/hashicorp-vault2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/integrations/platforms/jenkins2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/integrations/platforms/kubernetes2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/integrations/platforms/railway2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/integrations/platforms/render2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/integrations/platforms/teamcity2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/integrations/platforms/travis-ci2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/integrations/platforms/vercel2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/public-api2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/public-api/dynamic-secrets2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/public-api/errors2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/public-api/external-identities2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/public-api/secrets2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/quickstart2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/sdks2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/sdks/go2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/sdks/js2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/sdks/node2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/sdks/python2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/security2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/security/architecture2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/security/cryptography2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/self-hosting2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/self-hosting/aws2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/self-hosting/aws-eks2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/self-hosting/azure2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/self-hosting/configuration/envars2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/self-hosting/digitalocean2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/self-hosting/docker-compose2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/self-hosting/gcp2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/self-hosting/kubernetes2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/self-hosting/maintenance2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/self-hosting/railway2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev/self-hosting/raspberrypi2026-04-14T14:13:03.320Zdaily0.7 \ No newline at end of file From b74217694ecb39af9306fcbbbb9e48ed3ebd8ae5 Mon Sep 17 00:00:00 2001 From: rohan Date: Tue, 14 Apr 2026 20:36:07 +0530 Subject: [PATCH 07/12] feat: add docs for team ownership + miscs updates Signed-off-by: rohan --- public/access-control/teams.md | 53 +++++++-- public/sitemap.xml | 166 ++++++++++++++--------------- src/pages/access-control/teams.mdx | 47 ++++++-- 3 files changed, 164 insertions(+), 102 deletions(-) diff --git a/public/access-control/teams.md b/public/access-control/teams.md index 3fa8f665..0adf2a8c 100644 --- a/public/access-control/teams.md +++ b/public/access-control/teams.md @@ -22,7 +22,7 @@ A Team is an organisation-level group that contains **members** (human users) an When a team is added to an app: 1. You select which environments the team should have access to (e.g. `Development`, `Staging`) -2. Phase's server automatically wraps `EnvironmentKey`s for every team member using the app's `ServerEnvironmentKey` +2. Phase automatically provisions environment encryption keys for every team member 3. Team members can immediately decrypt secrets in those environments When a member is added to a team that already has app access, keys are provisioned automatically. When a member is removed, their team-granted keys are revoked — unless they also have individual access to the same environment. @@ -31,12 +31,13 @@ When a member is added to a team that already has app access, keys are provision | Concept | Description | |---------|-------------| +| **Team ownership** | Each team has an owner who retains full management access regardless of role overrides | | **Team membership** | A user or service account belongs to one or more teams | | **Team app access** | A team is granted access to an app, scoped to specific environments | | **Role overrides** | Teams can optionally override the org role's app-level permissions for their members | | **Union semantics** | If a user is in multiple teams with access to the same app, they get the **union** of all team role permissions | | **Individual priority** | Individual (direct) app access always uses the org role, not team roles | -| **Grant tracking** | Phase tracks *why* each `EnvironmentKey` exists (individual vs team grant) so that removing team access doesn't accidentally revoke individually-granted keys | +| **Access tracking** | Phase tracks *how* each environment key was granted (individual vs team) so that removing team access doesn't accidentally revoke individually-granted keys | ## Creating a Team @@ -48,7 +49,36 @@ When a member is added to a team that already has app access, keys are provision 4. Optionally set **role overrides** (see [Role overrides](#role-overrides) below). If you skip this, team members will use their org role for app-level permissions. -5. Click **Create**. The team is created with no members or app access — you'll add those next. +5. Click **Create**. The team is created with no members or app access — you'll add those next. You are automatically set as the team **owner**. + +## Team ownership + +Each team has an **owner** — a team member with elevated management privileges. The team owner can always manage the team's app access and environment scope, even if their effective role (via a team role override) would not normally grant those permissions. + +When a team is created manually, the creator is automatically set as the owner. Teams created via [SCIM provisioning](/access-control/provisioning/scim) start with no owner, since the SCIM specification does not include group ownership information. + +### Who can set or transfer ownership + +| Action | Who can do it | +|--------|---------------| +| **Set owner** (when no owner exists) | Owner or Admin role users | +| **Transfer ownership** | Current team owner, or Owner/Admin role users | + +The new owner must be an existing member of the team. + +### Setting or transferring ownership + +1. Open the team detail page by clicking on the team name. + +2. Scroll to the **Ownership** section near the bottom of the page. If the team has an owner, their name is displayed. If not, you'll see a prompt to assign one. + +3. Click **Set owner** or **Transfer ownership**. + +4. Select a team member from the list and confirm. + + + If a team has no owner, only organisation Owner and Admin roles can assign one. This is relevant for SCIM-managed teams, where the team is created automatically without a designated owner. + ## Managing team members @@ -80,7 +110,7 @@ When a member is added to a team that already has app access, keys are provision 3. Select which **environments** within the app the team should have access to. -4. Click **Add**. Phase provisions environment keys for all team members with an active `identity_key`. Members who haven't completed their key ceremony yet (e.g. SCIM-provisioned users who haven't logged in) will receive keys on their first login. +4. Click **Add**. Phase provisions environment encryption keys for all active team members. Members who haven't completed their account setup yet (e.g. SCIM-provisioned users who haven't logged in) will receive keys on their first login. ### Updating environment access @@ -123,7 +153,7 @@ If a user has both **individual** (direct) access and **team** access to the sam ## SSE requirement -Teams require [Server-Side Encryption (SSE)](/console/apps#encryption-mode) to be enabled on any app they access. This is because the server needs to provision encryption keys on behalf of team members — it unwraps the `ServerEnvironmentKey` and re-wraps the environment seed/salt for each member's public key. +Teams require [Server-Side Encryption (SSE)](/console/apps#encryption-mode) to be enabled on any app they access. This is because the server needs to provision environment encryption keys on behalf of team members — it uses the server-held copy of the environment key to create individually-wrapped copies for each member. If an app has SSE disabled, it won't appear in the app selection dialog when adding apps to a team. You can enable SSE on an app from the app's settings page under **Encryption Mode**. @@ -149,7 +179,7 @@ Team-owned service accounts are visually distinguished with a team badge on both ### Visibility rules -| SA type | Who can see it | Who can manage it | +| Account type | Who can see it | Who can manage it | |---------|---------------|-------------------| | **Org-level** (no team) | Anyone with `ServiceAccounts.read` | Anyone with `ServiceAccounts.update/delete` | | **Team-owned** | Team members + Owner/Admin | Team members + Owner/Admin | @@ -160,12 +190,12 @@ Users who are not members of the owning team will not see team-owned service acc Owner and Admin users can transfer a service account between org-level and team ownership: -- **Team → Org-level**: Clears the team association. The service account becomes visible org-wide. Existing tokens and app access are preserved. +- **Team → Org-level**: Clears the team ownership. The service account becomes visible org-wide. Existing tokens and team membership are preserved. - **Org-level → Team**: Assigns the service account to a team. Visibility narrows to team members and global access users. ### Team deletion -When a team is deleted, all team-owned service accounts are soft-deleted and their tokens are revoked. Org-level service accounts that were added to the team as members are unaffected — they lose team-based app access but remain visible org-wide. +When a team is deleted, all team-owned service accounts are deleted and their tokens are revoked. Org-level service accounts that were added to the team as members are unaffected — they lose team-based app access but remain visible org-wide. ### Removing a team-owned SA from its team @@ -179,12 +209,13 @@ When [SCIM provisioning](/access-control/provisioning/scim) is configured, your - Membership changes must be made in the identity provider - A `SCIM` badge is shown next to the team name in the console - Role overrides and app access can still be managed from Phase +- SCIM-managed teams are created without an owner — an Owner or Admin must [assign one](#setting-or-transferring-ownership) to enable owner-level management -## Grant tracking +## Access tracking -Phase tracks the **reason** each `EnvironmentKey` exists using `EnvironmentKeyGrant` records. Each grant is tagged as either `individual` (direct app access) or `team` (via team membership), with a reference to the specific team. +Phase tracks **how** each environment key was granted — whether through direct (individual) access or through team membership. Each key grant records its source, including a reference to the specific team when applicable. -This prevents a common pitfall: if a user has both individual and team access to the same environment, removing the team access should *not* revoke the key. Phase only soft-deletes an `EnvironmentKey` when all of its grants have been removed. +This prevents a common pitfall: if a user has both individual and team access to the same environment, removing the team should *not* revoke their access. Phase only revokes an environment key when all of its access grants have been removed — so individually-granted keys are preserved even after a team is removed. ## Viewing team access on member and app pages diff --git a/public/sitemap.xml b/public/sitemap.xml index 7a0181be..de13a710 100644 --- a/public/sitemap.xml +++ b/public/sitemap.xml @@ -1,86 +1,86 @@ -https://docs.phase.dev2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/access-control2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/access-control/authentication2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/access-control/authentication/oauth-sso2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/access-control/authentication/oidc-sso2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/access-control/authentication/tokens2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/access-control/external-identities2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/access-control/network2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/access-control/provisioning/scim2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/access-control/roles2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/access-control/service-accounts2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/access-control/teams2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/cli2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/cli/commands2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/cli/install2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/cli/usage2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/console2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/console/apps2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/console/dynamic-secrets2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/console/environments2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/console/organisation2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/console/secrets2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/console/users2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/agents/claude-code2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/agents/codex2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/agents/cursor2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/agents/opencode2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/agents/vscode-copilot2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/frameworks2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/platforms/aws-codebuild2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/platforms/aws-elastic-container-service2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/platforms/aws-iam2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/platforms/aws-secrets-manager2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/platforms/azure-key-vault2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/platforms/azure-pipelines2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/platforms/bitbucket-pipelines2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/platforms/buildkite2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/platforms/circleci2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/platforms/cloudflare-pages2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/platforms/cloudflare-workers2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/platforms/docker2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/platforms/docker-compose2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/platforms/drone-ci2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/platforms/github-actions2026-04-14T14:13:03.319Zdaily0.7 -https://docs.phase.dev/integrations/platforms/github-dependabot2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/integrations/platforms/gitlab-ci2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/integrations/platforms/hashicorp-nomad2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/integrations/platforms/hashicorp-terraform2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/integrations/platforms/hashicorp-vault2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/integrations/platforms/jenkins2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/integrations/platforms/kubernetes2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/integrations/platforms/railway2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/integrations/platforms/render2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/integrations/platforms/teamcity2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/integrations/platforms/travis-ci2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/integrations/platforms/vercel2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/public-api2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/public-api/dynamic-secrets2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/public-api/errors2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/public-api/external-identities2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/public-api/secrets2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/quickstart2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/sdks2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/sdks/go2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/sdks/js2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/sdks/node2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/sdks/python2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/security2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/security/architecture2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/security/cryptography2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/self-hosting2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/self-hosting/aws2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/self-hosting/aws-eks2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/self-hosting/azure2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/self-hosting/configuration/envars2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/self-hosting/digitalocean2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/self-hosting/docker-compose2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/self-hosting/gcp2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/self-hosting/kubernetes2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/self-hosting/maintenance2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/self-hosting/railway2026-04-14T14:13:03.320Zdaily0.7 -https://docs.phase.dev/self-hosting/raspberrypi2026-04-14T14:13:03.320Zdaily0.7 +https://docs.phase.dev2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/access-control2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/access-control/authentication2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/access-control/authentication/oauth-sso2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/access-control/authentication/oidc-sso2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/access-control/authentication/tokens2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/access-control/external-identities2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/access-control/network2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/access-control/provisioning/scim2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/access-control/roles2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/access-control/service-accounts2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/access-control/teams2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/cli2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/cli/commands2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/cli/install2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/cli/usage2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/console2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/console/apps2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/console/dynamic-secrets2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/console/environments2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/console/organisation2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/console/secrets2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/console/users2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/agents/claude-code2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/agents/codex2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/agents/cursor2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/agents/opencode2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/agents/vscode-copilot2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/frameworks2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/platforms/aws-codebuild2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/platforms/aws-elastic-container-service2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/platforms/aws-iam2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/platforms/aws-secrets-manager2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/platforms/azure-key-vault2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/platforms/azure-pipelines2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/platforms/bitbucket-pipelines2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/platforms/buildkite2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/platforms/circleci2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/platforms/cloudflare-pages2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/platforms/cloudflare-workers2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/platforms/docker2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/platforms/docker-compose2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/platforms/drone-ci2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/platforms/github-actions2026-04-14T15:05:19.434Zdaily0.7 +https://docs.phase.dev/integrations/platforms/github-dependabot2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/integrations/platforms/gitlab-ci2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/integrations/platforms/hashicorp-nomad2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/integrations/platforms/hashicorp-terraform2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/integrations/platforms/hashicorp-vault2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/integrations/platforms/jenkins2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/integrations/platforms/kubernetes2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/integrations/platforms/railway2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/integrations/platforms/render2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/integrations/platforms/teamcity2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/integrations/platforms/travis-ci2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/integrations/platforms/vercel2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/public-api2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/public-api/dynamic-secrets2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/public-api/errors2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/public-api/external-identities2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/public-api/secrets2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/quickstart2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/sdks2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/sdks/go2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/sdks/js2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/sdks/node2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/sdks/python2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/security2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/security/architecture2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/security/cryptography2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/self-hosting2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/self-hosting/aws2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/self-hosting/aws-eks2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/self-hosting/azure2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/self-hosting/configuration/envars2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/self-hosting/digitalocean2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/self-hosting/docker-compose2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/self-hosting/gcp2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/self-hosting/kubernetes2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/self-hosting/maintenance2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/self-hosting/railway2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev/self-hosting/raspberrypi2026-04-14T15:05:19.435Zdaily0.7 \ No newline at end of file diff --git a/src/pages/access-control/teams.mdx b/src/pages/access-control/teams.mdx index 8b63fc8a..0adf2a8c 100644 --- a/src/pages/access-control/teams.mdx +++ b/src/pages/access-control/teams.mdx @@ -22,7 +22,7 @@ A Team is an organisation-level group that contains **members** (human users) an When a team is added to an app: 1. You select which environments the team should have access to (e.g. `Development`, `Staging`) -2. Phase's server automatically wraps `EnvironmentKey`s for every team member using the app's `ServerEnvironmentKey` +2. Phase automatically provisions environment encryption keys for every team member 3. Team members can immediately decrypt secrets in those environments When a member is added to a team that already has app access, keys are provisioned automatically. When a member is removed, their team-granted keys are revoked — unless they also have individual access to the same environment. @@ -31,12 +31,13 @@ When a member is added to a team that already has app access, keys are provision | Concept | Description | |---------|-------------| +| **Team ownership** | Each team has an owner who retains full management access regardless of role overrides | | **Team membership** | A user or service account belongs to one or more teams | | **Team app access** | A team is granted access to an app, scoped to specific environments | | **Role overrides** | Teams can optionally override the org role's app-level permissions for their members | | **Union semantics** | If a user is in multiple teams with access to the same app, they get the **union** of all team role permissions | | **Individual priority** | Individual (direct) app access always uses the org role, not team roles | -| **Grant tracking** | Phase tracks *why* each `EnvironmentKey` exists (individual vs team grant) so that removing team access doesn't accidentally revoke individually-granted keys | +| **Access tracking** | Phase tracks *how* each environment key was granted (individual vs team) so that removing team access doesn't accidentally revoke individually-granted keys | ## Creating a Team @@ -48,7 +49,36 @@ When a member is added to a team that already has app access, keys are provision 4. Optionally set **role overrides** (see [Role overrides](#role-overrides) below). If you skip this, team members will use their org role for app-level permissions. -5. Click **Create**. The team is created with no members or app access — you'll add those next. +5. Click **Create**. The team is created with no members or app access — you'll add those next. You are automatically set as the team **owner**. + +## Team ownership + +Each team has an **owner** — a team member with elevated management privileges. The team owner can always manage the team's app access and environment scope, even if their effective role (via a team role override) would not normally grant those permissions. + +When a team is created manually, the creator is automatically set as the owner. Teams created via [SCIM provisioning](/access-control/provisioning/scim) start with no owner, since the SCIM specification does not include group ownership information. + +### Who can set or transfer ownership + +| Action | Who can do it | +|--------|---------------| +| **Set owner** (when no owner exists) | Owner or Admin role users | +| **Transfer ownership** | Current team owner, or Owner/Admin role users | + +The new owner must be an existing member of the team. + +### Setting or transferring ownership + +1. Open the team detail page by clicking on the team name. + +2. Scroll to the **Ownership** section near the bottom of the page. If the team has an owner, their name is displayed. If not, you'll see a prompt to assign one. + +3. Click **Set owner** or **Transfer ownership**. + +4. Select a team member from the list and confirm. + + + If a team has no owner, only organisation Owner and Admin roles can assign one. This is relevant for SCIM-managed teams, where the team is created automatically without a designated owner. + ## Managing team members @@ -80,7 +110,7 @@ When a member is added to a team that already has app access, keys are provision 3. Select which **environments** within the app the team should have access to. -4. Click **Add**. Phase provisions environment keys for all team members with an active `identity_key`. Members who haven't completed their key ceremony yet (e.g. SCIM-provisioned users who haven't logged in) will receive keys on their first login. +4. Click **Add**. Phase provisions environment encryption keys for all active team members. Members who haven't completed their account setup yet (e.g. SCIM-provisioned users who haven't logged in) will receive keys on their first login. ### Updating environment access @@ -123,7 +153,7 @@ If a user has both **individual** (direct) access and **team** access to the sam ## SSE requirement -Teams require [Server-Side Encryption (SSE)](/console/apps#encryption-mode) to be enabled on any app they access. This is because the server needs to provision encryption keys on behalf of team members — it unwraps the `ServerEnvironmentKey` and re-wraps the environment seed/salt for each member's public key. +Teams require [Server-Side Encryption (SSE)](/console/apps#encryption-mode) to be enabled on any app they access. This is because the server needs to provision environment encryption keys on behalf of team members — it uses the server-held copy of the environment key to create individually-wrapped copies for each member. If an app has SSE disabled, it won't appear in the app selection dialog when adding apps to a team. You can enable SSE on an app from the app's settings page under **Encryption Mode**. @@ -179,12 +209,13 @@ When [SCIM provisioning](/access-control/provisioning/scim) is configured, your - Membership changes must be made in the identity provider - A `SCIM` badge is shown next to the team name in the console - Role overrides and app access can still be managed from Phase +- SCIM-managed teams are created without an owner — an Owner or Admin must [assign one](#setting-or-transferring-ownership) to enable owner-level management -## Grant tracking +## Access tracking -Phase tracks the **reason** each `EnvironmentKey` exists using `EnvironmentKeyGrant` records. Each grant is tagged as either `individual` (direct app access) or `team` (via team membership), with a reference to the specific team. +Phase tracks **how** each environment key was granted — whether through direct (individual) access or through team membership. Each key grant records its source, including a reference to the specific team when applicable. -This prevents a common pitfall: if a user has both individual and team access to the same environment, removing the team access should *not* revoke the key. Phase only soft-deletes an `EnvironmentKey` when all of its grants have been removed. +This prevents a common pitfall: if a user has both individual and team access to the same environment, removing the team should *not* revoke their access. Phase only revokes an environment key when all of its access grants have been removed — so individually-granted keys are preserved even after a team is removed. ## Viewing team access on member and app pages From 1a5d8085f3c103ed7f4561ac5528efd49cdde474 Mon Sep 17 00:00:00 2001 From: rohan Date: Wed, 15 Apr 2026 15:48:29 +0530 Subject: [PATCH 08/12] feat: misc fixes and clarifications to docs for teams and service accounts Signed-off-by: rohan --- src/pages/access-control/service-accounts.mdx | 6 +++++- src/pages/access-control/teams.mdx | 21 ++++++++++--------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/pages/access-control/service-accounts.mdx b/src/pages/access-control/service-accounts.mdx index 662eb233..389b35b9 100644 --- a/src/pages/access-control/service-accounts.mdx +++ b/src/pages/access-control/service-accounts.mdx @@ -88,12 +88,16 @@ To delete a Service Account, click on the "Delete" button at the bottom of the p Each Service Account has its own unique keyring, just like User accounts. KMS modes determine who has access to the service account's keyring and can create and manage tokens for this service account. #### Client-side KMS -By default, Service Accounts use **Client-side KMS**. This means only designated users with the required `ServiceAccountTokens` permissions have access to create and manage tokens for this service account. These users are called *Service Account Handlers* and have access the service account's keyring, encrypted with their own keys. +By default, org-level Service Accounts use **Client-side KMS**. This means only designated users with the required `ServiceAccountTokens` permissions have access to create and manage tokens for this service account. These users are called *Service Account Handlers* and have access the service account's keyring, encrypted with their own keys. #### Server-side KMS You can optionally enable **Server-side KMS** for a Service Account. This grants the Phase backend access to the service account's keyring, effectively making the backend a *Service Account Handler*. Enabling Server-side KMS allows the backend to create and manage tokens on behalf of the Service Account. This is required to use features such as [External Identities](/access-control/external-identities). + + **Team-owned service accounts** always use Server-side KMS. This is enabled automatically when the account is created, so that any team member with the appropriate permissions can generate tokens — without needing to be a designated Service Account Handler. This is important for dynamic team membership, including teams managed via [SCIM provisioning](/access-control/provisioning/scim), where members may join or leave at any time. + + #### Manage KMS mode You can manage the KMS mode for a Service Account by clicking the **Manage** button beside the account KMS indicator at the top of the account page: diff --git a/src/pages/access-control/teams.mdx b/src/pages/access-control/teams.mdx index 0adf2a8c..89e12572 100644 --- a/src/pages/access-control/teams.mdx +++ b/src/pages/access-control/teams.mdx @@ -35,8 +35,7 @@ When a member is added to a team that already has app access, keys are provision | **Team membership** | A user or service account belongs to one or more teams | | **Team app access** | A team is granted access to an app, scoped to specific environments | | **Role overrides** | Teams can optionally override the org role's app-level permissions for their members | -| **Union semantics** | If a user is in multiple teams with access to the same app, they get the **union** of all team role permissions | -| **Individual priority** | Individual (direct) app access always uses the org role, not team roles | +| **Union semantics** | If a user has multiple access grants to the same app (individual, one or more teams), they get the **union** of all applicable permissions | | **Access tracking** | Phase tracks *how* each environment key was granted (individual vs team) so that removing team access doesn't accidentally revoke individually-granted keys | ## Creating a Team @@ -143,13 +142,11 @@ When a role override is set, it replaces the org role's `app_permissions` for re ### Union semantics -If a user belongs to multiple teams that all have access to the same app, Phase takes the **union** of permissions across all applicable team roles. If *any* team role grants a permission, the user has that permission. +When a user has multiple access grants to the same app — whether through individual (direct) access, one or more teams, or a combination — Phase takes the **union** of all applicable permissions. If *any* grant permits an action, the user is allowed to perform it. -**Example:** Alice is in Team A (role: `Developer`) and Team B (role: `Manager`). Both teams have access to App X. Alice gets the union of Developer and Manager app-level permissions for App X. +Individual access uses the user's org role. Each team uses its role override (or the org role if no override is set). -### Individual access takes priority - -If a user has both **individual** (direct) access and **team** access to the same app, the individual access path is used. This means the user's org role determines app-level permissions, regardless of any team role overrides. +**Example:** Alice has individual access (org role: `Developer`) and is also in Team B (role: `Manager`). Both grant access to App X. Alice gets the union of Developer and Manager app-level permissions for App X. ## SSE requirement @@ -173,19 +170,23 @@ Service accounts can be **owned by a team**, meaning their lifecycle and visibil 3. If the team has a defined Service Account role, the role for this account will be fixed. If there is no defined role for service accounts in the team, select a role for this account. -4. Click **Create**. The The service account is automatically added as a member of the team and can access all apps and environments that the team is added to. +4. Click **Create**. The service account is automatically added as a member of the team and can access all apps and environments that the team has access to. + +Team-owned service accounts always use **Server-side KMS**, which is enabled automatically on creation. This allows any team member with the appropriate `ServiceAccountTokens` permissions to generate tokens for the account — without needing to be a designated Service Account Handler. This is essential for dynamic team membership, including [SCIM-managed teams](#scim-managed-teams), where members may join or leave at any time. Team-owned service accounts are visually distinguished with a team badge on both the team detail page and the organisation-level service accounts list. -### Visibility rules +### Visibility and management rules | Account type | Who can see it | Who can manage it | |---------|---------------|-------------------| | **Org-level** (no team) | Anyone with `ServiceAccounts.read` | Anyone with `ServiceAccounts.update/delete` | -| **Team-owned** | Team members + Owner/Admin | Team members + Owner/Admin | +| **Team-owned** | Team members + Owner/Admin | Team members with appropriate permissions + team owner + Owner/Admin | Users who are not members of the owning team will not see team-owned service accounts in the organisation-level service accounts list — unless they have global access (Owner/Admin). +Management permissions for team-owned service accounts are determined by the team's [role overrides](#role-overrides). If the team has a **Member role** override, that role's permissions are used for actions like creating tokens, updating the account, or managing KMS settings. If no override is set, the member's org role is used. The **team owner** always has full management access regardless of role overrides. + ### Ownership transfer Owner and Admin users can transfer a service account between org-level and team ownership: From 63ee52af113ee5f6234070bafc8f9b06bcb3ee3f Mon Sep 17 00:00:00 2001 From: rohan Date: Sat, 18 Apr 2026 21:10:49 +0530 Subject: [PATCH 09/12] docs: remove service account ownership transfer references --- src/pages/access-control/teams.mdx | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/pages/access-control/teams.mdx b/src/pages/access-control/teams.mdx index 89e12572..96877f4c 100644 --- a/src/pages/access-control/teams.mdx +++ b/src/pages/access-control/teams.mdx @@ -187,20 +187,13 @@ Users who are not members of the owning team will not see team-owned service acc Management permissions for team-owned service accounts are determined by the team's [role overrides](#role-overrides). If the team has a **Member role** override, that role's permissions are used for actions like creating tokens, updating the account, or managing KMS settings. If no override is set, the member's org role is used. The **team owner** always has full management access regardless of role overrides. -### Ownership transfer - -Owner and Admin users can transfer a service account between org-level and team ownership: - -- **Team → Org-level**: Clears the team ownership. The service account becomes visible org-wide. Existing tokens and team membership are preserved. -- **Org-level → Team**: Assigns the service account to a team. Visibility narrows to team members and global access users. - ### Team deletion When a team is deleted, all team-owned service accounts are deleted and their tokens are revoked. Org-level service accounts that were added to the team as members are unaffected — they lose team-based app access but remain visible org-wide. ### Removing a team-owned SA from its team -A team-owned service account cannot be removed from its owning team. To dissociate it from the team, either delete the service account or transfer its ownership to the organisation (Owner/Admin only). +A team-owned service account cannot be removed from its owning team. To dissociate it from the team, delete the service account. Ownership cannot be changed after creation — if you need an organisation-level account instead, create a new service account at the organisation level. ## SCIM-managed teams From a3b088c9d24e642df09f1b2c00e5182a833d799f Mon Sep 17 00:00:00 2001 From: rohan Date: Sat, 18 Apr 2026 21:19:55 +0530 Subject: [PATCH 10/12] chore: rebuild sitemap and mds Signed-off-by: rohan --- public/access-control/service-accounts.md | 6 +- public/access-control/teams.md | 28 ++-- public/sitemap.xml | 166 +++++++++++----------- 3 files changed, 99 insertions(+), 101 deletions(-) diff --git a/public/access-control/service-accounts.md b/public/access-control/service-accounts.md index 662eb233..389b35b9 100644 --- a/public/access-control/service-accounts.md +++ b/public/access-control/service-accounts.md @@ -88,12 +88,16 @@ To delete a Service Account, click on the "Delete" button at the bottom of the p Each Service Account has its own unique keyring, just like User accounts. KMS modes determine who has access to the service account's keyring and can create and manage tokens for this service account. #### Client-side KMS -By default, Service Accounts use **Client-side KMS**. This means only designated users with the required `ServiceAccountTokens` permissions have access to create and manage tokens for this service account. These users are called *Service Account Handlers* and have access the service account's keyring, encrypted with their own keys. +By default, org-level Service Accounts use **Client-side KMS**. This means only designated users with the required `ServiceAccountTokens` permissions have access to create and manage tokens for this service account. These users are called *Service Account Handlers* and have access the service account's keyring, encrypted with their own keys. #### Server-side KMS You can optionally enable **Server-side KMS** for a Service Account. This grants the Phase backend access to the service account's keyring, effectively making the backend a *Service Account Handler*. Enabling Server-side KMS allows the backend to create and manage tokens on behalf of the Service Account. This is required to use features such as [External Identities](/access-control/external-identities). + + **Team-owned service accounts** always use Server-side KMS. This is enabled automatically when the account is created, so that any team member with the appropriate permissions can generate tokens — without needing to be a designated Service Account Handler. This is important for dynamic team membership, including teams managed via [SCIM provisioning](/access-control/provisioning/scim), where members may join or leave at any time. + + #### Manage KMS mode You can manage the KMS mode for a Service Account by clicking the **Manage** button beside the account KMS indicator at the top of the account page: diff --git a/public/access-control/teams.md b/public/access-control/teams.md index 0adf2a8c..96877f4c 100644 --- a/public/access-control/teams.md +++ b/public/access-control/teams.md @@ -35,8 +35,7 @@ When a member is added to a team that already has app access, keys are provision | **Team membership** | A user or service account belongs to one or more teams | | **Team app access** | A team is granted access to an app, scoped to specific environments | | **Role overrides** | Teams can optionally override the org role's app-level permissions for their members | -| **Union semantics** | If a user is in multiple teams with access to the same app, they get the **union** of all team role permissions | -| **Individual priority** | Individual (direct) app access always uses the org role, not team roles | +| **Union semantics** | If a user has multiple access grants to the same app (individual, one or more teams), they get the **union** of all applicable permissions | | **Access tracking** | Phase tracks *how* each environment key was granted (individual vs team) so that removing team access doesn't accidentally revoke individually-granted keys | ## Creating a Team @@ -143,13 +142,11 @@ When a role override is set, it replaces the org role's `app_permissions` for re ### Union semantics -If a user belongs to multiple teams that all have access to the same app, Phase takes the **union** of permissions across all applicable team roles. If *any* team role grants a permission, the user has that permission. +When a user has multiple access grants to the same app — whether through individual (direct) access, one or more teams, or a combination — Phase takes the **union** of all applicable permissions. If *any* grant permits an action, the user is allowed to perform it. -**Example:** Alice is in Team A (role: `Developer`) and Team B (role: `Manager`). Both teams have access to App X. Alice gets the union of Developer and Manager app-level permissions for App X. +Individual access uses the user's org role. Each team uses its role override (or the org role if no override is set). -### Individual access takes priority - -If a user has both **individual** (direct) access and **team** access to the same app, the individual access path is used. This means the user's org role determines app-level permissions, regardless of any team role overrides. +**Example:** Alice has individual access (org role: `Developer`) and is also in Team B (role: `Manager`). Both grant access to App X. Alice gets the union of Developer and Manager app-level permissions for App X. ## SSE requirement @@ -173,25 +170,22 @@ Service accounts can be **owned by a team**, meaning their lifecycle and visibil 3. If the team has a defined Service Account role, the role for this account will be fixed. If there is no defined role for service accounts in the team, select a role for this account. -4. Click **Create**. The The service account is automatically added as a member of the team and can access all apps and environments that the team is added to. +4. Click **Create**. The service account is automatically added as a member of the team and can access all apps and environments that the team has access to. + +Team-owned service accounts always use **Server-side KMS**, which is enabled automatically on creation. This allows any team member with the appropriate `ServiceAccountTokens` permissions to generate tokens for the account — without needing to be a designated Service Account Handler. This is essential for dynamic team membership, including [SCIM-managed teams](#scim-managed-teams), where members may join or leave at any time. Team-owned service accounts are visually distinguished with a team badge on both the team detail page and the organisation-level service accounts list. -### Visibility rules +### Visibility and management rules | Account type | Who can see it | Who can manage it | |---------|---------------|-------------------| | **Org-level** (no team) | Anyone with `ServiceAccounts.read` | Anyone with `ServiceAccounts.update/delete` | -| **Team-owned** | Team members + Owner/Admin | Team members + Owner/Admin | +| **Team-owned** | Team members + Owner/Admin | Team members with appropriate permissions + team owner + Owner/Admin | Users who are not members of the owning team will not see team-owned service accounts in the organisation-level service accounts list — unless they have global access (Owner/Admin). -### Ownership transfer - -Owner and Admin users can transfer a service account between org-level and team ownership: - -- **Team → Org-level**: Clears the team ownership. The service account becomes visible org-wide. Existing tokens and team membership are preserved. -- **Org-level → Team**: Assigns the service account to a team. Visibility narrows to team members and global access users. +Management permissions for team-owned service accounts are determined by the team's [role overrides](#role-overrides). If the team has a **Member role** override, that role's permissions are used for actions like creating tokens, updating the account, or managing KMS settings. If no override is set, the member's org role is used. The **team owner** always has full management access regardless of role overrides. ### Team deletion @@ -199,7 +193,7 @@ When a team is deleted, all team-owned service accounts are deleted and their to ### Removing a team-owned SA from its team -A team-owned service account cannot be removed from its owning team. To dissociate it from the team, either delete the service account or transfer its ownership to the organisation (Owner/Admin only). +A team-owned service account cannot be removed from its owning team. To dissociate it from the team, delete the service account. Ownership cannot be changed after creation — if you need an organisation-level account instead, create a new service account at the organisation level. ## SCIM-managed teams diff --git a/public/sitemap.xml b/public/sitemap.xml index de13a710..980f4800 100644 --- a/public/sitemap.xml +++ b/public/sitemap.xml @@ -1,86 +1,86 @@ -https://docs.phase.dev2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/access-control2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/access-control/authentication2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/access-control/authentication/oauth-sso2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/access-control/authentication/oidc-sso2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/access-control/authentication/tokens2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/access-control/external-identities2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/access-control/network2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/access-control/provisioning/scim2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/access-control/roles2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/access-control/service-accounts2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/access-control/teams2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/cli2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/cli/commands2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/cli/install2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/cli/usage2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/console2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/console/apps2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/console/dynamic-secrets2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/console/environments2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/console/organisation2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/console/secrets2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/console/users2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/agents/claude-code2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/agents/codex2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/agents/cursor2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/agents/opencode2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/agents/vscode-copilot2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/frameworks2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/platforms/aws-codebuild2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/platforms/aws-elastic-container-service2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/platforms/aws-iam2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/platforms/aws-secrets-manager2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/platforms/azure-key-vault2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/platforms/azure-pipelines2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/platforms/bitbucket-pipelines2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/platforms/buildkite2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/platforms/circleci2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/platforms/cloudflare-pages2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/platforms/cloudflare-workers2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/platforms/docker2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/platforms/docker-compose2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/platforms/drone-ci2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/platforms/github-actions2026-04-14T15:05:19.434Zdaily0.7 -https://docs.phase.dev/integrations/platforms/github-dependabot2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/integrations/platforms/gitlab-ci2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/integrations/platforms/hashicorp-nomad2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/integrations/platforms/hashicorp-terraform2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/integrations/platforms/hashicorp-vault2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/integrations/platforms/jenkins2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/integrations/platforms/kubernetes2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/integrations/platforms/railway2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/integrations/platforms/render2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/integrations/platforms/teamcity2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/integrations/platforms/travis-ci2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/integrations/platforms/vercel2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/public-api2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/public-api/dynamic-secrets2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/public-api/errors2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/public-api/external-identities2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/public-api/secrets2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/quickstart2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/sdks2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/sdks/go2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/sdks/js2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/sdks/node2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/sdks/python2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/security2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/security/architecture2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/security/cryptography2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/self-hosting2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/self-hosting/aws2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/self-hosting/aws-eks2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/self-hosting/azure2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/self-hosting/configuration/envars2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/self-hosting/digitalocean2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/self-hosting/docker-compose2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/self-hosting/gcp2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/self-hosting/kubernetes2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/self-hosting/maintenance2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/self-hosting/railway2026-04-14T15:05:19.435Zdaily0.7 -https://docs.phase.dev/self-hosting/raspberrypi2026-04-14T15:05:19.435Zdaily0.7 +https://docs.phase.dev2026-04-18T15:43:14.782Zdaily0.7 +https://docs.phase.dev/access-control2026-04-18T15:43:14.785Zdaily0.7 +https://docs.phase.dev/access-control/authentication2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/access-control/authentication/oauth-sso2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/access-control/authentication/oidc-sso2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/access-control/authentication/tokens2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/access-control/external-identities2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/access-control/network2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/access-control/provisioning/scim2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/access-control/roles2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/access-control/service-accounts2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/access-control/teams2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/cli2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/cli/commands2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/cli/install2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/cli/usage2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/console2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/console/apps2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/console/dynamic-secrets2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/console/environments2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/console/organisation2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/console/secrets2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/console/users2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/agents/claude-code2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/agents/codex2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/agents/cursor2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/agents/opencode2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/agents/vscode-copilot2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/frameworks2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/aws-codebuild2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/aws-elastic-container-service2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/aws-iam2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/aws-secrets-manager2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/azure-key-vault2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/azure-pipelines2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/bitbucket-pipelines2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/buildkite2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/circleci2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/cloudflare-pages2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/cloudflare-workers2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/docker2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/docker-compose2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/drone-ci2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/github-actions2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/github-dependabot2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/gitlab-ci2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/hashicorp-nomad2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/hashicorp-terraform2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/hashicorp-vault2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/jenkins2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/kubernetes2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/railway2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/render2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/teamcity2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/travis-ci2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/integrations/platforms/vercel2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/public-api2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/public-api/dynamic-secrets2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/public-api/errors2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/public-api/external-identities2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/public-api/secrets2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/quickstart2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/sdks2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/sdks/go2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/sdks/js2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/sdks/node2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/sdks/python2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/security2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/security/architecture2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/security/cryptography2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/self-hosting2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/self-hosting/aws2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/self-hosting/aws-eks2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/self-hosting/azure2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/self-hosting/configuration/envars2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/self-hosting/digitalocean2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/self-hosting/docker-compose2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/self-hosting/gcp2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/self-hosting/kubernetes2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/self-hosting/maintenance2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/self-hosting/railway2026-04-18T15:43:14.786Zdaily0.7 +https://docs.phase.dev/self-hosting/raspberrypi2026-04-18T15:43:14.786Zdaily0.7 \ No newline at end of file From 57c3650a2379acabebb372d0e70628052efbc37e Mon Sep 17 00:00:00 2001 From: rohan Date: Sat, 18 Apr 2026 22:07:39 +0530 Subject: [PATCH 11/12] chore: regen sitemap Signed-off-by: rohan --- public/sitemap.xml | 164 +++++++++++++++++++++++---------------------- 1 file changed, 83 insertions(+), 81 deletions(-) diff --git a/public/sitemap.xml b/public/sitemap.xml index 2bf31601..4ca568ea 100644 --- a/public/sitemap.xml +++ b/public/sitemap.xml @@ -1,84 +1,86 @@ -https://docs.phase.dev2026-04-05T09:15:58.955Zdaily0.7 -https://docs.phase.dev/access-control2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/access-control/authentication2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/access-control/authentication/oauth-sso2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/access-control/authentication/oidc-sso2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/access-control/authentication/tokens2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/access-control/external-identities2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/access-control/network2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/access-control/roles2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/access-control/service-accounts2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/cli2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/cli/commands2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/cli/install2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/cli/usage2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/console2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/console/apps2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/console/dynamic-secrets2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/console/environments2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/console/organisation2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/console/secrets2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/console/users2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/agents/claude-code2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/agents/codex2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/agents/cursor2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/agents/opencode2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/agents/vscode-copilot2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/frameworks2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/aws-codebuild2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/aws-elastic-container-service2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/aws-iam2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/aws-secrets-manager2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/azure-key-vault2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/azure-pipelines2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/bitbucket-pipelines2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/buildkite2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/circleci2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/cloudflare-pages2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/cloudflare-workers2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/docker2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/docker-compose2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/drone-ci2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/github-actions2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/github-dependabot2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/gitlab-ci2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/hashicorp-nomad2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/hashicorp-terraform2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/hashicorp-vault2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/jenkins2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/kubernetes2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/railway2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/render2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/teamcity2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/travis-ci2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/integrations/platforms/vercel2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/public-api2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/public-api/dynamic-secrets2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/public-api/errors2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/public-api/external-identities2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/public-api/secrets2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/quickstart2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/sdks2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/sdks/go2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/sdks/js2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/sdks/node2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/sdks/python2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/security2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/security/architecture2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/security/cryptography2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/self-hosting2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/self-hosting/aws2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/self-hosting/aws-eks2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/self-hosting/azure2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/self-hosting/configuration/envars2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/self-hosting/digitalocean2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/self-hosting/docker-compose2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/self-hosting/gcp2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/self-hosting/kubernetes2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/self-hosting/maintenance2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/self-hosting/railway2026-04-05T09:15:58.956Zdaily0.7 -https://docs.phase.dev/self-hosting/raspberrypi2026-04-05T09:15:58.956Zdaily0.7 +https://docs.phase.dev2026-04-18T16:35:11.806Zdaily0.7 +https://docs.phase.dev/access-control2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/access-control/authentication2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/access-control/authentication/oauth-sso2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/access-control/authentication/oidc-sso2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/access-control/authentication/tokens2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/access-control/external-identities2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/access-control/network2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/access-control/provisioning/scim2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/access-control/roles2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/access-control/service-accounts2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/access-control/teams2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/cli2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/cli/commands2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/cli/install2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/cli/usage2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/console2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/console/apps2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/console/dynamic-secrets2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/console/environments2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/console/organisation2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/console/secrets2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/console/users2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/agents/claude-code2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/agents/codex2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/agents/cursor2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/agents/opencode2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/agents/vscode-copilot2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/frameworks2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/aws-codebuild2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/aws-elastic-container-service2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/aws-iam2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/aws-secrets-manager2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/azure-key-vault2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/azure-pipelines2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/bitbucket-pipelines2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/buildkite2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/circleci2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/cloudflare-pages2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/cloudflare-workers2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/docker2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/docker-compose2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/drone-ci2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/github-actions2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/github-dependabot2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/gitlab-ci2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/hashicorp-nomad2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/hashicorp-terraform2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/hashicorp-vault2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/jenkins2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/kubernetes2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/railway2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/render2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/teamcity2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/travis-ci2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/integrations/platforms/vercel2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/public-api2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/public-api/dynamic-secrets2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/public-api/errors2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/public-api/external-identities2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/public-api/secrets2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/quickstart2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/sdks2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/sdks/go2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/sdks/js2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/sdks/node2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/sdks/python2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/security2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/security/architecture2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/security/cryptography2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/self-hosting2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/self-hosting/aws2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/self-hosting/aws-eks2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/self-hosting/azure2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/self-hosting/configuration/envars2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/self-hosting/digitalocean2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/self-hosting/docker-compose2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/self-hosting/gcp2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/self-hosting/kubernetes2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/self-hosting/maintenance2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/self-hosting/railway2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev/self-hosting/raspberrypi2026-04-18T16:35:11.807Zdaily0.7 \ No newline at end of file From 0998441f55001179a654c34fc99e017fa4ca2d55 Mon Sep 17 00:00:00 2001 From: rohan Date: Fri, 1 May 2026 17:05:15 +0530 Subject: [PATCH 12/12] chore: update sitema Signed-off-by: rohan --- public/cli/install.md | 20 ++++- public/quickstart.md | 12 ++- public/sitemap.xml | 168 +++++++++++++++++++++--------------------- 3 files changed, 114 insertions(+), 86 deletions(-) diff --git a/public/cli/install.md b/public/cli/install.md index 937fc346..1cf5fa74 100644 --- a/public/cli/install.md +++ b/public/cli/install.md @@ -37,11 +37,21 @@ curl -fsSL https://pkg.phase.dev/install.sh | sh # curl -fsSL https://pkg.phase.dev/install.sh | sh -s -- --version 2.0.0 ``` -```fish {{ title: 'Windows' }} +```fish {{ title: 'Scoop' }} scoop bucket add phasehq https://github.com/phasehq/scoop-cli.git scoop install phase ``` +```fish {{ title: 'Windows (.exe)' }} +# Download the latest .exe for your architecture from: +# https://github.com/phasehq/cli/releases/latest +# +# phase_cli__windows_amd64.exe (Intel / AMD 64-bit) +# phase_cli__windows_arm64.exe (ARM 64-bit) +# +# Rename to phase.exe and add it to a directory on your PATH. +``` + ```fish {{ title: 'Alpine Linux' }} apk add --no-cache curl curl -fsSL https://pkg.phase.dev/install.sh | sh @@ -73,10 +83,16 @@ brew update && brew upgrade phase phase update ``` -```fish {{ title: 'Windows' }} +```fish {{ title: 'Scoop' }} scoop update phase ``` +```fish {{ title: 'Windows (.exe)' }} +# Re-download the latest .exe from: +# https://github.com/phasehq/cli/releases/latest +# and replace your existing phase.exe. +``` + ```fish {{ title: 'Alpine Linux' }} phase update ``` diff --git a/public/quickstart.md b/public/quickstart.md index 2d630d63..7ff4a092 100644 --- a/public/quickstart.md +++ b/public/quickstart.md @@ -42,11 +42,21 @@ brew install phasehq/cli/phase curl -fsSL https://pkg.phase.dev/install.sh | bash ``` -```fish {{ title: 'Windows' }} +```fish {{ title: 'Scoop' }} scoop bucket add phasehq https://github.com/phasehq/scoop-cli.git scoop install phase ``` +```fish {{ title: 'Windows (.exe)' }} +# Download the latest .exe for your architecture from: +# https://github.com/phasehq/cli/releases/latest +# +# phase_cli__windows_amd64.exe (Intel / AMD 64-bit) +# phase_cli__windows_arm64.exe (ARM 64-bit) +# +# Rename to phase.exe and add it to a directory on your PATH. +``` + ```fish {{ title: 'Alpine Linux' }} curl -fsSL https://pkg.phase.dev/install.sh | bash ``` diff --git a/public/sitemap.xml b/public/sitemap.xml index 4ca568ea..46c06d83 100644 --- a/public/sitemap.xml +++ b/public/sitemap.xml @@ -1,86 +1,88 @@ -https://docs.phase.dev2026-04-18T16:35:11.806Zdaily0.7 -https://docs.phase.dev/access-control2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/access-control/authentication2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/access-control/authentication/oauth-sso2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/access-control/authentication/oidc-sso2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/access-control/authentication/tokens2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/access-control/external-identities2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/access-control/network2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/access-control/provisioning/scim2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/access-control/roles2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/access-control/service-accounts2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/access-control/teams2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/cli2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/cli/commands2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/cli/install2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/cli/usage2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/console2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/console/apps2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/console/dynamic-secrets2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/console/environments2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/console/organisation2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/console/secrets2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/console/users2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/agents/claude-code2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/agents/codex2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/agents/cursor2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/agents/opencode2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/agents/vscode-copilot2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/frameworks2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/aws-codebuild2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/aws-elastic-container-service2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/aws-iam2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/aws-secrets-manager2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/azure-key-vault2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/azure-pipelines2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/bitbucket-pipelines2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/buildkite2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/circleci2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/cloudflare-pages2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/cloudflare-workers2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/docker2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/docker-compose2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/drone-ci2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/github-actions2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/github-dependabot2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/gitlab-ci2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/hashicorp-nomad2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/hashicorp-terraform2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/hashicorp-vault2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/jenkins2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/kubernetes2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/railway2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/render2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/teamcity2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/travis-ci2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/integrations/platforms/vercel2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/public-api2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/public-api/dynamic-secrets2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/public-api/errors2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/public-api/external-identities2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/public-api/secrets2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/quickstart2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/sdks2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/sdks/go2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/sdks/js2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/sdks/node2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/sdks/python2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/security2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/security/architecture2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/security/cryptography2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/self-hosting2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/self-hosting/aws2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/self-hosting/aws-eks2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/self-hosting/azure2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/self-hosting/configuration/envars2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/self-hosting/digitalocean2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/self-hosting/docker-compose2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/self-hosting/gcp2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/self-hosting/kubernetes2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/self-hosting/maintenance2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/self-hosting/railway2026-04-18T16:35:11.807Zdaily0.7 -https://docs.phase.dev/self-hosting/raspberrypi2026-04-18T16:35:11.807Zdaily0.7 +https://docs.phase.dev2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/access-control2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/access-control/authentication2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/access-control/authentication/oauth-sso2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/access-control/authentication/oidc-sso2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/access-control/authentication/password2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/access-control/authentication/sso2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/access-control/authentication/tokens2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/access-control/external-identities2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/access-control/network2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/access-control/provisioning/scim2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/access-control/roles2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/access-control/service-accounts2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/access-control/teams2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/cli2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/cli/commands2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/cli/install2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/cli/usage2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/console2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/console/apps2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/console/dynamic-secrets2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/console/environments2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/console/organisation2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/console/secrets2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/console/users2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/agents/claude-code2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/agents/codex2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/agents/cursor2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/agents/opencode2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/agents/vscode-copilot2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/frameworks2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/aws-codebuild2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/aws-elastic-container-service2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/aws-iam2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/aws-secrets-manager2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/azure-key-vault2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/azure-pipelines2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/bitbucket-pipelines2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/buildkite2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/circleci2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/cloudflare-pages2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/cloudflare-workers2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/docker2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/docker-compose2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/drone-ci2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/github-actions2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/github-dependabot2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/gitlab-ci2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/hashicorp-nomad2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/hashicorp-terraform2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/hashicorp-vault2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/jenkins2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/kubernetes2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/railway2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/render2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/teamcity2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/travis-ci2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/integrations/platforms/vercel2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/public-api2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/public-api/dynamic-secrets2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/public-api/errors2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/public-api/external-identities2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/public-api/secrets2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/quickstart2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/sdks2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/sdks/go2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/sdks/js2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/sdks/node2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/sdks/python2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/security2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/security/architecture2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/security/cryptography2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/self-hosting2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/self-hosting/aws2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/self-hosting/aws-eks2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/self-hosting/azure2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/self-hosting/configuration/envars2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/self-hosting/digitalocean2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/self-hosting/docker-compose2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/self-hosting/gcp2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/self-hosting/kubernetes2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/self-hosting/maintenance2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/self-hosting/railway2026-05-01T11:33:56.846Zdaily0.7 +https://docs.phase.dev/self-hosting/raspberrypi2026-05-01T11:33:56.846Zdaily0.7 \ No newline at end of file