Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions charts/currents/templates/_common.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,11 @@ ClickHouse data is loaded from an external export (scripts/org-import).
- name: SSO_SAML_SP_KEY_FILE
value: {{ printf "/etc/currents/sso/%s" .Values.currents.sso.saml.spKeyKey | quote }}
{{- end }}
{{- /* toString, so a quoted "false" stays off: any non-empty string is true to `if`. */}}
{{- if eq (toString .Values.currents.sso.saml.allowIdpInitiated) "true" }}
- name: SSO_SAML_ALLOW_IDP_INITIATED
value: "true"
{{- end }}
{{- end }}
{{- end -}}

Expand Down
5 changes: 4 additions & 1 deletion charts/currents/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ currents:
# -- SP entityID / audience presented to your IdP. A stable opaque identifier (e.g. `currents-onprem:your-org`), NOT a URL. Must match the Audience / SP Entity ID configured in your IdP.
# @section -- SAML SSO
issuer: ""
# -- Provider id; recommend your IdP service name (e.g. `okta`). Becomes the last path segment of the ACS callback URL.
# -- Provider id; recommend your IdP service name (e.g. `okta`). Becomes the last path segment of the ACS URL, `https://<appHost>/api/auth/sso/saml2/sp/acs/<providerId>`.
# @section -- SAML SSO
providerId: onprem-saml
# -- K8s secret holding the IdP metadata XML (and the SP key, when signing requests). Mounted read-only at /etc/currents/sso. See the SAML SSO guide for how to create it.
Expand All @@ -111,6 +111,9 @@ currents:
# -- Secret key (file name) of the SP private key PEM (only when authnRequestsSigned=true)
# @section -- SAML SSO
spKeyKey: sp-key.pem
# -- Accept sign-ins started from the IdP (for example its app dashboard), which carry no request from Currents to match. Off: such a sign-in is refused, and users start from the Currents sign-in page.
# @section -- SAML SSO
allowIdpInitiated: false
mcp:
# -- Serve remote MCP at `/mcp`, so coding agents can use Currents tools over HTTP. Clients
# authenticate with an API key or personal access token, or with OAuth (below). Requests
Expand Down
2 changes: 2 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ The Currents Helm Chart is stateless, so depends on being connected to stateful

- [🚀 Start Here: EKS Quickstart](./eks/quickstart.md)
- [EKS Upgrade Guide](./eks/upgrading.md)
- [Upgrading to Chart 1.0](./eks/upgrade-1.0.md)
- [Docs for chart 0.8.x](https://currents-dev.github.io/helm-charts/0.8/docs/)
- [Importing Organization Data (Cloud → Self-Hosted Migration)](./org-data-import.md)
- [Development Guide](./developer-guide/README.md)
- [Support Policy](./support.md)
Expand Down
3 changes: 2 additions & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,14 @@ The following table lists the configurable parameters of the `currents` chart an
|-----|------|---------|-------------|
| currents.sso.saml.enabled | bool | `false` | Enable SAML SSO. Requires `issuer` and `metadataSecretName` below (a K8s secret holding your IdP metadata XML). Turns on email-first SSO login. |
| currents.sso.saml.issuer | string | `""` | SP entityID / audience presented to your IdP. A stable opaque identifier (e.g. `currents-onprem:your-org`), NOT a URL. Must match the Audience / SP Entity ID configured in your IdP. |
| currents.sso.saml.providerId | string | `"onprem-saml"` | Provider id; recommend your IdP service name (e.g. `okta`). Becomes the last path segment of the ACS callback URL. |
| currents.sso.saml.providerId | string | `"onprem-saml"` | Provider id; recommend your IdP service name (e.g. `okta`). Becomes the last path segment of the ACS URL, `https://<appHost>/api/auth/sso/saml2/sp/acs/<providerId>`. |
| currents.sso.saml.metadataSecretName | string | `""` | K8s secret holding the IdP metadata XML (and the SP key, when signing requests). Mounted read-only at /etc/currents/sso. See the SAML SSO guide for how to create it. |
| currents.sso.saml.metadataKey | string | `"idp-metadata.xml"` | The secret key (file name) of the IdP metadata XML |
| currents.sso.saml.defaultRole | string | `"member"` | Role granted to auto-provisioned SSO users |
| currents.sso.saml.allowedDomains | string | `""` | Comma-separated email domains allowed to sign in via SSO (optional allow-list) |
| currents.sso.saml.authnRequestsSigned | bool | `false` | Sign outbound AuthnRequests. Requires the SP key (below) in the same secret; upload the matching certificate to your IdP. |
| currents.sso.saml.spKeyKey | string | `"sp-key.pem"` | Secret key (file name) of the SP private key PEM (only when authnRequestsSigned=true) |
| currents.sso.saml.allowIdpInitiated | bool | `false` | Accept sign-ins started from the IdP (for example its app dashboard), which carry no request from Currents to match. Off: such a sign-in is refused, and users start from the Currents sign-in page. |

### Remote MCP and OAuth

Expand Down
11 changes: 9 additions & 2 deletions docs/eks/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ CURRENTS_API_URL=https://currents-record.eks.example.com npx pwc --key <your-key

## Upgrade Existing Installations

When you need to move to a newer Currents release, follow the dedicated [EKS Upgrade Guide](./upgrading.md).
When you need to move to a newer Currents release, follow the dedicated [EKS Upgrade Guide](./upgrading.md). From `0.8.x`, read [Upgrading to Chart 1.0](./upgrade-1.0.md) first.

## Remote MCP and OAuth

Expand All @@ -244,8 +244,9 @@ server:
Delegate sign-in to your SAML 2.0 identity provider (Okta, Microsoft Entra ID, etc.). Users sign in **email-first** — they enter their email, are redirected to your IdP to authenticate, and are auto-provisioned into your organization on return. SMTP must be configured (used for provisioning and invitations).

1. **Create the SAML app in your IdP.** Using Okta as the example, set:
- **Single Sign-On / ACS URL:** `https://<appHost>/api/auth/sso/saml2/callback/okta`
- **Single Sign-On / ACS URL:** `https://<appHost>/api/auth/sso/saml2/sp/acs/okta`
Comment thread
twk3 marked this conversation as resolved.
— the last segment is your `providerId`; `<appHost>` is your `currents.domains.appHost`.
Use the same URL as the Recipient and Destination. In Okta, leave "Use this for Recipient URL and Destination URL" checked (the default) and both follow the Single Sign-On URL. Currents rejects an assertion whose Recipient or Destination is any other URL.
- **Audience / SP Entity ID:** `currents-onprem:your-org` — a stable opaque identifier, **not a URL**.
- **Name ID format:** `Persistent`
- **Application username:** Email
Expand All @@ -271,6 +272,8 @@ Delegate sign-in to your SAML 2.0 identity provider (Okta, Microsoft Entra ID, e
# Optional:
# defaultRole: member
# allowedDomains: "acme.com,acme.io"
# Accept sign-ins started from the IdP's app dashboard
# allowIdpInitiated: true
```

4. **Apply:**
Expand All @@ -280,6 +283,10 @@ Delegate sign-in to your SAML 2.0 identity provider (Okta, Microsoft Entra ID, e

Sign in from the dashboard by entering your email — you'll be redirected to your IdP. New SSO users join your organization automatically with the role from `defaultRole` (default `member`); the root admin continues to sign in with email + password.

A sign-in started from the IdP's app dashboard (an Okta tile, the Entra My Apps portal) is refused unless `allowIdpInitiated` is `true`. Currents can't match it to a request of its own, so leave it off unless your users need the tile.

Once SSO is on, Currents serves its SP metadata at `https://<appHost>/api/auth/sso/saml2/sp/metadata?providerId=okta` (with your `providerId`), for IdPs that import it.

To rotate the IdP signing certificate, replace the secret with the refreshed metadata and restart the server pod:
```sh
kubectl create secret generic currents-sso-saml --from-file=idp-metadata.xml=./idp-metadata.xml \
Expand Down
136 changes: 136 additions & 0 deletions docs/eks/upgrade-1.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# Upgrading to Chart 1.0

This guide covers upgrading from chart `0.8.x` (images `2026-07-26-00x`) to `1.0.0`. Read it before you upgrade: one change breaks SAML SSO sign-in until you update your identity provider, and the app content bucket has to exist first.

For the general upgrade flow, see the [EKS Upgrade Guide](./upgrading.md). The docs for the chart you are upgrading from are at [chart 0.8.x docs](https://currents-dev.github.io/helm-charts/0.8/docs/).

## What Changes

| Change | Action |
|--------|--------|
| [SAML SSO ACS URL moves](#saml-sso) | Required if you use SSO: update your IdP when you upgrade |
| [SAML sign-ins started from the IdP are refused](#saml-sso) | Set `currents.sso.saml.allowIdpInitiated: true` if your users sign in from an IdP tile |
| [App content bucket](#app-content-bucket) | Create a second bucket and set `currents.appContentStorage.bucket` |
| [Remote MCP and OAuth](#remote-mcp-and-oauth) | None: on by default. Set the values to `false` to keep them off |
| [Database migrations](#database-migrations) | None: they run when the scheduler starts. Check they finish |
| [`currents.sso.saml.spCertKey` removed](#removed-values) | Remove it from your values file |
| [Artifact expiry](#artifact-expiry) | Optional: add a lifecycle rule to the artifact bucket |

## Before You Upgrade

1. Back up MongoDB and ClickHouse. The upgrade runs database migrations, and `helm rollback` doesn't undo them.
2. If you use SAML SSO, schedule the IdP change for the upgrade window. See [SAML SSO](#saml-sso).
3. Create the app content bucket. See [App content bucket](#app-content-bucket).
4. Update your values file:

```yaml
currents:
appContentStorage:
bucket: currents-app-content
# Only to keep them off:
# mcp:
# enabled: false
# oauth:
# enabled: false
sso:
saml:
# Only if users sign in from the IdP's app dashboard:
# allowIdpInitiated: true
```

## Run the Upgrade

```bash
helm upgrade --install currents currents \
--repo https://currents-dev.github.io/helm-charts/ \
--version 1.0.0 \
-f currents-helm-config.yaml
```

Then follow the scheduler until its migrations finish. See [Database migrations](#database-migrations).

## SAML SSO

The ACS URL moves:

| | URL |
|--|-----|
| `0.8.x` | `https://<appHost>/api/auth/sso/saml2/callback/<providerId>` |
| `1.0.0` | `https://<appHost>/api/auth/sso/saml2/sp/acs/<providerId>` |

The old path answers `404`, so SSO sign-in fails from the upgrade until your IdP sends assertions to the new URL. The root admin's email and password sign-in still works. When the upgrade is done:

1. In your IdP's SAML app, set the Single Sign-On / ACS URL (Entra ID: Reply URL) to the new URL.
2. Set the Recipient and Destination URLs to the new URL as well. In Okta, leave "Use this for Recipient URL and Destination URL" checked (the default) and both follow the Single Sign-On URL. Currents rejects an assertion whose Recipient or Destination is any other URL.
3. Leave the Audience / SP Entity ID as it is. It must still equal `currents.sso.saml.issuer`, which doesn't change.
4. Sign in from the Currents sign-in page.

A sign-in started from the IdP's app dashboard (an Okta tile, the Entra My Apps portal) is refused unless `currents.sso.saml.allowIdpInitiated` is `true`. Currents can't match such a sign-in to a request of its own. If your users don't need the tile, leave it off and have them start from the Currents sign-in page.

Currents also serves its SP metadata at `https://<appHost>/api/auth/sso/saml2/sp/metadata?providerId=<providerId>`, for IdPs that import it.

## App Content Bucket

Context shares, organization logos and session files go to a second bucket. Without `currents.appContentStorage.bucket`, context sharing and logo editing are off and session file uploads answer `503`.

1. Create the bucket, set its CORS rule and add its lifecycle rules as described in [App content bucket](./dependencies.md#app-content-bucket). The lifecycle rules must be scoped to the share prefixes: the bucket also holds logos and session files.
2. If the pods reach storage through IRSA, add the bucket to the role's policy. See [IRSA](./iam.md#irsa).
3. Set `currents.appContentStorage.bucket`. The other `appContentStorage` values default to the `objectStorage` ones, so the same endpoint and secret serve both buckets.

If you run RustFS in the cluster from [Alternative Object Storage](./dependencies.md#alternative-object-storage-in-cluster), upgrade it to `1.0.1` and run the bucket Job from that section again: it creates the app content bucket and its rules. Delete the earlier Job first: while it exists, applying the file doesn't start a new run.

```bash
kubectl delete job rustfs-create-bucket --ignore-not-found
```

RustFS releases before `1.0.0`, such as `1.0.0-alpha.79`, accept lifecycle rules without enforcing them.

## Remote MCP and OAuth

Remote MCP is served at `https://<appHost>/mcp`, and the OAuth provider lets MCP clients sign in with a Currents account. Both are on by default after the upgrade. OAuth turns on only when `currents.domains.https` is `true` (or `appHost` is `localhost` or a `*.localhost` name).

To keep either off, set `currents.mcp.enabled: false` or `currents.oauth.enabled: false`. See [Remote MCP and OAuth](./quickstart.md#remote-mcp-and-oauth).

To check them after the upgrade:

```bash
# 401 without credentials, 503 when MCP is off
curl -s -o /dev/null -w '%{http_code}\n' -X POST https://<appHost>/mcp
# The OAuth provider's metadata; 404 when OAuth is off
curl -s https://<appHost>/.well-known/oauth-authorization-server
```

## Database Migrations

The scheduler runs this release's migrations when it starts:

| Migration | What it does |
|-----------|--------------|
| `20260918-backfill-run-status` | Stores each run's status on its MongoDB document |
| `20260928-drop-non-unique-plans-price-id-index` | Drops a duplicate MongoDB index |
| `050`, `060` | Add columns to `run_metric_v2` in ClickHouse |
| `070-backfill-run-metric-search-columns` | Re-inserts every run into `run_metric_v2` to fill those columns |

With 100,000 runs, the scheduler's startup took under a minute in testing: about 25 seconds for the run status backfill and 10 seconds for `070`. They scale with the number of runs, so expect several minutes for a million.

This is not downtime: the dashboard, API and run recording keep working while the scheduler migrates. Until the migrations finish, filtering runs by status and searching by CI build ID can leave out runs recorded before the upgrade. The change-streams pod also copies every updated run to ClickHouse, during the migrations and for a few minutes after, so new results can take longer to process.

The scheduler pod reports ready while the migrations run, so a finished rollout doesn't mean they are done. Follow the scheduler's log:

```bash
kubectl logs -n currents deploy/currents-scheduler -f
```

The migrations are done when it logs `Startup tasks complete`. A few `Kept the existing index` warnings on the way are expected. If a migration logs an error instead, such as a ClickHouse `Timeout error.`, restart the scheduler as described in [Database Migrations and Startup Tasks](./upgrading.md#database-migrations-and-startup-tasks).

## Removed Values

`currents.sso.saml.spCertKey` is removed; the API never read the certificate it pointed to. Signed AuthnRequests need only `spKeyKey`; upload the matching certificate to your IdP.

## Artifact Expiry

Currents does not delete artifacts. To limit how long they are kept, add a lifecycle rule to the artifact bucket as described in [Artifact expiry](./dependencies.md#artifact-expiry).

## Rollback

`helm rollback` returns the templates and images to `0.8.x`, but not the database: the migrations stay applied. To return the data to its state before the upgrade, restore the backup you took. Point your IdP back at the old ACS URL as well.
1 change: 1 addition & 0 deletions docs/eks/upgrading.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ For reference, the Docker Compose environment has a separate upgrade flow: [Upgr

1. Check the chart [CHANGELOG](https://github.com/currents-dev/helm-charts/blob/main/CHANGELOG.md) for the target release.
2. Review any breaking changes and required values or secrets updates.
3. Upgrading from `0.8.x` to `1.0.0`? Follow [Upgrading to Chart 1.0](./upgrade-1.0.md) first: it changes SAML SSO and needs a second bucket.

Infrastructure backups and third-party dependencies are customer-managed. See [Currents Service Dependencies](./dependencies.md) and [Support Policy](../support.md).

Expand Down
Loading