From 3c58b02d86a21d0a98b2c863d32b916e44da6b3b Mon Sep 17 00:00:00 2001 From: rohan Date: Fri, 4 Sep 2026 22:41:56 +0530 Subject: [PATCH 1/3] chore: fix typos and grammar Signed-off-by: rohan --- .../access-control/authentication/account.md | 105 ++++++ public/access-control/authentication/mfa.md | 72 +++++ .../authentication/oauth-sso.md | 6 +- .../access-control/authentication/oidc-sso.md | 10 +- .../access-control/authentication/password.md | 4 +- public/access-control/authentication/sso.md | 16 +- public/access-control/external-identities.md | 6 +- public/access-control/network.md | 2 +- public/access-control/roles.md | 6 +- public/access-control/service-accounts.md | 12 +- public/cli.md | 2 +- public/cli/commands.md | 20 +- public/console/dynamic-secrets.md | 10 +- public/console/logstreams.md | 304 ++++++++++++++++++ public/console/organisation.md | 12 +- public/console/secrets.md | 2 +- public/console/users.md | 12 +- public/index.md | 4 +- .../integrations/platforms/aws-codebuild.md | 2 +- public/integrations/platforms/aws-iam.md | 4 +- .../platforms/aws-secrets-manager.md | 10 +- .../integrations/platforms/azure-pipelines.md | 2 +- .../platforms/bitbucket-pipelines.md | 4 +- public/integrations/platforms/buildkite.md | 4 +- public/integrations/platforms/circleci.md | 4 +- .../platforms/cloudflare-workers.md | 2 +- .../integrations/platforms/docker-compose.md | 6 +- public/integrations/platforms/docker.md | 6 +- public/integrations/platforms/drone-ci.md | 4 +- .../integrations/platforms/github-actions.md | 10 +- .../platforms/github-dependabot.md | 8 +- public/integrations/platforms/gitlab-ci.md | 2 +- .../integrations/platforms/hashicorp-nomad.md | 6 +- .../platforms/hashicorp-terraform.md | 2 +- .../integrations/platforms/hashicorp-vault.md | 6 +- public/integrations/platforms/jenkins.md | 2 +- public/integrations/platforms/jetbrains.md | 2 +- public/integrations/platforms/kubernetes.md | 2 +- public/integrations/platforms/railway.md | 2 +- public/integrations/platforms/teamcity.md | 4 +- public/integrations/platforms/travis-ci.md | 4 +- public/integrations/platforms/vercel.md | 8 +- public/llms.txt | 3 + public/public-api/errors.md | 4 +- public/public-api/secrets.md | 4 +- public/quickstart.md | 4 +- public/sdks/js.md | 6 +- public/security/architecture.md | 14 +- public/security/cryptography.md | 4 +- public/self-hosting/aws.md | 4 +- public/self-hosting/azure.md | 6 +- public/self-hosting/configuration/envars.md | 27 +- public/self-hosting/digitalocean.md | 6 +- public/self-hosting/gcp.md | 4 +- public/self-hosting/kubernetes.md | 2 +- public/self-hosting/maintenance.md | 6 +- public/self-hosting/railway.md | 2 +- public/self-hosting/raspberrypi.md | 2 +- public/sitemap.xml | 199 ++++++------ .../authentication/oauth-sso.mdx | 6 +- .../authentication/oidc-sso.mdx | 6 +- .../access-control/external-identities.mdx | 6 +- src/pages/access-control/network.mdx | 2 +- src/pages/access-control/roles.mdx | 6 +- src/pages/access-control/service-accounts.mdx | 12 +- src/pages/cli/commands.mdx | 20 +- src/pages/cli/index.mdx | 2 +- src/pages/console/dynamic-secrets.mdx | 10 +- src/pages/console/organisation.mdx | 12 +- src/pages/console/secrets.mdx | 2 +- src/pages/console/users.mdx | 12 +- src/pages/index.mdx | 4 +- .../integrations/platforms/aws-codebuild.mdx | 2 +- src/pages/integrations/platforms/aws-iam.mdx | 4 +- .../platforms/aws-secrets-manager.mdx | 10 +- .../platforms/azure-pipelines.mdx | 2 +- .../platforms/bitbucket-pipelines.mdx | 4 +- .../integrations/platforms/buildkite.mdx | 4 +- src/pages/integrations/platforms/circleci.mdx | 4 +- .../platforms/cloudflare-workers.mdx | 2 +- .../integrations/platforms/docker-compose.mdx | 6 +- src/pages/integrations/platforms/docker.mdx | 6 +- src/pages/integrations/platforms/drone-ci.mdx | 4 +- .../integrations/platforms/github-actions.mdx | 10 +- .../platforms/github-dependabot.mdx | 8 +- .../integrations/platforms/gitlab-ci.mdx | 2 +- .../platforms/hashicorp-nomad.mdx | 6 +- .../platforms/hashicorp-terraform.mdx | 2 +- .../platforms/hashicorp-vault.mdx | 6 +- src/pages/integrations/platforms/jenkins.mdx | 2 +- .../integrations/platforms/jetbrains.mdx | 2 +- .../integrations/platforms/kubernetes.mdx | 2 +- src/pages/integrations/platforms/railway.mdx | 2 +- src/pages/integrations/platforms/teamcity.mdx | 4 +- .../integrations/platforms/travis-ci.mdx | 4 +- src/pages/integrations/platforms/vercel.mdx | 8 +- src/pages/public-api/errors.mdx | 4 +- src/pages/public-api/secrets.mdx | 4 +- src/pages/quickstart.mdx | 4 +- src/pages/sdks/js.mdx | 6 +- src/pages/security/architecture.mdx | 14 +- src/pages/security/cryptography.mdx | 4 +- src/pages/self-hosting/aws.mdx | 4 +- src/pages/self-hosting/azure.mdx | 6 +- .../self-hosting/configuration/envars.mdx | 14 +- src/pages/self-hosting/digitalocean.mdx | 6 +- src/pages/self-hosting/gcp.mdx | 4 +- src/pages/self-hosting/kubernetes.mdx | 2 +- src/pages/self-hosting/maintenance/index.mdx | 6 +- src/pages/self-hosting/railway.mdx | 2 +- src/pages/self-hosting/raspberrypi.mdx | 2 +- 111 files changed, 906 insertions(+), 390 deletions(-) create mode 100644 public/access-control/authentication/account.md create mode 100644 public/access-control/authentication/mfa.md create mode 100644 public/console/logstreams.md diff --git a/public/access-control/authentication/account.md b/public/access-control/authentication/account.md new file mode 100644 index 00000000..e2300874 --- /dev/null +++ b/public/access-control/authentication/account.md @@ -0,0 +1,105 @@ +import { Tag } from '@/components/Tag' +import { DocActions } from '@/components/DocActions' + +export const description = 'Manage your Phase account: linked sign-in methods, email address, display name, and account deletion.' + +AUTHENTICATION + +# Account Management + +The Account page lets you manage everything about how you sign in to Phase. It is personal to you and applies across all of your organisations. Open it from the user menu in the top right corner of the Console: click your avatar, then click your profile card (your name and email) at the top of the menu. + +![The profile card in the user menu opens the Account page](/assets/images/auth/account/user-menu.png) + + + +![The Account page](/assets/images/auth/account/account-page.png) + +## Sensitive action re-authentication + +Changes to your sign-in methods, email address, two-factor authentication, and account deletion require a recent sign-in. The default window is 15 minutes. Self-hosted operators can tune it with the [`AUTH_FRESHNESS_MAX_AGE_SECONDS`](/self-hosting/configuration/envars#additional-environment-variables) environment variable. + +If your last sign-in is older than that, a **Confirm it's you** dialog appears when you start the change. You can cancel, or sign in again to continue. This limits what a stolen or unattended session can do. + +![Confirm it's you dialog](/assets/images/auth/account/reauth-dialog.png) + +The login page shows why you are back, and offers only the sign-in methods linked to your account. + +![Login page during re-authentication](/assets/images/auth/account/reauth-login.png) + +Signing in again does not lose your place. Phase returns you to the Account page and restores the interrupted flow: the same dialog, the same step, and anything you had entered. Codes and passwords are never carried over, so you enter them again. + +## Sign-in methods + +Your account can have multiple sign-in identities linked to it, for example a Google account and a Microsoft Entra ID identity. You can sign in with any linked identity, and they all resolve to the same Phase account, keyrings, and organisation memberships. + +### Linking a new sign-in method + +1. On the Account page, find **Sign-in methods**. Providers configured on your instance are shown, along with any organisation-level SSO providers for organisations you are a member of. Active methods show a badge: *Linked* for identities, *Enabled* for a password. +2. Hover the card of an unlinked provider and click **Link**. +3. Authenticate with the provider. You will be returned to the Account page with the new identity linked. + +Identities are matched by the provider's stable account ID, not by email address. **The email on the linked identity does not need to match your Phase account email.** This makes linking the right tool for moving to a new identity provider. For example: you signed up with Google, and your organisation later adopts Microsoft Entra ID SSO. Link your Entra ID identity from the Account page, and you can sign in with either from then on. + + +If you see *"An account with this email already exists"* when signing in with a new provider, this is Phase's account takeover protection: a new sign-in identity is never automatically attached to an existing account based on a matching email. Sign in with your existing method and link the new provider from the Account page instead. If you hold a pending invite to the organisation, the message directs you to accept the invite with your existing sign-in method first. The organisation's SSO works after you join. + + +Linking an identity that is already attached to a different Phase account is refused. Phase never merges accounts. Linking is also refused when the provider reports the identity's email as unverified. Verify it with your provider first, then try again. + +You will receive an email notification whenever a sign-in method is linked to or unlinked from your account. + +### Migrating an organisation to enforced SSO + +If your organisation plans to [enforce SSO](/access-control/authentication/sso#enforce-sso), have every member link the new provider from their Account page **before** enforcement is switched on. Members who have not linked the organisation's provider cannot sign in to the organisation after enforcement. Admins can track linking progress in the organisation's audit log. Each link creates a member audit event. + +### Unlinking a sign-in method + +Hover the card of a linked identity, click **Unlink**, and confirm. You can no longer sign in with that identity afterwards. Unlinking is blocked when: + +- It is your **only** sign-in method (a password counts as a method when password authentication is enabled on the instance). +- The identity belongs to an organisation SSO provider that is currently **enforced** for an organisation you are a member of. +- Your membership is **SCIM-provisioned**. Your identity provider is the source of truth for your access. + +## Display name + +Your name and profile picture are initially taken from the identity provider you first signed up with. To set a custom display name, click the pencil icon next to your name on the Account page. A custom name takes precedence over provider-reported names and is used in emails and member lists. It survives unlinking the identity it originally came from. + +## Changing your email address + +Your account email is used for sign-in identification, notifications, and organisation invites. To change it: + +1. Click the pencil icon next to your email address on the Account page. +2. Enter the new address. Phase sends a verification code to it. The code is valid for 15 minutes. +3. Enter the code, along with your password (or sudo password if your account has no login password), to confirm the change. + +The new address does not need to match a linked sign-in identity. An address already used by another account is refused. On self-hosted instances with an [email domain allowlist](/self-hosting/configuration/envars), the new address must be in the allowlist. A security alert is sent to your **old** address whenever the change completes. + + +Your account email is a cryptographic input to your local device key. Confirming the change therefore re-encrypts your account keyrings for **all** of your organisations in one step. This is why your password or sudo password is required. Nothing changes about your organisation keys or secrets; only the encrypted wrapper is rotated. + + +Email changes are not available for SCIM-provisioned accounts, where the identity provider manages the email address. + +On self-hosted instances without an [email gateway](/self-hosting/configuration/envars#email-gateway-configuration) configured (or with `SKIP_EMAIL_VERIFICATION` set), the verification code step is skipped, the same convention as password signup. + +## Deleting your account + +You can permanently delete your Phase account from the **Delete account** section on the Account page. Deletion is immediate and irreversible: your organisation memberships, encryption keys, personal access tokens, and personal data are permanently removed. + +Deletion is blocked while: + +- You are the **only owner** of an organisation. [Transfer ownership](/console/organisation) to another member first. Organisations with another owner do not block deletion. +- Your account is **SCIM-provisioned** in any organisation. Ask your administrator to deprovision you from the identity provider instead. + +On self-hosted instances, accounts with Django staff or superuser access cannot be deleted from the Console. + +When deletion completes, Phase sends a confirmation email to the deleted address. + +To confirm deletion, type your email address into the confirmation dialog. + + +Organisation audit logs are preserved for compliance. Events you performed remain in your organisations' logs, with the actor shown as *"Deleted account"*. Your account and its personal data are removed. Audit records can still contain identifying fields captured at the time of each event. + + +Any active dynamic secret leases you hold are revoked at the provider before your account is removed. Existing service account tokens and organisation resources you created (network policies, service tokens) are unaffected: they belong to the organisation, not to you. diff --git a/public/access-control/authentication/mfa.md b/public/access-control/authentication/mfa.md new file mode 100644 index 00000000..3056a56a --- /dev/null +++ b/public/access-control/authentication/mfa.md @@ -0,0 +1,72 @@ +import { Tag } from '@/components/Tag' +import { DocActions } from '@/components/DocActions' + +export const description = 'Protect your Phase account with TOTP-based two-factor authentication.' + +AUTHENTICATION + +# Two-Factor Authentication (2FA) + +Phase supports two-factor authentication using time-based one-time passwords (TOTP) with any standard authenticator app. Once enabled, every Console sign-in to your account (password, OAuth, or SSO) requires a 6-digit code from your authenticator in addition to your primary sign-in method. + + + + +Two-factor authentication protects **Console sign-in** only. Personal access tokens, service tokens, and CLI, API, and SDK access are not affected: existing and new tokens keep working without a code. + + +## Enable 2FA + +1. Open the user menu in the top right corner of the Console and click your profile card to open the [Account page](/access-control/authentication/account). +2. Under **Two-factor authentication**, click **Enable**. You may be asked to confirm it's you first: sensitive account changes require a recent session. You are returned to setup after signing in again. +3. Scan the QR code with your authenticator app, or copy the setup secret shown below the QR code and add it manually. + + ![2FA setup: scan the QR code or copy the secret](/assets/images/auth/account/totp-setup-1.png) + +4. Enter the 6-digit code from your app to confirm. 2FA is only activated once a code has been verified. + + ![2FA setup: confirm with a 6-digit code](/assets/images/auth/account/totp-setup-2.png) + +5. Save your **recovery codes**: reveal, copy, or download them before finishing. They are shown only once. + +Once enabled, the Account page shows the TOTP status and your remaining recovery codes. + +![TOTP enabled on the Account page](/assets/images/auth/account/totp-enabled.png) + +Phase sends you an email notification when 2FA is enabled, when it is disabled, and when you regenerate your recovery codes. + +## Signing in with 2FA + +After your primary sign-in method succeeds (entering your password, or completing the OAuth/SSO round trip), Phase prompts for a 6-digit code from your authenticator app. The code is accepted with a small clock-skew tolerance (one 30-second step in either direction), and each code can only be used once. + +2FA applies uniformly to **all** of your sign-in methods, including organisation-level SSO. If your identity provider also performs its own MFA, you will complete both. Phase does not skip its challenge based on upstream MFA claims. + +Enter the code within 10 minutes of your primary sign-in. After that the challenge expires and you sign in again from the start. + +After 10 incorrect codes, verification is locked until 15 minutes after the first failed attempt. + +## Recovery codes + +When you enable 2FA, Phase generates 10 single-use recovery codes. Each can be used once in place of an authenticator code (including at sign-in via the *Use a recovery code* option) if you lose access to your device. + +- Store them somewhere safe (a password manager or printed copy). They are displayed only at generation time. +- Your remaining code count is shown on the Account page, with a warning when you are running low. +- Regenerate a fresh set at any time from the Account page. Under **Two-factor authentication**, hover the TOTP card and click **Manage**, then **Regenerate recovery codes**. This invalidates all previous codes and requires a current authenticator code or an unused recovery code. + + +Recovery codes protect your **sign-in**, not your encrypted data. Your secrets remain protected by your sudo password and recovery kit. Keep both independently safe. + + +## Disable 2FA + +On the Account page, under **Two-factor authentication**, hover the TOTP card and click **Manage**, then **Disable two-factor authentication**. Enter a current authenticator code or an unused recovery code to confirm. Signing in no longer requires a code afterwards, and your remaining recovery codes are invalidated. + +If you have lost both your authenticator device and your recovery codes, you cannot disable 2FA yourself. Contact your instance administrator (self-hosted) or Phase support (cloud). + +## Security notes + +- TOTP follows RFC 6238 with standard parameters (SHA-1, 6 digits, 30-second period) for maximum authenticator app compatibility. +- The TOTP seed is encrypted at rest with the server's keypair and is only shown once, during setup. +- Replay protection: each accepted code advances a per-account high-water mark, so an intercepted code cannot be used a second time even within its validity window. +- Recovery codes are stored as salted Argon2id hashes; the plaintext is never persisted. +- Brute-force protection: per-account attempt limits are enforced server-side, alongside IP-based rate limiting on the verification endpoint. diff --git a/public/access-control/authentication/oauth-sso.md b/public/access-control/authentication/oauth-sso.md index b91e6c76..f5abc566 100644 --- a/public/access-control/authentication/oauth-sso.md +++ b/public/access-control/authentication/oauth-sso.md @@ -96,10 +96,10 @@ You can find detailed official instructions for setting up SSO with a Google OAu Follow these steps to set up GitHub SSO for your Phase application: -If you are using GitHub Enterprise Server (self-hosted) instance, you may follow the steps below to set up GitHub SSO for your Phase application as the instructions are nearly identical. The only exception being the Authorization callback URL. +If you are using a GitHub Enterprise Server (self-hosted) instance, you may follow the steps below to set up GitHub SSO for your Phase application as the instructions are nearly identical. The only exception being the Authorization callback URL. - GitHub Enterprise Server (self-hosted) instance for OAuth SSO is only available for organizations with an `Enterprise` tier subscription. See [Pricing](https://phase.dev/pricing). + A GitHub Enterprise Server (self-hosted) instance for OAuth SSO is only available for organizations with an `Enterprise` tier subscription. See [Pricing](https://phase.dev/pricing). 1. Log in to your GitHub account and go to [OAuth Apps](https://github.com/settings/applications/new) in Developer Settings. @@ -185,7 +185,7 @@ Make sure the application has the `read_user` scope. This grants read-only acces 6. Supply these credentials to your Phase Console deployment as [environment variables](/self-hosting/configuration/envars#git-lab-sso). - You can use user-owned or group-owned applications to login to Phase. If you are running a self-hosted instance, you can also use an instance-wide application. + You can use user-owned or group-owned applications to log in to Phase. If you are running a self-hosted instance, you can also use an instance-wide application. You can find detailed official instructions for setting up SSO with a GitLab OAuth Application [here](https://docs.gitlab.com/ee/integration/oauth_provider.html). diff --git a/public/access-control/authentication/oidc-sso.md b/public/access-control/authentication/oidc-sso.md index 52c3ddfa..3f6765ff 100644 --- a/public/access-control/authentication/oidc-sso.md +++ b/public/access-control/authentication/oidc-sso.md @@ -78,7 +78,7 @@ Follow these steps to set up Google SSO for your Phase application: 14. In the Application type dropdown, select **Web application**. Enter a recognizable name in the **Name** field, add the **Authorized redirect URI** (e.g., https://[**YOUR_DOMAIN**].com/api/auth/callback/google-oidc), and click **CREATE**. - You can copy the following path, please make sure to pre-fix it with scheme + your domain. + You can copy the following path, please make sure to prefix it with scheme + your domain. ``` /api/auth/callback/google-oidc @@ -129,7 +129,7 @@ You can use JumpCloud as an OIDC provider to set up SSO for your Phase instance. 8. Add your Phase application's **Redirect URI** (e.g., https://[**YOUR_DOMAIN**].com/api/auth/callback/jumpcloud-oidc) and **Login URL**. - You can copy the following path, please make sure to pre-fix it with scheme + your domain. + You can copy the following path, please make sure to prefix it with scheme + your domain. ``` /api/auth/callback/jumpcloud-oidc @@ -141,7 +141,7 @@ You can use JumpCloud as an OIDC provider to set up SSO for your Phase instance. ![Select Standard Scopes](/assets/images/auth/sso/oidc/jumpcloud/9-select-email-profile-from-standard-scope.png) -10. Click the **Activate** button at the bottom right of screen to enable the application. +10. Click the **Activate** button at the bottom right of the screen to enable the application. ![Activate Application](/assets/images/auth/sso/oidc/jumpcloud/10-click-activate.png) @@ -367,6 +367,10 @@ You can use Okta as an OIDC provider to set up SSO for your Phase instance. Foll ![Copy Okta OIDC Issuer Host](/assets/images/auth/sso/oidc/okta/7-copy-okta-oidc-issuer-host.png) + + From inside the Okta admin console, the drop-down can show the admin host (`…-admin.okta.com`). Remove the `-admin` suffix: the issuer is the org domain. Okta issues tokens under the org domain, and Phase rejects an admin-host issuer at save time. + + You now have the three values needed to configure Phase — **Issuer URL**, **Client ID**, and **Client Secret**. See the **Per-organisation** / **Instance-wide** tabs below for where to plug them in. diff --git a/public/access-control/authentication/password.md b/public/access-control/authentication/password.md index 926b0a79..55aaea6d 100644 --- a/public/access-control/authentication/password.md +++ b/public/access-control/authentication/password.md @@ -27,9 +27,11 @@ Phase uses an email-first login flow. Enter your email address, and the system w - If your account uses a password, you will be prompted to enter it. - If your organisation uses SSO, you will be redirected to your identity provider. +If [two-factor authentication](/access-control/authentication/mfa) is enabled on your account, you will also be prompted for a code from your authenticator app. Your email address and other sign-in settings can be managed from the [Account page](/access-control/authentication/account). + ## Password change -You can change your password from **Settings > Account**. Changing your password re-encrypts all organisation keyrings to ensure continued end-to-end encryption with your new credentials. +You can change your password from **Settings > Account & Security** in any of your organisations. Changing your password re-encrypts all organisation keyrings to ensure continued end-to-end encryption with your new credentials. ## Account recovery diff --git a/public/access-control/authentication/sso.md b/public/access-control/authentication/sso.md index 67d96207..c761b634 100644 --- a/public/access-control/authentication/sso.md +++ b/public/access-control/authentication/sso.md @@ -28,7 +28,11 @@ Administrators can configure a Single Sign-On provider for their organisation di **Entra ID:** register an application in the [Azure Portal](https://portal.azure.com) under *Microsoft Entra ID → App registrations*. Note the **Tenant ID**, **Application (client) ID**, and generate a new **Client secret**. - **Okta:** create an OIDC *Web Application* in your Okta admin console. Note the **Issuer URL** (your Okta domain, e.g. `https://dev-12345.okta.com`), **Client ID**, and **Client secret**. + **Okta:** create an OIDC *Web Application* in your Okta admin console. Note the **Issuer URL** (your Okta org domain, e.g. `https://dev-12345.okta.com`), **Client ID**, and **Client secret**. + + + Use the org domain, not the admin console domain (`…-admin.okta.com`). Okta issues tokens under the org domain, so an admin-domain issuer fails every sign-in. Phase rejects it at save time. + 5. Return to the Console and fill in: @@ -39,7 +43,7 @@ Administrators can configure a Single Sign-On provider for their organisation di ![Entra ID setup dialog — filled](/assets/images/auth/sso/org/03-entra-setup-dialog-filled.png) -6. Click **Save**. The provider is created but not yet active. +6. Click **Save**. Phase fetches the provider's OIDC discovery document and makes sure the configured issuer matches the value the provider reports. If they do not match, the save is rejected and the error shows the correct value to use. The provider is created but not yet active. ![Provider card — saved but inactive](/assets/images/auth/sso/org/04-provider-card-saved.png) @@ -70,6 +74,10 @@ A successful round-trip brings you back to the SSO settings page. Enforcing SSO disables password login for all members of the organisation and requires every sign-in to go through the configured provider. + +Before enforcing, make sure every member can actually sign in through the provider. Members who joined with a different method (for example Google OAuth or a password) must [link the organisation's SSO identity](/access-control/authentication/account#sign-in-methods) from their Account page first. Phase never automatically attaches a new sign-in identity to an existing account based on a matching email. You can track linking progress in the organisation's audit log. + + 1. Click **Enforce SSO**. A confirmation dialog appears. ![Enforce SSO dialog — acknowledgement unchecked](/assets/images/auth/sso/org/08-enforce-sso-dialog-unchecked.png) @@ -87,6 +95,10 @@ If your current session was established via the organisation's SSO provider, enf Other members' existing sessions remain active for open tabs but will be rejected on the next request. They will be redirected to the lobby where a *"Sign in with provider name"* prompt appears next to the enforced organisation. +### Inviting users to an enforced organisation + +New users can sign up and accept their invite entirely through the organisation's SSO provider. Invited users who already have a Phase account follow a one-time bootstrap. Invite **acceptance** is exempt from SSO enforcement: they sign in with their existing method, accept the invite, and become a member. If their identity for the organisation's provider is already linked, the organisation's SSO works immediately after they join. If not, they [link it from their Account page](/access-control/authentication/account#sign-in-methods) first. All other organisation access still requires the organisation's SSO session. + ![Lobby — organisation locked behind SSO](/assets/images/auth/sso/org/15-lobby-sso-lockout.png) ### Disable enforcement diff --git a/public/access-control/external-identities.md b/public/access-control/external-identities.md index ec54eb39..b4e959c6 100644 --- a/public/access-control/external-identities.md +++ b/public/access-control/external-identities.md @@ -52,7 +52,7 @@ Benefits: ## Prerequisites - Server-side encryption (SSE) enabled for the Service Account you want to use the External Identity with. -- A third-party platform or service that supported by Phase +- A third-party platform or service that is supported by Phase ## Supported External Identity Providers Phase currently supports the following external identity providers: @@ -97,7 +97,7 @@ For AWS IAM, you will need to provide the following information: The ARN(s) of the AWS IAM User(s) to bind to the Phase Service Account. Separate multiple ARNs with commas. - The duration (in seconds) for which the signed requests from the AWS IAM User will be valid. Default is 60 seconds. Lower the better. This is to protect against replay attacks. + The duration (in seconds) for which the signed requests from the AWS IAM User will be valid. Default is 60 seconds. The lower the better. This is to protect against replay attacks. Optionally, specify a custom AWS STS endpoint. If not provided, the default AWS STS endpoint will be used (`https://sts.amazonaws.com`). @@ -172,7 +172,7 @@ Once an External Identity is created, it will appear in the list on the **Extern To use an External Identity, the Service Account must have [Server-side KMS](/access-control/service-accounts#server-side-kms) enabled. -Once you have configured an External Identity, you can bind it to a Phase Service Account. To do this, navigate to the **Service Accounts** page, select the desired Service Account and click **Mange** to open the account detail page. Scroll down to the **External Identities** section and click **Manage External Identities**: +Once you have configured an External Identity, you can bind it to a Phase Service Account. To do this, navigate to the **Service Accounts** page, select the desired Service Account and click **Manage** to open the account detail page. Scroll down to the **External Identities** section and click **Manage External Identities**: ![manage external identities button](/assets/images/console/access-control/external-identities/manage-account-identities-button.png) diff --git a/public/access-control/network.md b/public/access-control/network.md index 84746ed5..7dfae13f 100644 --- a/public/access-control/network.md +++ b/public/access-control/network.md @@ -5,7 +5,7 @@ import { DocActions } from '@/components/DocActions' # Network -You can control access to resources in Phase from specific IPv4 or IPv6 sources by defining individual IPs or CIDR ranges in a Network Access Policy. You may attach such Network Access Policy to a User and/or Service Accounts individually or enforce it across your entire organization via a Global Policy. This allows you to put an additional layer of security on top of the existing access control mechanisms, by making sure that a client can only gain access to resources in Phase via mediums and/or assets such as the Phase Console, CLI, SDKs, Kubernetes Operator, REST API, etc. while being in the confines of your network. +You can control access to resources in Phase from specific IPv4 or IPv6 sources by defining individual IPs or CIDR ranges in a Network Access Policy. You may attach such a Network Access Policy to a User and/or Service Accounts individually or enforce it across your entire organization via a Global Policy. This allows you to put an additional layer of security on top of the existing access control mechanisms, by making sure that a client can only gain access to resources in Phase via mediums and/or assets such as the Phase Console, CLI, SDKs, Kubernetes Operator, REST API, etc. while being in the confines of your network. diff --git a/public/access-control/roles.md b/public/access-control/roles.md index 559cd900..ffb44750 100644 --- a/public/access-control/roles.md +++ b/public/access-control/roles.md @@ -260,7 +260,7 @@ Alternatively, you may provision a custom access policy by toggling switches in ### Resource Permissions Cheat Sheet -Some actions require a combination of permissions across multiple resources. Below is a list of common actions that require a combination of two of more permissions: +Some actions require a combination of permissions across multiple resources. Below is a list of common actions that require a combination of two or more permissions: - To update the role of a user in your Organization: - `Members:update` @@ -272,7 +272,7 @@ Some actions require a combination of permissions across multiple resources. Bel - Updating the third party integration credentials used for a given integration in an App: - `Integrations:update` - `IntegrationCredentials:read` -- Creating an new third party integration inside of an App +- Creating a new third party integration inside of an App - `Integrations:create` - `Environments:read` - Creating a new Service Token: @@ -282,7 +282,7 @@ Some actions require a combination of permissions across multiple resources. Bel - `EncryptionMode:update` - `Environments:read` - Access to all environments in the App (only to enable SSE) -- To view and delete other users Personal Access Tokens: +- To view and delete other users' Personal Access Tokens: - `MemberPersonalAccessTokens:read` - `MemberPersonalAccessTokens:delete` - Adding or removing a Team's access to an App: diff --git a/public/access-control/service-accounts.md b/public/access-control/service-accounts.md index 389b35b9..4f415b99 100644 --- a/public/access-control/service-accounts.md +++ b/public/access-control/service-accounts.md @@ -5,7 +5,7 @@ import { DocActions } from '@/components/DocActions' # Service Accounts -Service Accounts provide a secure and controlled method for programmatic access to the Phase platform. Service accounts are non-human users that can use various authentication mechanisms to access resources such as secrets within the applications and environments it has been granted access to. +Service Accounts provide a secure and controlled method for programmatic access to the Phase platform. Service accounts are non-human users that can use various authentication mechanisms to access resources such as secrets within the applications and environments they have been granted access to. 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. @@ -24,13 +24,13 @@ Team-owned service accounts are useful when a team needs dedicated programmatic To create a new Service Account: -1. Navigate to Access Control page from the sidebar and click on the **Service Accounts** tab. +1. Navigate to the Access Control page from the sidebar and click on the **Service Accounts** tab. ![Navigate to access control](/assets/images/console/access-control/service-accounts/create-new-service-accounts/1-navigate-to-access-control.png) ![Click on service accounts tab](/assets/images/console/access-control/service-accounts/create-new-service-accounts/2-click-on-service-accounts-tab.png) -2. Click the **Create Service Account** button in the center of the screen, if you have previously created service accounts you will see in the top right corner of the screen. +2. Click the **Create Service Account** button in the center of the screen, if you have previously created service accounts you will see it in the top right corner of the screen. ![Click create service account](/assets/images/console/access-control/service-accounts/create-new-service-accounts/3-click-create-new-service-account.png) @@ -44,7 +44,7 @@ By default, when you create a new Service Account it uses the [Service](/access- |----------|--------|------|--------|--------|--------| | **Secrets** | Full access | ✅ | ✅ | ✅ | ✅ | -You may choose to select a different Managed role or a Custom role by clicking the one from the dropdown. +You may choose to select a different Managed role or a Custom role by clicking one from the dropdown. ![Create new service account](/assets/images/console/access-control/service-accounts/create-new-service-accounts/4-create-new-service-account.png) @@ -88,7 +88,7 @@ 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, 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. +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 to the service account's keyring, encrypted with their own keys. #### Server-side KMS @@ -115,7 +115,7 @@ You can find instructions on how to create a Service Account Token [here](/acces ## Add a Service Account to an App -You can find instructions on adding Service Account to Apps [here](/console/apps#add-a-service-account-to-an-app). +You can find instructions on adding a Service Account to Apps [here](/console/apps#add-a-service-account-to-an-app). ## Manage account Network Access Policies diff --git a/public/cli.md b/public/cli.md index 38595087..248fb8aa 100644 --- a/public/cli.md +++ b/public/cli.md @@ -12,7 +12,7 @@ export const description = The Phase CLI works together with the [Phase Console](https://github.com/phasehq/console) to bring end-to-end encrypted secret management to your command line. {{ className: 'lead' }} -The CLI fetches, decrypts, and injects secrets into your applications during runtime. You can manage secrets across all environment, use personal secret-overrides, resolve references and much more. +The CLI fetches, decrypts, and injects secrets into your applications during runtime. You can manage secrets across all environments, use personal secret-overrides, resolve references and much more. diff --git a/public/cli/commands.md b/public/cli/commands.md index 079edc7e..33446a1c 100644 --- a/public/cli/commands.md +++ b/public/cli/commands.md @@ -87,7 +87,7 @@ To view all available commands and their descriptions, run: Authenticate with Phase using the CLI on your own machine. The `phase auth` command lets you log in to either Phase Cloud or a Self-hosted instance of Phase. -Phase CLI will automatically look for `PHASE_HOST` and or `PHASE_SERVICE_TOKEN` environment variables to authenticate with the Phase Service. If any are present, this will override any authentication medum previously chosen. +Phase CLI will automatically look for `PHASE_HOST` and/or `PHASE_SERVICE_TOKEN` environment variables to authenticate with the Phase Service. If any are present, this will override any authentication medium previously chosen. For more details, see [Environment Variables](commands#environment-variables). @@ -110,7 +110,7 @@ Please authenticate via the Phase Console: https://console.phase.dev/webauth/OTM This opens the Phase Console in a new tab. Enter your `sudo` password when prompted. The CLI securely receives your credentials via encrypted POST requests to finalize authentication. If you are already authenticated, it will display your email address and provide instructions for switching accounts. -2. **Token**: This allows you to authenticate to Phase directly uisng a Personal Access Token (PAT) or a Service Account Token that you may have manually created in the Phase Console. +2. **Token**: This allows you to authenticate to Phase directly using a Personal Access Token (PAT) or a Service Account Token that you may have manually created in the Phase Console. For `token` mode, provide the following: @@ -207,7 +207,7 @@ Examples: ## 🔗 `init` -Link your local application or project to your Phase app. The `phase init` command creates a `.phase.json` file in the root of your projects which holds important contexts for the `phase` cli, so you don't have to pass arguments repetitively. This file does not contain any sensitive information and can be check into your git repo. +Link your local application or project to your Phase app. The `phase init` command creates a `.phase.json` file in the root of your projects which holds important contexts for the `phase` cli, so you don't have to pass arguments repetitively. This file does not contain any sensitive information and can be checked into your git repo. Usage: @@ -293,7 +293,7 @@ Usage: > phase run [--env ENVIRONMENT] [--app APP_NAME] [--tags TAGS] [command_to_run] ``` -- `command_to_run`: The command you wish to run, such as `yarn dev`. You can also chain multiple command together by wrapping them in double quotes, example: `phase run "printenv | grep secret"` +- `command_to_run`: The command you wish to run, such as `yarn dev`. You can also chain multiple commands together by wrapping them in double quotes, example: `phase run "printenv | grep secret"` - `--env`: (Optional) Specify the environment (e.g., `dev`, `staging`, `production`). Supports partial string matching eg. `prod` for `production` Default is `development` - `--path`: (Optional) Specific path under which to fetch secrets from and inject into your application. Default is '/'. Pass an empty string `""` to fetch secrets from all paths. - `--app`: (Optional) Name of your Phase application. Use this if you don't have a `.phase.json` file in your project directory or want to override it. @@ -344,7 +344,7 @@ Chaining multiple commands: **Additional Notes**: -- The `phase run` only exposes secrets to your applications runtime and not to the rest of your system for security reasons. +- The `phase run` only exposes secrets to your application's runtime and not to the rest of your system for security reasons. - When specifying tags with `--tags`, only secrets matching these tags will be injected into the environment. - Cross-environment and local references in secrets are automatically resolved and injected. Warnings are issued if any references cannot be resolved. - Errors during the command execution or secret fetching process will result in an appropriate error message and termination of the process. @@ -482,7 +482,7 @@ Usage: - `KEY`: One or more keys to fetch. Single key returns a JSON object; multiple keys returns a JSON array. - `--env`: (Optional) Specify the environment in which to search for the secret. -- `--path`: (Optional) The path from which to fetch the secret from. Default is '/' +- `--path`: (Optional) The path from which to fetch the secret. Default is '/' - `--app`: (Optional) Name of your Phase application. Use this option to override the `.phase.json` file in your project directory or when it's not present. - `--app-id`: (Optional) ID of your Phase application. Takes precedence over `--app` if both are provided. - `--tags`: (Optional) Comma-separated list of tags to filter secrets. @@ -1383,7 +1383,7 @@ DATABASE_URL | 🌐 postgresql://${dev.DB_USER}:${dev.DB_PASSWORD}@ DATABASE_URL=postgresql://j_mclaren:6c37810ec6e74ec3228416d2844564fceb99ebd94b29f4334c244db011630b0e@mc-laren-prod-db.c9ufzjtplsaq.us-west-1.rds.amazonaws.com:5432/XP1_LM ``` -**Note**: This is assuming an environment named dev/development exists and has a secrets with the keys `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`. +**Note**: This is assuming an environment named dev/development exists and has secrets with the keys `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`. --- @@ -1456,7 +1456,7 @@ To use offline mode with a service account, authenticate first: ### Wrapped key share -Offline decryption requires a wrapped key share, which is stored locally after authentication. If you authenticated before this feature was available, simply re-run `phase auth` to store it****.**** +Offline decryption requires a wrapped key share, which is stored locally after authentication. If you authenticated before this feature was available, simply re-run `phase auth` to store it. --- @@ -1493,7 +1493,7 @@ Example: Type: String -Description: A way to authenticate with the Phase Service via tokens, useful for running the cli in an headless environment like CI/CD, Docker containers etc. +Description: A way to authenticate with the Phase Service via tokens, useful for running the cli in a headless environment like CI/CD, Docker containers etc. Example: @@ -1510,7 +1510,7 @@ Type: Boolean Description: A way to temporarily disable TLS certificate verification checks -Note: Disable TLS certificate verification is dangerous and can expose you to risks of [MITM](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) attacks. +Note: Disabling TLS certificate verification is dangerous and can expose you to risks of [MITM](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) attacks. Example: diff --git a/public/console/dynamic-secrets.md b/public/console/dynamic-secrets.md index 47d59b66..98606d2a 100644 --- a/public/console/dynamic-secrets.md +++ b/public/console/dynamic-secrets.md @@ -18,7 +18,7 @@ Dynamic Secrets can be created manually or automatically through integrations wi ## Supported Providers -Dynamic Secrets are support for the following providers: +Dynamic Secrets are supported for the following providers: - [AWS IAM](/integrations/platforms/aws-iam) @@ -33,13 +33,13 @@ You need to Enable Server-side Encryption (SSE) for the App from the [Settings]( ![create dynamic secret button](/assets/images/console/dynamic-secrets/create-dynamic-secret-button.png) -Choose a provider, and then fill in the required fields. The required configuration will vary for each provider, but all dynamic secrets will required: +Choose a provider, and then fill in the required fields. The required configuration will vary for each provider, but all dynamic secrets will require: - **Secret Name**: A unique name for the secret. - **Description**: A brief description of the secret. - **Max TTL**: The maximum time-to-live for the secret. This is the maximum duration that the credentials can be leased or renewed for. - **Default TTL**: The default time-to-live for the secret. This is the default duration that the credentials will be leased for when they are created. This value must be less than or equal to the Max TTL. -- **Outputs**: This is a mapping of secrets or credentials created on the third-party service, and how they will be mapped to secrets in your Phase Environment.. These fields will vary depending on the provider. +- **Outputs**: This is a mapping of secrets or credentials created on the third-party service, and how they will be mapped to secrets in your Phase Environment. These fields will vary depending on the provider. ![common config](/assets/images/console/dynamic-secrets/common-config.png) @@ -52,7 +52,7 @@ Finally, click **Finish** to save your configuration and create the Dynamic Secr ## Leasing credentials -To lease credentials for a Dynamic Secret, click on the **Generate* button for the secret. Provide a name for the lease, a TTL in seconds, and click "Generate". The TTL must be less than or equal to the Max TTL specified in the Dynamic Secret configuration. +To lease credentials for a Dynamic Secret, click on the **Generate** button for the secret. Provide a name for the lease, a TTL in seconds, and click "Generate". The TTL must be less than or equal to the Max TTL specified in the Dynamic Secret configuration. ![generate lease 1](/assets/images/console/dynamic-secrets/generate-lease-1.png) @@ -96,7 +96,7 @@ To renew a lease, click on the **Renew** button next to the lease in the list. P ![renew lease](/assets/images/console/dynamic-secrets/renew-lease.png) -### Revoke a Leases +### Revoke a Lease To revoke a lease, click on the **Revoke** button next to the lease in the list. Confirm the revocation in the dialog that appears. This will immediately delete the credentials associated with the lease and mark the lease as revoked. diff --git a/public/console/logstreams.md b/public/console/logstreams.md new file mode 100644 index 00000000..01772404 --- /dev/null +++ b/public/console/logstreams.md @@ -0,0 +1,304 @@ +import { Tag } from '@/components/Tag' +import { DocActions } from '@/components/DocActions' + +export const description = 'Stream organisation audit logs and secret events from Phase to your SIEM or log management platform in near real-time.' + +CONSOLE + +# Log Streams + +Log Streams continuously ship organisation audit logs and secret events from Phase to an external log management platform or SIEM for monitoring, alerting and threat detection. Streams are configured under **Integrations** → **Log Streams**, deliver in near real-time, and expose a per-delivery history with manual retry for anything that fails. Log Streams are available on the **Enterprise** tier. + + + + + Log Streams ship **metadata only**. Secret values, keys and comments are + end-to-end encrypted and never leave Phase. + + +## How it works + +- Phase **pushes** events to your destination — no inbound access, agents or polling required. A background engine sweeps every 30 seconds and ships new events in ordered chunks. +- Delivery is **at-least-once**: a stream's position (cursor) only advances after the destination accepts a chunk, or after a failed chunk's exact range is durably recorded as re-shippable — so a transient failure can never silently lose an event, but an event can occasionally be delivered twice. Deduplicate on `event.id`, a stable UUID that is identical across redeliveries. +- Each stream selects its own **event sources** and destination credentials. You can run multiple streams side by side — each keeps independent cursors, so they never interfere. +- Streams are **ship-forward only**: a new stream begins delivering from the moment it is created and does not backfill older events. This is a destination-side restriction — log platforms cap how far in the past an ingested event's timestamp may be (Datadog silently discards anything older than **18 hours**, even when the request is accepted), so backfilling meaningful history over the live intake isn't possible. A dedicated export feature for historical logs — archiving to S3 in a format compatible with [Datadog Log Rehydration](https://docs.datadoghq.com/logs/log_configuration/rehydrating/) — is coming in a future release. +- Changes to streams (create, update, pause, resume, delete, retries) are recorded in the organisation audit log under **Logs** → **Log Streams** — and, like any other audit event, they export through the stream itself. + +### Requirements + +- A Phase organisation on the **Enterprise** tier, or a self-hosted instance with an activated license. +- The `LogStreams` permission in your organisation role, plus **global access** — streams export activity across the whole organisation (Owner and Admin roles qualify by default). + +### Event sources + +- **Organisation audit events**: organisation-level activity — apps, environments, members, roles, service accounts, tokens, network policies and teams. +- **Secret events**: create, read, update and delete events for secrets across all apps. + +## Exported events + +Every event is a structured JSON envelope (`schema_version: 1`) aligned with OpenTelemetry semantic conventions. `event.category` is `secrets` or `org_audit`; `event.type` is one of `create`, `read`, `update`, `delete` or `access`. The `actor` block identifies who acted (a `user`, `service_account` with its token, `service_token`, or `phase` for system actions), and `phase.description` carries a human-readable summary of every event. + +Secret events carry a `phase.secret` block (id, path, version, type — never the name or value). Organisation audit events instead carry a `phase.resource` block with a readable `type` slug (e.g. `app`, `environment`, `member`, `invite`, `role`, `service_account_token`, `rotating_secret`, `network_access_policy`, `log_stream`), the resource `id` and `metadata`, plus `old_values` / `new_values` for changes. + +The example below is shown as it lands in **Datadog**: the `usr`, `network`, `http`, `ddsource`, `service` and `ddtags` fields are Datadog standard-attribute remappings of the neutral envelope's `user`, `client` and `user_agent` blocks, added by the Datadog adapter at delivery time. + +```json +{ + "schema_version": 1, + "event": { "id": "…", "category": "secrets", "type": "read" }, + "timestamp": "2026-07-30T12:00:00+00:00", + "actor": { "type": "service_account", "id": "…", "name": "ci-deploy", "token": { "name": "gh-actions" } }, + "usr": { "id": "…", "name": "Dev Eloper", "email": "dev@example.com" }, + "network": { "client": { "ip": "203.0.113.7" } }, + "http": { "useragent": "phase-cli/1.18" }, + "phase": { + "organisation": { "id": "…", "name": "acme" }, + "app": { "id": "…", "name": "backend" }, + "environment": { "id": "…", "name": "Production", "type": "PROD" }, + "secret": { "id": "…", "path": "/api/payments", "version": 3, "type": "SECRET" }, + "description": "Secret read in backend / Production by ci-deploy" + }, + "ddsource": "phase", + "service": "phase-console", + "ddtags": "phase_org:acme,phase_stream:datadog-prod" +} +``` + +To pivot from an exported secret event back to Phase, copy the `phase.secret.id` and paste it into the Console's global search (⌘K) — it resolves directly to the secret's app, environment and path. + +## Delivery guarantees + +- **At-least-once delivery.** Events ship in ordered chunks (up to 500 per request), and a stream's cursor only advances after the destination accepts the chunk, or after a failed chunk's exact range is recorded as a re-shippable failure — a transient failure can therefore never silently lose an event, but one can occasionally be delivered twice (for example, if a network timeout hides a successful ingestion). **Deduplicate on `event.id`**. +- **Near real-time.** Streams are swept every 30 seconds; a healthy stream delivers new events within about a minute. +- **Ordering.** Events ship in `(timestamp, id)` order per source. Manual re-ships of failed ranges arrive later than newer events — order by the event's own `timestamp` in queries, not ingestion time. +- **Delivery status.** Each stream shows a per-source delivery delay ("Up to date", "26 minutes behind" — the age of the oldest event still waiting to ship). A **Delayed** status means events are queued but deliveries are running late; on self-hosted instances, persistent delay usually means the worker service is down or the pool needs more capacity (see [Self-hosting](#self-hosting)). + +### When a delivery fails + +1. The chunk is retried with exponential backoff, honouring the destination's `Retry-After`, up to the stream's configured **retry attempts** (1–10, default 5). +2. If retries are exhausted, the chunk is recorded as **failed** with its exact event time range, the stream is marked **degraded**, and shipping continues with newer events — one bad chunk never blocks the stream. +3. If a later successful delivery covers a failed range (for example after an authentication recovery), the failure is **auto-resolved**. +4. Anything still unresolved appears under the **out of sync** badge on the stream card. Click through to the filtered event history and press **Retry** on a row to re-ship exactly that range. Once a range falls fully outside the destination's ingestion window, the retry is refused — the destination would accept and silently discard the events, falsely marking the range recovered. Expired rows are auto-resolved as **Expired** after a grace period, and the events remain queryable in the Console. If only the older part of a range has expired, a retry ships the still-live tail and records the expired part as **skipped**. +5. **Authentication failures** skip retries entirely and pause the stream (retrying with a dead key is pointless). Fix the credentials, press **Resume**, and shipping continues from the stored cursor with no gap. +6. **Deleting the stream's third-party credentials** also pauses it — a stream without credentials can never deliver, so it is paused visibly rather than left looking healthy. Select new credentials in the stream's configuration, save, and resume. + +### Backfilling missed events + +Backfilling covers ranges a stream failed to deliver while active. It does not extend to events from before the stream was created — streams are [ship-forward only](#how-it-works). Events always remain in Phase regardless of delivery outcome: + +1. For ranges within the destination's ingestion window: use the **Retry** button on the failed row — no other steps needed. +2. Ranges that have fallen outside the ingestion window can no longer be re-shipped — the destination would silently discard them. The events remain queryable in the Console: organisation audit events under **Logs**, and secret events in each app's **Logs** tab. + +## Managing streams + +- **Pause / Resume**: pausing stops all egress; resuming continues from the stored cursor with no gap (subject to the destination's ingestion window). + + ![Log stream configuration tab with status, pause control and event source toggles](/assets/images/console/log-streams/log-stream-config.png) + +- **Events tab**: every delivery is recorded — `Completed`, `Failed` or `Skipped` — with its event count, attempts, exact time range and error detail. Failed rows stay listed until they are resolved by a successful re-ship, and can be retried individually. Skipped rows record ranges that fell outside the destination's ingestion window — they cannot be re-shipped and auto-resolve as **Expired**. + + ![Events tab showing the delivery history with status filters](/assets/images/console/log-streams/log-stream-events.png) + +- **Stream options**: a `service` name for the destination (default `phase-console`), free-form tags, and the per-chunk retry limit. + +## Datadog + +Stream logs to [Datadog](https://www.datadoghq.com/) for monitoring, alerting and Cloud SIEM detection. Works with all Datadog site regions (US1, US3, US5, EU1, UK1, AP1, AP2, US1-FED and US2-FED). + +### Step 1: Create a Datadog API key + +1. Log in to Datadog and go to **Organization Settings** → **API Keys**. + + ![Datadog API Keys page with the New Key button](/assets/images/console/log-streams/datadog-new-key-button.png) + +2. Click **+ New Key** and name it, e.g. `phase-log-stream`. + + ![Datadog New API Key dialog with the key named phase-log-stream](/assets/images/console/log-streams/datadog-new-key-name.png) + +3. Copy the key value. + + ![Created Datadog API key with the Copy button](/assets/images/console/log-streams/datadog-new-key-created.png) + +Note: API keys are the right credential for log shipping: they are org-level, intake-only by design (they can submit data but cannot read or manage anything), cannot be scoped further, and [remain valid even if the user who created them is later disabled](https://docs.datadoghq.com/account_management/api-app-keys/). + +4. Note your Datadog **site** — you can see it in your browser's address bar, e.g. `us3.datadoghq.com`, `datadoghq.com`, or `datadoghq.eu`. + +### Step 2: Add Datadog credentials to Phase + +1. In the Phase Console, go to **Integrations** → **Third-party credentials** and click **+ Add credentials**. + + ![Third-party credentials tab with the Add credentials button](/assets/images/console/log-streams/create-new-cred-button.png) + +2. Select the **Datadog** card. + + ![Create new service credentials dialog with the Datadog card](/assets/images/console/log-streams/create-new-cred-datadog-1.png) + +3. Enter your **API key** and pick your **site** from the region dropdown. The optional **application key** is not required for log streaming. +4. Give the credentials a descriptive name and save. + + ![Datadog credential form with API key, site region and name](/assets/images/console/log-streams/create-new-cred-datadog-2.png) + +### Step 3: Create a Log Stream + +1. Go to **Integrations** → **Log Streams** and click **Create a Log Stream**. + + ![Log Streams tab with the Create a Log Stream button](/assets/images/console/log-streams/create-a-log-stream-button.png) + +2. Select **Datadog**, then your Datadog credentials. +3. Choose the event sources to ship. +4. Optionally configure the Datadog `service` name, additional tags and the per-chunk retry limit. Tag values are sanitised to Datadog's tag rules (lowercased, spaces and special characters become underscores). +5. Click **Test connection** to validate the API key against Datadog's key-validation endpoint (no log data is written), then **Create**. + + ![Create a Log Stream dialog with credentials, event sources and Datadog destination options](/assets/images/console/log-streams/create-a-log-stream-dialog.png) + +The new stream appears with its health status, per-source delivery state and a deep link to the shipped logs in Datadog: + +![Log stream card showing per-source delivery status and the Explore logs in Datadog link](/assets/images/console/log-streams/log-stream-card.png) + +Events will appear in the Datadog **Log Explorer** under `source:phase` within about a minute. Example events as they land in Datadog: + + + +```json {{ title: 'App secret audit log' }} +// A user read a secret via the REST API using curl +{ + "actor": { + "id": "4b238ce5-f367-4542-b9b9-d839c89e6a33", + "name": "Nimish", // 👈 User + "type": "user" + }, + "event": { + "category": "secrets", + "id": "e62e3a35-81c2-4c9b-aec4-08fdf49451a2", + "type": "read" + }, + "http": { + "useragent": "curl/8.7.1" // 👈 Client User agent + }, + "network": { + "client": { + "ip": "100.18.54.22" // 👈 User IP address + } + }, + "phase": { + "app": { + "id": "50ed8caa-2643-4c62-887b-1ef7cb8339a8", + "name": "example-app" // 👈 App name + }, + "description": "Secret read in example-app / Development by QA Nimish", + "environment": { + "id": "029cca04-b79f-4146-867e-dcb089a08c16", + "name": "Development", // 👈 Environment + "type": "DEV" + }, + "organisation": { + "id": "b081a3bc-4a72-4744-aa9a-b06fcc057ceb", + "name": "acme" + }, + "secret": { + "id": "861456fc-2b80-422f-9221-a9114584e92d", // 👈 You can look this up in Phase Global Search + "path": "/", + "type": "SECRET", + "version": 1 + } + }, + "schema_version": 1, + "service": "phase-console", + "timestamp": "2026-08-03T14:53:51.820499+00:00", + "usr": { + "email": "nimish@phase.dev", + "id": "4b238ce5-f367-4542-b9b9-d839c89e6a33", + "name": "QA Nimish" + } +} +``` + +```json {{ title: 'Organisation audit event' }} +// A user invited another user +{ + "actor": { + "id": "4b238ce5-f367-4542-b9b9-d839c89e6a33", + "name": "nimish@phase.dev", + "type": "user" + }, + "event": { + "category": "org_audit", + "id": "fae90a38-a459-4c01-9fdb-e7122c6d221e", + "type": "create" + }, + "http": { + "useragent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.7778.280 Safari/537.36" + }, + "network": { + "client": { + "ip": "100.18.54.22" + } + }, + "phase": { + "description": "Invited 'rohan@phase.dev' with role 'Developer'", + "organisation": { + "id": "b081a3bc-4a72-4744-aa9a-b06fcc057ceb", + "name": "acme" + }, + "resource": { + "id": "2b7c7c89-3914-4719-aa26-b005775c423b", + "metadata": { + "email": "rohan@phase.dev", + "role": "Developer" + }, + "type": "invite" + } + }, + "schema_version": 1, + "service": "phase-console", + "timestamp": "2026-08-03T11:33:10.498884+00:00", + "usr": { + "email": "nimish@phase.dev", + "id": "4b238ce5-f367-4542-b9b9-d839c89e6a33", + "name": "nimish@phase.dev" + } +} +``` + + + +### Using the logs in Datadog + +Since Phase ships structured JSON, every field is parsed automatically. IP addresses, user agents and user identity are mapped to Datadog standard attributes (`network.client.ip`, `http.useragent`, `usr.*`) so they light up native facets with no pipeline configuration. Some useful queries: + +```fish +# 👇 Filter for secret read events +source:phase @event.category:secrets @event.type:read + +# 👇 Filter for organisation audit logs of a specific user +source:phase @usr.email:dev@example.com + +# 👇 Filter for logs from a specific client IPv4 network address +source:phase @network.client.ip:203.0.113.7 + +# 👇 Filter secret logs for the Production environment of my backend application +source:phase @phase.app.name:backend @phase.environment.name:Production +``` + +For Cloud SIEM, you can create detection rules over these logs, for example: + +- Secret reads from an IP outside your allowed ranges: `source:phase @event.type:read -@network.client.ip:203.0.113.0/24` +- A service account token created and used within minutes, or mass secret reads from a single actor in a short window. + + + Datadog's intake silently discards events with timestamps older than **18 + hours**. This is why streams cannot backfill historical data from before + they were created, and why a stream that is paused or failing for that long + records the missed range as **skipped** in the delivery history and jumps + the cursor forward. The engine skips shortly *before* the 18-hour mark — + it keeps a ~40-minute safety margin so events admitted for delivery cannot + age past the cutoff mid-flight. The events always remain queryable in + Phase: organisation audit events under **Logs** in the Console, and secret + events in each app's **Logs** tab. + + +## Self-hosting + +- Log shipping runs on a dedicated `log-streams` queue. The bundled worker (`python manage.py rqworker`) starts a pool for it automatically — size it with the [`LOG_STREAM_WORKERS`](/self-hosting/configuration/envars) environment variable (default: `2`). Shipping is network-bound and serialized per stream, so useful concurrency roughly equals your number of active streams. +- If you run split workers (e.g. one Deployment per queue on Kubernetes), add a consumer for the `log-streams` queue. +- See the [self-hosting guide](/self-hosting) and [environment variables reference](/self-hosting/configuration/envars) for full deployment configuration. diff --git a/public/console/organisation.md b/public/console/organisation.md index 59bc5b14..fa3f77f9 100644 --- a/public/console/organisation.md +++ b/public/console/organisation.md @@ -2,7 +2,7 @@ import { Tag } from '@/components/Tag' import { DocActions } from '@/components/DocActions' export const description = - 'This guide will explain how organisations works in Phase' + 'This guide will explain how organisations work in Phase' CONSOLE @@ -14,21 +14,21 @@ Organisations in Phase contain all your [Apps](/console/apps) and [Users](/conso ## Create an Organisation -When you signup on Phase, you will need to create an Organisation. You must choose an name for your Organisation that can contain letters or numbers. Organistaion names must be unique. +When you sign up on Phase, you will need to create an Organisation. You must choose a name for your Organisation that can contain letters or numbers. Organisation names must be unique. -![create organsation](/assets/images/console/organisation/organisation-create.png) +![create organisation](/assets/images/console/organisation/organisation-create.png) ## Apps This page lists all Apps in your Organisation, along with information about the number of members, environments, integrations and service accounts accessible by you in each App. Click on an App to view and manage it. -![organsation apps](/assets/images/console/organisation/organisation-apps.png) +![organisation apps](/assets/images/console/organisation/organisation-apps.png) ## Members This page lists all members of your Organisation. If you are an Owner or Admin, you can modify member roles from this screen. -![organsation members](/assets/images/console/organisation/organisation-members.png) +![organisation members](/assets/images/console/organisation/organisation-members.png) You can also invite new members to your Organisation. To invite a new member, click on the "Add a member" button, enter the email of the user you wish to invite, optionally select a role and click "Invite". You will need to manually provision access to Apps for the new member. @@ -40,7 +40,7 @@ You are limited to selecting a non Global Access role when inviting a new member This page shows your account and recovery info related to this Organisation. You can view your current role, preferences and download your account recovery kit from this screen. This page will also show you the current billing status of your Organisation. -![organsation settings](/assets/images/console/organisation/organisation-settings.png) +![organisation settings](/assets/images/console/organisation/organisation-settings.png) ## Transfer Ownership diff --git a/public/console/secrets.md b/public/console/secrets.md index 325d54ca..61333929 100644 --- a/public/console/secrets.md +++ b/public/console/secrets.md @@ -137,7 +137,7 @@ You can easily share secrets to other users via a secure link. When sharing a se ### Permalink -Permalinks allow you to share a secret with other users who already have access to it in Phase. This is useful when you want to link to a specific secret within an App, Environment, or Folder to others on your team. +Permalinks allow you to share a secret with other users who already have access to it in Phase. This is useful when you want to link a specific secret within an App, Environment, or Folder to others on your team. ![secret permalink](/assets/images/console/secrets/sharing/secret-permalink.png) diff --git a/public/console/users.md b/public/console/users.md index df4fdf17..9416084c 100644 --- a/public/console/users.md +++ b/public/console/users.md @@ -14,9 +14,9 @@ Learn how User accounts work in Phase. ## Account keys & Signup -Phase is end-to-end encrypted, which means that each member of an [Organisation](/console/organisation) has a unique set of encryption keys that only the accoutn Owner has access to. +Phase is end-to-end encrypted, which means that each member of an [Organisation](/console/organisation) has a unique set of encryption keys that only they have access to. -You can sign up for Phase using email and password or via an SSO provider (Google, GitHub, GitLab, etc.). Email/password signups on Phase Cloud require email verification before the account is activated. +You can sign up for Phase using your email and password or via an SSO provider (Google, GitHub, GitLab, etc.). Email/password signups on Phase Cloud require email verification before the account is activated. ### Step 1: Create a sudo password @@ -74,7 +74,7 @@ Remember: Your `sudo` password is a critical security measure. Always use a stro ## Add users to an Organisation -You can add a user as an Organistion member by inviting them from the [Organisation members](/console/organisation#members) screen. +You can add a user as an Organisation member by inviting them from the [Organisation members](/console/organisation#members) screen. To invite a new member, click on the "Add a member" button, enter the email of the user you wish to invite. An email invite with a link to join your organisation will be sent to their email address. You will also be shown an invite link that can be copied and shared if required. @@ -88,10 +88,10 @@ Note: Invited members will not have access to any Apps or Environments after joi ## Remove a member from an Organisation -You can permanently remove a member from an Organsation from the [Organisation members](/console/organisation#members) screen. To remove a member, click on the "Remove member" button beside their name. +You can permanently remove a member from an Organisation from the [Organisation members](/console/organisation#members) screen. To remove a member, click on the "Remove member" button beside their name. ## User Roles -Users in Phase must be given a role. By default, user's are given the managed "Developer" role when they join an Organisation. This role can be changed once they join. +Users in Phase must be given a role. By default, users are given the managed "Developer" role when they join an Organisation. This role can be changed once they join. -[Learn about about how roles work](/access-control/roles). \ No newline at end of file +[Learn about how roles work](/access-control/roles). \ No newline at end of file diff --git a/public/index.md b/public/index.md index ff40b5f7..f6df5ed8 100644 --- a/public/index.md +++ b/public/index.md @@ -27,7 +27,7 @@ Phase is an open-source, end-to-end encrypted platform for creating, managing, a The Phase platform provides powerful secret management features including personal secret overrides, secret versioning & roll-back, secret referencing, RBAC, and much more. -You can replace .env files with runtime secret inject with a fully-featured [CLI](/cli), deploy secrets to third party services with native integrations, and build your own custom workflows and integrations with [SDKs](/sdks) and [APIs](/public-api). +You can replace .env files with runtime secret injection with a fully-featured [CLI](/cli), deploy secrets to third party services with native integrations, and build your own custom workflows and integrations with [SDKs](/sdks) and [APIs](/public-api). @@ -38,7 +38,7 @@ The platform is built on a sophisticated [encryption architecture](/security/arc ## Get started{{ anchor: true }} -Get setup with Phase in minutes by following the Quickstart guide. This Guide will walk you through setting up your account via the [Phase Console](/#phase-console), installing the [CLI](/#phase-cli) and importing your existing secrets. +Get set up with Phase in minutes by following the Quickstart guide. This Guide will walk you through setting up your account via the [Phase Console](/#phase-console), installing the [CLI](/#phase-cli) and importing your existing secrets.
- - - -## Integrate Phase - -Seamlessly work with your preferred tools and platforms. - - - -
-
- -## Self-host Phase - -Deploy Phase on your own infrastructure, maintain full control over your data. - - - -
-
- ---- - -## Ready to try?{{ anchor: true }} - -To get started, create a new application in your [Phase Console](https://console.phase.dev) and set up the [Phase CLI](/cli/usage). {{ className: 'lead' }} - -
-
diff --git a/src/components/PhaseAtAGlance.jsx b/src/components/PhaseAtAGlance.jsx new file mode 100644 index 00000000..984fcf1d --- /dev/null +++ b/src/components/PhaseAtAGlance.jsx @@ -0,0 +1,571 @@ +import clsx from 'clsx' +import Link from 'next/link' +import { FaCog, FaKey, FaLock } from 'react-icons/fa' +import { FiEye, FiFolder } from 'react-icons/fi' +import { + SiAmazoniam, + SiAmazonwebservices, + SiCloudflarepages, + SiCloudflareworkers, + SiDatadog, + SiDependabot, + SiGithub, + SiGithubactions, + SiGithubcopilot, + SiGitlab, + SiGnometerminal, + SiGo, + SiGooglecloud, + SiJenkins, + SiKubernetes, + SiMicrosoftazure, + SiNodedotjs, + SiNomad, + SiOkta, + SiOpenai, + SiPostgresql, + SiPython, + SiRailway, + SiRender, + SiTerraform, + SiVercel, +} from 'react-icons/si' + +import { ClaudeIcon, CursorIcon, OpenCodeIcon } from '@/components/icons/AgentIcons' + +/** + * "Phase at a glance" — the docs landing page, in the swiss drafting + * language. Ported from the website's HowPhaseWorks export sheet; every + * colour token is a light/dark pair so it follows the docs theme toggle + * natively (no image swap). Every cell title links to its docs section + * (underlined on hover), so the sheet doubles as a map of the docs. Four + * hue-coded bands with the store as the hub: + * + * Access (sky) — lifecycle axis develop → build → deploy → + * run and every surface that reaches into + * Phase along it; each drops a trace into + * the store. + * Store (emerald) — app › environment › path › key/value and + * the three secret types. + * Automate (violet) — rotation, dynamic secrets, syncs; three + * traces drop from the store. + * Control & monitor (amber) — authentication, network access policies, + * audit logs. Cross-cutting, so no traces. + * + * Static — no motion. Laid out for ≥1000px; below that the sheet scrolls + * horizontally inside its wrapper. Semantic accents mirror the website: + * lease-ledger dots (active / expiring / revoked), [SYNCED] statuses, + * amber sealed lock, amber ❯ prompt, IP allow-list chips. + */ + +/* ------------------------------------------------------------------ */ +/* Tokens — light class first, dark: pair second */ +/* ------------------------------------------------------------------ */ + +const t = { + sheet: 'bg-white text-zinc-700 dark:bg-zinc-900 dark:text-zinc-300', + frameBorder: 'border-zinc-200 dark:border-zinc-800', + rule: 'border-zinc-200 dark:border-zinc-800', + divide: 'divide-zinc-200 dark:divide-zinc-800', + line: 'bg-zinc-300 dark:bg-zinc-700', + lineSoft: 'bg-zinc-200 dark:bg-zinc-800', + ink: 'text-zinc-900 dark:text-zinc-100', + body: 'text-zinc-700 dark:text-zinc-300', + muted: 'text-zinc-500', + faint: 'text-zinc-400 dark:text-zinc-600', + panel: 'bg-zinc-50 dark:bg-zinc-800/40', + chip: 'border-zinc-300 text-zinc-700 dark:border-zinc-700 dark:text-zinc-300', + accentDot: 'bg-emerald-500 dark:bg-emerald-400', + accentBorder: 'border-emerald-500 dark:border-emerald-400', + tabIdle: 'text-zinc-500', + tabActive: 'text-zinc-900 dark:text-zinc-100', + iconTone: 'text-zinc-700 dark:text-zinc-300', + plus: 'text-zinc-300 dark:text-zinc-700', + hue: { + sky: { + text: 'text-sky-600 dark:text-sky-400', + border: 'border-sky-500/50 dark:border-sky-400/45', + }, + emerald: { + text: 'text-emerald-600 dark:text-emerald-400', + border: 'border-emerald-500/50 dark:border-emerald-400/45', + }, + violet: { + text: 'text-violet-600 dark:text-violet-400', + border: 'border-violet-500/50 dark:border-violet-400/45', + }, + amber: { + text: 'text-amber-600 dark:text-amber-400', + border: 'border-amber-500/50 dark:border-amber-400/45', + }, + }, + ok: { + text: 'text-emerald-600 dark:text-emerald-400', + dot: 'bg-emerald-500 dark:bg-emerald-400', + }, + warn: { + text: 'text-amber-600 dark:text-amber-400', + dot: 'bg-amber-500 dark:bg-amber-400', + }, + bad: { + text: 'text-red-600 dark:text-red-400', + dot: 'bg-red-500 dark:bg-red-400', + }, + glyph: { + config: 'text-cyan-600 dark:text-cyan-400', + secret: 'text-sky-600 dark:text-sky-400', + sealed: 'text-amber-600 dark:text-amber-400', + }, + sealedMask: 'text-amber-600/70 dark:text-amber-400/70', + prompt: 'text-amber-600 dark:text-amber-400', + ipRange: + 'border-blue-500/40 bg-blue-50 text-blue-700 dark:bg-blue-500/[0.06] dark:text-blue-300', + ipSingle: + 'border-emerald-500/40 bg-emerald-50 text-emerald-700 dark:bg-emerald-500/[0.06] dark:text-emerald-300', +} + +const eyebrow = 'font-mono text-[10px] uppercase tracking-[0.14em]' + +/* ------------------------------------------------------------------ */ +/* Primitives */ +/* ------------------------------------------------------------------ */ + +/** Band zone label — mono, uppercase, in the band's hue. */ +function BandLabel({ hue, children }) { + return {children} +} + +/** A provider / tool mark: icon (or text chip) + optional label. */ +function Mark({ Icon, text, label }) { + return ( + + {Icon ? ( + + ) +} + +/** Tailscale mark — 3×3 dot grid, middle row + bottom-centre solid (a T). */ +function TailscaleMark({ className }) { + return ( + + ) +} + +/** IP allow-list chip — blue for ranges, emerald for single addresses. */ +function IpChip({ range, children }) { + return ( + + {children} + + ) +} + +/** Status dot + mono text — the lease-ledger idiom (active / expiring / revoked). */ +function Status({ level, className, children }) { + return ( + + + ) +} + +/** Hue-coded node cell — border in the band hue at reduced opacity, title in + * the hue — a docs link when `href` is given, underlined on hover — with an + * optional right-aligned status, marks + a faint sub-line pinned to the + * bottom. */ +function Cell({ hue, title, href, status, sub, className, children }) { + return ( +
+
+ {href ? ( + + {title} + + ) : ( + {title} + )} + {status} +
+
+
{children}
+ {sub && ( +
{sub}
+ )} +
+
+ ) +} + +/** A row of vertical hairline traces, one per grid column, centered. */ +function Drops({ cols, spans, className }) { + return ( + + ) +} + +/* ------------------------------------------------------------------ */ +/* Store — the console-style frame */ +/* ------------------------------------------------------------------ */ + +const rowGrid = 'grid grid-cols-[188px_300px_84px_1fr] items-center px-4' + +function StoreFrame() { + return ( +
+ {/* App title bar */} +
+ + App + payments-api + + 3 environments · 47 secrets +
+ + {/* Environment tabs + path */} +
+
+ {[ + { name: 'Development', active: false }, + { name: 'Staging', active: false }, + { name: 'Production', active: true }, + ].map((env) => ( + + {env.active && } + {env.name} + + ))} +
+ + +
+ + {/* Table — the three rows are the type legend */} +
+ Key + Value + Type + +
+
+ {/* config — visible */} +
+ + + 5432 + config + always visible +
+ {/* secret — masked, revealed here */} +
+ + + + db.internal + + secret + masked · reveal with access +
+ {/* sealed — never revealed */} +
+ + + ********* + sealed + write-only · injected at runtime +
+
+
+ ) +} + +/* ------------------------------------------------------------------ */ +/* Component */ +/* ------------------------------------------------------------------ */ + +const ACCESS_SPANS = Array.from({ length: 6 }, () => 'col-span-1') +const agentIcon = clsx('h-3.5 w-3.5 shrink-0', t.iconTone) + +export function PhaseAtAGlance() { + return ( +
+
+ {/* ------------------------------ Access ------------------------------ */} +
+ Access + + {/* Lifecycle axis: develop → build → deploy → run */} +
+ {[ + { label: 'Develop', span: 'col-span-2' }, + { label: 'Build', span: 'col-span-2' }, + { label: 'Deploy', span: 'col-span-1' }, + { label: 'Run', span: 'col-span-1' }, + ].map((s) => ( + + {s.label} + + ))} +
+
+ +
+
+ + +
+ + + + skill · phase-cli + + + + + + + + REST API + + + + + + + + + + phase_secret · phase_secrets + + + plan +2 ~1 + + + + + native Secrets + + pods 3/3 ready + + +
+ + {/* Every access surface drops a trace into the store */} + +
+ + {/* ------------------------------- Store ------------------------------- */} +
+
+ Store +
+
+ +
+
+ + {/* Traces from the store into the automate cells */} +
+ +
+ Automate +
+
+ + {/* ----------------------------- Automate ------------------------------ */} +
+ + + + + + + + v42 · active secret + v41 · expiring in 6h + + + + + + + + active · expires in 54m + expiring · 3m + revoked + + + synced 12s ago} + sub="automated secret deployment" + > + + + + + + + + + + + + + + +
+ + {/* -------------------------- Control & monitor ------------------------ */} +
+ + +
+
+ ) +} diff --git a/src/components/icons/AgentIcons.jsx b/src/components/icons/AgentIcons.jsx new file mode 100644 index 00000000..70edfabe --- /dev/null +++ b/src/components/icons/AgentIcons.jsx @@ -0,0 +1,24 @@ +/** + * Agent marks without Simple Icons entries — copied from the website's + * swiss agent-icons (phase.dev). All render in currentColor. + */ +export const ClaudeIcon = (props) => ( + + + +) + +/** Official Cursor cube mark (2D variant from the Cursor brand kit). */ +export const CursorIcon = (props) => ( + + + +) + +/** Official OpenCode logomark (opencode.ai/brand), flattened to currentColor. */ +export const OpenCodeIcon = (props) => ( + + + + +) diff --git a/src/pages/index.mdx b/src/pages/index.mdx index f6df5ed8..4290000d 100644 --- a/src/pages/index.mdx +++ b/src/pages/index.mdx @@ -1,38 +1,19 @@ -import { PlatformsIntegration } from '@/components/PlatformsIntegration' +import { PhaseAtAGlance } from '@/components/PhaseAtAGlance' -import { Deployments } from '@/components/Deployments' -import { SecurityResources } from '@/components/SecurityResources' import { Platform } from '@/components/Platform' -import { About } from '@/components/AboutPhase' import { HeroPattern } from '@/components/HeroPattern' -import { Tag } from '@/components/Tag' -import { FaArrowRight } from 'react-icons/fa' export const description = - 'Phase is an open source & end-to-end encrypted platform for creating, managing, syncing and deploying secrets and environment variables across your infrastructure.' + 'Secrets management for your applications and AI agents. Store secrets as key-value pairs across environments and access them via the CLI, SDKs and APIs. Automate the secret lifecycle — mint, rotate, deploy, revoke. Control access and gain visibility.' -# Introduction +# The Phase platform -Phase is an open-source, end-to-end encrypted platform for creating, managing, and deploying application secrets and environment variables across your infrastructure. {{ className: 'lead' }} - -- **Import** secrets from `.env` files and [inject](/quickstart#3-inject-secrets) them into any application or container at runtime. -- **Automate** secret deployment to platforms like [GitHub Actions](/integrations/platforms/github-actions), [Kubernetes](/integrations/platforms/kubernetes), [AWS](/integrations/platforms/aws-secrets-manager) and more. -- **Share** secrets with your [team](/console/users#add-users-to-an-organisation) and manage access to secrets with [cryptographic RBAC](/console/environments#manage-user-access). -- **Manage** secrets with [environments](/console/environments), audit-logs, [RBAC](/access-control) etc. - -![console](/assets/images/console/console-ui.webp) - - -The Phase platform provides powerful secret management features including personal secret overrides, secret versioning & roll-back, secret referencing, RBAC, and much more. -You can replace .env files with runtime secret injection with a fully-featured [CLI](/cli), deploy secrets to third party services with native integrations, and build your own custom workflows and integrations with [SDKs](/sdks) and [APIs](/public-api). - - - -The platform is built on a sophisticated [encryption architecture](/security/architecture), while abstracting as much of the complexity of this implementation away from the user as possible. +Secrets management for your applications and AI agents. Store secrets as key-value pairs across environments and access them via the CLI, SDKs and APIs. Automate the secret lifecycle — mint, rotate, deploy, revoke. Control access and gain visibility. {{ className: 'lead' }} + --- @@ -44,51 +25,4 @@ Get set up with Phase in minutes by following the Quickstart guide. This Guide w
- - - -## Integrate Phase - -Seamlessly work with your preferred tools and platforms. - - - -
-
- -## Self-host Phase - -Deploy Phase on your own infrastructure, maintain full control over your data. - - - -
-
- ---- - -## Ready to try?{{ anchor: true }} - -To get started, create a new application in your [Phase Console](https://console.phase.dev) and set up the [Phase CLI](/cli/usage). {{ className: 'lead' }} - -
-
From 7db59da6d29f3a31b6835ad916e04b4b63a2d338 Mon Sep 17 00:00:00 2001 From: rohan Date: Mon, 7 Sep 2026 13:12:12 +0530 Subject: [PATCH 3/3] fix: import Signed-off-by: rohan --- src/pages/index.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/index.mdx b/src/pages/index.mdx index 68dec1c4..a7eea848 100644 --- a/src/pages/index.mdx +++ b/src/pages/index.mdx @@ -3,6 +3,7 @@ import { PhaseAtAGlance } from '@/components/PhaseAtAGlance' import { Deployments } from '@/components/Deployments' import { Platform } from '@/components/Platform' import { HeroPattern } from '@/components/HeroPattern' +import { PlatformsIntegration } from '@/components/PlatformsIntegration' export const description = 'Secrets management for your applications and AI agents. Store secrets as key-value pairs across environments and access them via the CLI, SDKs and APIs. Automate the secret lifecycle — mint, rotate, deploy, revoke. Control access and gain visibility.'