Skip to content

feat: expose the app-content bucket, MCP and OAuth [ENG-1740] - #59

Merged
twk3 merged 4 commits into
mainfrom
feat/eng-1740-app-content-mcp-oauth-retention
Oct 13, 2026
Merged

twk3 merged 4 commits into
mainfrom
feat/eng-1740-app-content-mcp-oauth-retention

Conversation

@twk3

@twk3 twk3 commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

The Helm version of currents-dev/docker#31: chart values for the app-content bucket, remote MCP and the OAuth provider, and documentation for artifact retention (ENG-1740).

The chart builds each pod's environment explicitly, so until now none of PERMANENT_STORAGE_*, MCP_ENABLED or OAUTH_* reached a pod unless the operator added them through env.

Changes

  • currents.appContentStorage.* renders PERMANENT_STORAGE_* on the server, change-streams and writer pods. The writer needs it because it deletes session files.
    • Any field left unset falls back to the objectStorage value, so one endpoint and one secret serve both buckets.
    • The internal endpoint and region fall back only when the endpoint does. With its own endpoint (e.g. R2), the artifact storage's internal endpoint would send the pods to the wrong storage.
    • With neither secret set, the pods use their IAM role (IRSA).
    • bucket defaults to empty, so an upgrade changes nothing until it is set.
  • currents.mcp.enabled defaults to true; currents.mcp.origins sets MCP_ORIGINS.
  • currents.oauth.* turns on the OAuth provider, dynamic client registration and client ID metadata documents.
    • All default on, which also applies to existing releases on upgrade.
    • The provider renders only when domains.https is true, or appHost is localhost or a *.localhost name. On any other http host the API refuses to start with OAuth on, so the chart leaves it off there.
    • A *.localhost appHost also gets OAUTH_HTTP_ALLOWED_HOSTS. Other http hosts don't get the option: there Better Auth advertises an https:// issuer the install doesn't serve.
  • OAUTH_JWKS_URL is set to the API's own port, only when domains.https is false (so appHost is localhost or *.localhost).
    • The API verifies every access token against its own signing keys, and fetches them from appHost unless this is set.
    • A pod resolves neither localhost nor *.localhost to the API, so without it every token is issued and then rejected at /mcp.
    • With domains.https, it stays unset and the API fetches from appHost, as cloud does.
  • samples/rustfs-create-bucket-job.yaml (and its copy in docs/eks/dependencies.md) creates currents-app-content beside currents, with lifecycle rules scoped to ai-context-share/, share-3d/, share-7d/ and trace-links/ (2, 4, 8 and 8 days). Logos and session files share the bucket, so the rules are never bucket-wide.
  • Docs:
    • dependencies.md gets the app-content bucket (create it, s3:DeleteObject, CORS PUT for logo uploads, scoped lifecycle rules) and artifact expiry. The chart can't reach the operator's bucket, so retention is documentation rather than a value.
    • iam.md adds the second bucket to the IRSA policy.
    • quickstart.md gets appContentStorage and a "Remote MCP and OAuth" section.
    • Both samples set appContentStorage.bucket.
    • configuration.md is regenerated.
  • SAML: drops SSO_SAML_SP_CERT_FILE and currents.sso.saml.spCertKey. The API reads only the SP key.

Upgrade notes

  • Releases with domains.https: true get OAuth on upgrade. Set currents.oauth.enabled: false to keep it off.
  • Context sharing, logo editing and session file uploads need currents.appContentStorage.bucket and a bucket created as described in dependencies.md.
  • A values file that still sets spCertKey is ignored for that key.

Testing

helm template across value combinations:

  • https, *.localhost over http, localhost:8080 over http, and another http host (OAuth not rendered).
  • MCP and OAuth off; registration and client ID metadata documents off.
  • appContentStorage: unset, everything inherited, IRSA, its own endpoint and secret, pathStyle: false overriding the artifact true, and no endpoint anywhere (fails with a message).
  • helm lint with the CI values passes, and configuration.md matches helm-docs.

A real install on Docker Desktop Kubernetes, following the developer guide in a separate namespace, with samples/local/chart-config.yaml and images built from currents main:

  • Bucket job: creates both buckets and the four rules.
  • Pod env: the server, writer and change-streams pods carry the expected values.
  • OAuth:
    • Metadata on http://currents-app.localhost is all http://.
    • The full flow passes: sign-in, client registration, authorize, consent, token, then /mcp with the OAuth token listing tools.
    • Without OAUTH_JWKS_URL, /mcp rejected the same token with no token payload.
    • helm template with domains.https: true renders no OAUTH_JWKS_URL.
  • Session files and shares:
    • A POST /v1/sessions upload lands in currents-app-content through the rustfs.localhost presigned URL.
    • A share link created through MCP serves the screenshot byte for byte.
    • DELETE /v1/sessions/<id> empties the bucket through the writer's internal endpoint.
  • Off switches: currents.mcp.enabled=false and currents.oauth.enabled=false give /mcp 503 and no OAuth metadata; re-enabling restores both.

Not tested:

  • Logo upload. It uses the same server env and was tested in the browser on ENG-1738.
  • The EKS ingress (no EKS cluster).

Related

🤖 Generated with Claude Code

https://claude.ai/code/session_01UhM4wHR2xPP8bbrkXGaqUD

- currents.appContentStorage.* renders the PERMANENT_STORAGE_* the server,
  change-streams and writer read for context shares, organization logos and
  session files. Unset fields take the objectStorage values; the internal
  endpoint and region only with the endpoint. Without a bucket, sharing and
  logo editing stay off, so upgrades are unchanged until it is set.
- currents.mcp.enabled (default true) and currents.oauth.* render MCP_* and
  OAUTH_* on the server. OAuth defaults on, and also turns on for existing
  releases on upgrade, but renders only with domains.https or an appHost of
  localhost or *.localhost: on any other http host the API refuses to start.
  A *.localhost appHost gets OAUTH_HTTP_ALLOWED_HOSTS.
- OAUTH_JWKS_URL points at the API on localhost: a pod cannot resolve a
  *.localhost appHost, and may not reach a real one without going out through
  the ingress, so every access token was rejected.
- The RustFS bucket job creates currents-app-content with lifecycle rules for
  the share prefixes. The docs cover the bucket, its CORS and IAM, and artifact
  expiry on external storage.
- Drop SSO_SAML_SP_CERT_FILE and currents.sso.saml.spCertKey: the API never
  read them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhM4wHR2xPP8bbrkXGaqUD
@baz-reviewer

baz-reviewer Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Review this PR on Baz

Baz Summary

Expose first-class Helm values for remote MCP, OAuth, and app-content storage, rendering the required environment variables across the server, writer, and changestreams deployments. Document external bucket setup, scoped retention policies, IAM access, OAuth behavior, and remove the unused SAML certificate setting.

Topics

TopicDetails
App Content Storage Configure the permanent app-content bucket for server, writer, and changestreams, including storage fallbacks, secret-based credentials, IAM permissions, sample bucket creation, and scoped lifecycle guidance that preserves logos and session files.
Modified files (12)
  • charts/currents/templates/_common.tpl
  • charts/currents/templates/changestreams/deployment.yaml
  • charts/currents/templates/server/deployment.yaml
  • charts/currents/templates/writer/deployment.yaml
  • charts/currents/values.yaml
  • docs/configuration.md
  • docs/developer-guide/README.md
  • docs/eks/dependencies.md
  • docs/eks/iam.md
  • samples/eks/eks-config.yaml
  • samples/local/chart-config.yaml
  • samples/rustfs-create-bucket-job.yaml
Latest Contributors(2)
UserCommitDate
dj@currents.devfix: set OAUTH_JWKS_UR...October 13, 2026
yohay.arch@gmail.comchore: adding logger v...April 03, 2025
Remote MCP and OAuth Expose configurable MCP and OAuth provider settings with safe HTTP-host handling, JWKS configuration, feature toggles, and generated documentation for remote client authentication.
Modified files (5)
  • charts/currents/templates/_common.tpl
  • charts/currents/templates/server/deployment.yaml
  • charts/currents/values.yaml
  • docs/configuration.md
  • docs/eks/quickstart.md
Latest Contributors(2)
UserCommitDate
dj@currents.devfix: set OAUTH_JWKS_UR...October 13, 2026
yohay.arch@gmail.comchore: adding logger v...April 03, 2025

Merger  Activate to get a short verdict whether this PR is good to go or not

Skills  Activate Skill Maintainer to keep your skills up to date

Planner  This PR would have been improved with Baz Planner - Try it now

Comment thread samples/rustfs-create-bucket-job.yaml Outdated
With domains.https the API fetches its signing keys from appHost, as cloud
does. Over http the appHost is localhost or *.localhost, which a pod resolves
to itself or not at all, so the chart points the API at its own port there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhM4wHR2xPP8bbrkXGaqUD
Comment thread charts/currents/templates/_common.tpl
…ain [ENG-1740]

The job replaced the app-content bucket's lifecycle configuration on every
apply, dropping rules added since. It now writes its rules only to a bucket
without any. The quickstart says when to point OAUTH_JWKS_URL at the API
itself: a server pod that cannot reach or trust appHost rejects every token.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhM4wHR2xPP8bbrkXGaqUD
Comment thread samples/rustfs-create-bucket-job.yaml Outdated
…les [ENG-1740]

The RustFS bucket job skipped the share rules whenever the app-content bucket
had any lifecycle configuration, so a bucket with only other rules never
expired its share prefixes. It now rewrites the four share rules, matched by
ID, and keeps the bucket's other rules, as the Docker rustfs-init does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhM4wHR2xPP8bbrkXGaqUD
@twk3
twk3 merged commit 4da2922 into main Oct 13, 2026
3 checks passed
@twk3
twk3 deleted the feat/eng-1740-app-content-mcp-oauth-retention branch October 13, 2026 23:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant