Skip to content

fix(dev): inherit non-expiring sandbox JWT in local gateway scripts - #2636

Open
pimlock wants to merge 1 commit into
mainfrom
1603-local-gateway-jwt-ttl/pimlock
Open

fix(dev): inherit non-expiring sandbox JWT in local gateway scripts#2636
pimlock wants to merge 1 commit into
mainfrom
1603-local-gateway-jwt-ttl/pimlock

Conversation

@pimlock

@pimlock pimlock commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

For local gateways, we removed the ttl_secs for the supervisor JWT before, since for these it's possible the user closes their laptop, opens it again and the sandbox JWT expired and cannot be refreshed anymore, making the sandbox unusable.

That was changed in #1721 to have JWTs not expire for local gateways.

However, local gateways started through our dev scripts still use 3600 as TTL, so gateways started through these run into the same issue. This is a fix for that.

Observed on a local Docker gateway: two sandboxes at ~5,600 restarts each over 8 days, both stuck in Provisioning.

Error: × Policy fetch failed after 5 attempts: code: 'The request does not have
  │ valid authentication credentials', message: "invalid token: ExpiredSignature"
WARN openshell_core::grpc_client: RefreshSandboxToken returned Unauthenticated;
     static token sources cannot rebootstrap automatically

The ttl_secs = 3600 lines predate the fix - all three were added by fa84e43 (#1575, 2026-05-26), eight days before e4bcfdf (#1721, 2026-06-03). They are leftovers the fix missed, not a deliberate later mitigation.

Related Issue

Relates to #1603 and #1721. #1721 fixed the gateway default and the Kubernetes/Helm path; this covers the dev-workflow launchers it left behind. #1603 is closed, so this is the remaining follow-up rather than new accepted work - happy to open a fresh issue if maintainers prefer that.

Changes

  • tasks/scripts/gateway-docker.sh, tasks/scripts/gateway-vm.sh: removed the hardcoded ttl_secs = 3600. Both are local-driver-only, so they now inherit the non-expiring default from crates/openshell-server/src/defaults.rs.
  • tasks/scripts/gateway.sh: this script also serves the kubernetes driver, which is a shared deployment and must keep a positive TTL, so a plain removal would have been wrong. The value is now emitted conditionally for that driver only, appended after the heredoc but before the case writes any [openshell.drivers.*] header so it still lands in the gateway_jwt table.

Removing the line rather than setting ttl_secs = 0 keeps one source of truth, so a future change to the default propagates on its own.

Testing

  • mise run pre-commit passes
  • Unit tests added/updated - not applicable, shell config generation only
  • E2E tests added/updated

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Architecture docs updated (if applicable) - not needed; architecture/gateway.md and docs/reference/gateway-config.mdx already document ttl_secs = 0 as the local default, and this change makes the scripts match what is documented

The local gateway launcher scripts hardcode gateway_jwt.ttl_secs = 3600,
which overrides the non-expiring default introduced in #1721. Local
Docker, Podman, and VM sandboxes are still unrecoverable when the gateway
is down longer than that TTL: the on-disk token expires and only the
Kubernetes ServiceAccount path can rebootstrap, so the supervisor
crash-loops on policy fetch and the sandbox never leaves Provisioning.

Drop the override so local drivers inherit the default. gateway.sh also
serves the kubernetes driver, which is a shared deployment and must keep
a positive TTL, so it now emits ttl_secs only for that driver.

The e2e regression test added in #1721 does not catch this because the
e2e harness uses its own configs, which already set ttl_secs = 0.

Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant