Repository navigation
fix!: register addresses a deployed solution can actually be reached at - #37
Merged
Merged
Conversation
A deployed solution registered `manifestUrl: http://localhost:8080/assets/mf-manifest.json` and upstream `http://localhost:8080` — its own listen address, via the PUBLIC_URL default — so the product showed "solution failed to load" and the gateway proxied the solution to itself. Both booted and looked healthy. - manifestUrl: with no PUBLIC_URL, register the root-relative path /assets/mf-manifest.json on the solution's own backend; the host resolves it against the route by which it reaches the solution. The runtime does not encode the host's route layout. BREAKING on the wire: the host must resolve a root-relative manifestUrl (the parallel module-saas-starter change). - upstream: take it from the reachable self endpoint Codefly injects as CODEFLY__SELF_ENDPOINT__<MODULE>__<SERVICE>__HTTP__HTTP (core v0.5.6), falling back to the listen address; SELF_UPSTREAM still overrides, PUBLIC_URL no longer feeds it. Labelled stopgap: the carrier is read by name in one helper until core/sdk-go release an accessor. - validate(): refuse a loopback upstream or PUBLIC_URL when CODEFLY__RUNTIME_CONTEXT names a deployed runtime (anything outside native/nix/container/free, e.g. a GitOps render's "kubernetes", core v0.5.6). Never keyed on the environment name. - exchange: only 401/403 name the SOLUTION_REGISTRATION_SECRETS provisioning; a 5xx reports "host unavailable (status N), retrying" with the gateway's body, other statuses a failure with their body; the heartbeat keeps retrying. - Manifest.Assets fs.FS: when set, /assets/ is served from it (nothing read from disk, so a read-only root filesystem works); else ASSETS_DIR as before. Content-hashed files are cached immutable, everything else and every non-file response no-cache. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
antoinetoussaint-byte
deleted the
fix/deployed-solution-registration
branch
September 24, 2026 00:16
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A deployed solution registered
manifestUrl: http://localhost:8080/assets/mf-manifest.jsonand upstreamhttp://localhost:8080. That is its own listen address, which it got through thePUBLIC_URLdefault. The product showed "solution failed to load", the gateway proxied the solution to itself, and the process still booted and looked healthy.What changes
frontendManifestURL). WhenPUBLIC_URLis unset,manifestUrlis/assets/mf-manifest.json, a path on the solution's own backend. The host resolves it against the route it uses to reach the solution. The runtime does not encode the host's route layout. An explicitPUBLIC_URLstill makes the URL absolute on that origin.selfUpstream/selfEndpoint). The gateway upstream comes from the self-endpoint carrier that core adds:CODEFLY__SELF_ENDPOINT__<MODULE>__<SERVICE>__HTTP__HTTP, normalised likeCODEFLY__ENDPOINT__. The existing selfCODEFLY__ENDPOINT__stays the listen address. If the carrier is absent, the upstream falls back to the listen address.SELF_UPSTREAMstill overrides it, andPUBLIC_URLno longer feeds it.validate()). A loopback upstream orPUBLIC_URLis refused in a deployed runtime context:localhost,*.localhost, loopback IPs, or the unspecified address.CODEFLY__RUNTIME_CONTEXT. The local kindsnative,nix,containerandfree(or unset) count as local. Any other value counts as deployed, for example thekubernetesvalue that core's GitOps render will inject.local-dogfood+kubernetesas refused andstaging+nativeas accepted.solutionCredential.exchange).401/403produce the "noSOLUTION_REGISTRATION_SECRETSentry / digest mismatch" message.5xxreportshost unavailable (status N), retrying: <gateway body>.Manifest.Assets fs.FS(additive). When it is set,/assets/is served withhttp.FileServerFSfrom it, so nothing is read from disk and a read-only root filesystem works. When it is nil,ASSETS_DIRworks as before. The CORS headers and content types are the same on both paths.immutable.no-cache, and so is any non-file response. This means a 404 for a hashed name is never cached for a year.README (configuration table, two new sections, exchange statuses) and AGENTS.md (the one
localhostliteral) are updated to match.Classification
selfEndpoint, commented "PENDING codefly-dev/core v0.5.6") until core/sdk-go release an accessor. The runtime-context signal is also pending core v0.5.6. Until a cell is rendered by that core, it has neither the carrier nor the signal: it falls back to the listen address and is not refused.Breaking (
!)This breaks on the wire, not in the Go API:
Manifest.Assetsis additive. A host has to resolve a root-relativemanifestUrl, which is the parallel module-saas-starter change. Against an older host, a solution on this version registers a manifest that host cannot load.Tests
TestManifestURLIsNeverTheListenAddress;TestServeRegistersOnListenPortnow asserts the relative path is served.TestSelfUpstreamIsTheReachableSelfEndpointandTestGatewayRegistrationCarriesTheReachableUpstream(the carrier reaches the wire).TestValidateRefusesLoopbackInADeployedRuntimeandTestLoopbackRefusalIgnoresTheEnvironmentName.TestSolutionExchangeBlamesTheCredentialOnlyWhenItWasJudged(401/403/500/502/503/429) andTestSolutionRegistrationKeepsRetryingAnUnavailableHost.TestAssetsServeFromTheManifestFS(ASSETS_DIR points at a missing dir),TestAssetsServeFromAssetsDirWithoutAnFSandTestAssetCacheControl.All four gate commands from AGENTS.md pass locally (
go mod verify,go test -race ./...,go vet,gofmt).Not verified
readOnlyRootFilesystem.kubernetesruntime-context value come from the coordinated core change, which was not released when this was written. If core ships different names,selfEndpointCarrierPrefixanddeployedRuntimeContextmust follow before this is tagged.🤖 Generated with Claude Code