Skip to content

feat(services): publish authoritative application origins - #4956

Draft
TaylorMutch wants to merge 1 commit into
feat/4667-service-discovery/TaylorMutchfrom
feat/4953-authoritative-app-urls/TaylorMutch
Draft

TaylorMutch wants to merge 1 commit into
feat/4667-service-discovery/TaylorMutchfrom
feat/4953-authoritative-app-urls/TaylorMutch

Conversation

@TaylorMutch

@TaylorMutch TaylorMutch commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Publish authoritative application URLs from the configured supervisor application origin, independently of the gateway API origin. Return explicit application and gateway URLs so clients can choose an access path.

Based on main at d7b616895. Stacked on feat/4667-service-discovery/TaylorMutch.

Related Issue

Closes #4953. Part of RFC 0017.

Changes

Integrator perspective

The service API tells clients which public URL to use; discovery tells routers where to send requests.

  • Configure the application domain and public_url for your public ingress. Responses expose application_url, the existing gateway_url, and a preferred url that selects the application URL when configured.
  • A proxy or controller consumes discovery snapshots/watches mapping each exact hostname to the current supervisor Pod IP and app-listener port. Follow ownership changes and honor withdrawal and expiry; consume the returned hostname without reconstructing it.
  • The sandbox proxy routes directly to those endpoints. An example Kubernetes HTTPRoute controller can instead configure HTTPRoutes and their backend/TLS resources. Application traffic bypasses the OpenShell gateway.

Publishing a URL does not create DNS or ingress resources, or establish reachability. Both ingress paths use [openshell.gateway].service_hostname_format; the app listener has no separate naming mode. Keeping the installation name and public HTTPS domain/port unchanged preserves the service URL when switching ingress.

Public URL selection

This PR publishes the configured application origin alongside the existing gateway-mediated URL. The example uses gateway installation gateway-a, workspace default, sandbox my-sandbox, and service web.

flowchart TD
    I["Service identity<br/>gateway-a / default / my-sandbox / web"]
    M["One gateway setting: service_hostname_format<br/>readable or hashed"]
    I --> L["Shared service label generator<br/>Hashed example: enh47uqyj7bpyttz"]
    M --> L
    L --> G["gateway_url<br/>https://enh47uqyj7bpyttz.gateway.example.com/"]
    L --> A["application_url<br/>https://enh47uqyj7bpyttz.apps.example.com/"]
    O["Configured application public origin<br/>https://apps.example.com"] --> A
    A -->|"Preferred when configured"| U["url returned to clients"]
    G -->|"Fallback when application_url is absent"| U
Loading

Hashed mode is shown above. Readable mode uses <workspace>--<sandbox>[--<service>] for both paths. The two access paths are alternatives; when their public origins match, their complete URLs match. Integrators consume discovery hostnames as returned.

Connecting the published URL to a sandbox

The proxy and example controller below are alternative discovery consumers, shown for context. This PR publishes URLs; it does not deploy either integration. Dashed arrows configure routing; solid arrows carry application traffic.

flowchart TD
    API["Service API<br/>Returns public application URL"] -.->|"URL used by client"| Client["Application client"]
    D["Discovery API<br/>Exact hostname → current supervisor Pod IP:port<br/>Installation identity and expiry"]

    D -.->|"Snapshots / watches"| P["Sandbox proxy<br/>TLS passthrough"]
    D -.->|"Snapshots / watches"| C["Example Kubernetes HTTPRoute controller<br/>Separate POC"]
    C -.->|"Reconciles HTTPRoutes, backend resources<br/>and backend TLS configuration"| K["Kubernetes Gateway<br/>Edge TLS termination"]

    Client -->|"Option A: HTTPS to published hostname"| P
    Client -->|"Option B: HTTPS to published hostname"| K
    P -->|"Application TLS forwarded unchanged"| S["Owning supervisor<br/>Application TLS listener"]
    K -->|"HTTPS to discovered endpoint<br/>Preserve application Host and backend SNI"| S
    S --> W["Declared service inside sandbox"]
Loading

Both paths keep application traffic out of the OpenShell gateway. The integrator provides DNS, certificates, and ingress configuration; discovery supplies backend changes and withdrawal/expiry information.

Release Notes

Testing

  • Hostname integration: 111 standalone application-URL-layer tests and 120 combined-stack routing/schema regressions passed, including shared shutdown fencing and ingress URL stability. Go SDK CI, strict Clippy for affected crates, protobuf/docs/Mermaid lint, and lockfile checks passed.
  • 40 focused combined-stack Rust regression tests cover listener routing, route-limit concurrency, shutdown fencing, advertisements, discovery, and proxy behavior.
  • Local k3d validated the Service removal with dedicated push/poll, abrupt shared-owner takeover, HTTP/WebSockets, network-policy denial, freshness/withdrawal, outage recovery, and disabled-listener gateway access. Workload identity and memory survived owner changes.
  • Real Go SDK snapshots/watches and workspace-restricted discovery credentials drove two proxy replicas; both followed Pod-IP endpoints, graceful owner handover, and route withdrawal without per-sandbox app Services.
  • Helm lint/unit/parser/coherence/scaling checks, Python lint/format/type checks, and topology assertions passed.

Live Kubernetes validation preceded integration of the latest listener hardening;
focused Rust regressions validate that final integration. New-head CI is pending.

Qualification limits

Live HA validation exercised supervisor process/Pod loss on a local k3d cluster. Whole-node failure, real network partitions, metric-driven HPA, sustained production load, and published release artifacts remain unqualified. Grant-file projection contributes to revocation propagation time. Both ingress paths now share the gateway hostname format and label generator. The same installation identity and public HTTPS domain/port preserve service URLs when switching ingress. Installation-status presentation (#4670) remains separate work. Live Kubernetes runs above preceded hostname integration; the naming and shutdown-fence integration is validated by focused Rust regressions.

The example Kubernetes HTTPRoute controller is a deferred compatibility POC outside this stack.

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Relevant implementation, configuration, and API documentation updated

PR dependency order: #4936 → #4940 → #4941 → #4956 → #4963 → #4964 → #4957 → #4958.

@copy-pr-bot

copy-pr-bot Bot commented Oct 27, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@github-actions

Copy link
Copy Markdown

@TaylorMutch
TaylorMutch added this pull request to stack #4942 October 27, 2026 02:54
@TaylorMutch
TaylorMutch force-pushed the feat/4953-authoritative-app-urls/TaylorMutch branch from a6d0833 to e6e1927 Compare October 27, 2026 03:15
@TaylorMutch
TaylorMutch force-pushed the feat/4667-service-discovery/TaylorMutch branch 2 times, most recently from 932643d to 6c83b66 Compare October 27, 2026 05:42
@TaylorMutch
TaylorMutch force-pushed the feat/4953-authoritative-app-urls/TaylorMutch branch from e6e1927 to 2574b9a Compare October 27, 2026 05:42
@TaylorMutch
TaylorMutch removed this pull request from stack #4942 October 27, 2026 05:45
@TaylorMutch
TaylorMutch added this pull request to stack #4965 October 27, 2026 05:46
@TaylorMutch
TaylorMutch removed this pull request from stack #4965 October 27, 2026 05:47
@TaylorMutch
TaylorMutch force-pushed the feat/4667-service-discovery/TaylorMutch branch from 6c83b66 to 755e4d1 Compare October 27, 2026 06:24
@TaylorMutch
TaylorMutch force-pushed the feat/4953-authoritative-app-urls/TaylorMutch branch 2 times, most recently from 70e365e to 30cf9ce Compare October 27, 2026 06:25
@TaylorMutch
TaylorMutch force-pushed the feat/4667-service-discovery/TaylorMutch branch 2 times, most recently from 0944ea2 to 8504067 Compare October 27, 2026 06:46
@TaylorMutch
TaylorMutch force-pushed the feat/4953-authoritative-app-urls/TaylorMutch branch from 30cf9ce to 6b2fe9c Compare October 27, 2026 06:46
@TaylorMutch
TaylorMutch force-pushed the feat/4667-service-discovery/TaylorMutch branch from 8504067 to feac6b4 Compare October 27, 2026 21:06
@TaylorMutch
TaylorMutch force-pushed the feat/4953-authoritative-app-urls/TaylorMutch branch 2 times, most recently from dae4a9d to 66220a7 Compare October 28, 2026 17:05
@TaylorMutch
TaylorMutch force-pushed the feat/4667-service-discovery/TaylorMutch branch 2 times, most recently from 0939a70 to cf5448a Compare October 28, 2026 22:52
@TaylorMutch
TaylorMutch force-pushed the feat/4953-authoritative-app-urls/TaylorMutch branch from 66220a7 to 3dc01d7 Compare October 28, 2026 22:52
@TaylorMutch
TaylorMutch force-pushed the feat/4667-service-discovery/TaylorMutch branch from cf5448a to d43f1ae Compare October 29, 2026 01:16
@TaylorMutch
TaylorMutch force-pushed the feat/4953-authoritative-app-urls/TaylorMutch branch from 3dc01d7 to 29befcd Compare October 29, 2026 01:16
@TaylorMutch
TaylorMutch force-pushed the feat/4667-service-discovery/TaylorMutch branch from d43f1ae to b8e0f49 Compare October 30, 2026 17:57
@TaylorMutch
TaylorMutch force-pushed the feat/4953-authoritative-app-urls/TaylorMutch branch 2 times, most recently from b71991c to ad8be4d Compare October 30, 2026 18:13
Signed-off-by: Taylor Mutch <taylormutch@gmail.com>
@TaylorMutch
TaylorMutch force-pushed the feat/4953-authoritative-app-urls/TaylorMutch branch from ad8be4d to 52300c8 Compare October 30, 2026 21:11
@TaylorMutch
TaylorMutch force-pushed the feat/4667-service-discovery/TaylorMutch branch from b8e0f49 to 088c1c3 Compare October 30, 2026 21:11

This branch has not been deployed

No deployments
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