refactor: extract all hardcoded URL/domain literals into internal/urls package#12
Merged
Merged
Conversation
…s package
User-facing pain that drove this: every domain rename or proxy hostname
tweak required scraping the codebase with grep + sed. The instant.dev →
instanode.dev rename earlier today touched 28 files and still missed
some (we're still finding stragglers). The "Use named constants, not
inline strings" memo applies — extracting was overdue.
New package internal/urls/urls.go centralises:
Public hostnames:
PublicAPIBase = "https://api.instanode.dev"
PublicMarketingBase = "https://instanode.dev"
StartURLPrefix = PublicMarketingBase + "/start"
DeploymentWildcard = "deployment.instanode.dev"
StoragePublicHost = "s3.instanode.dev"
Cluster-internal proxy FQDNs (for in-cluster workloads — friction PR #2):
InternalPGProxy = "instant-pg-proxy.instant.svc.cluster.local:5432"
InternalRedisProxy = "instant-redis-proxy.instant.svc.cluster.local:6379"
InternalMongoProxy = "instant-mongo-proxy.instant.svc.cluster.local:27017"
InternalNATSProxy = "instant-nats-proxy.instant.svc.cluster.local:4222"
InternalMinIO = "minio.instant-data.svc.cluster.local:9000"
Helper:
UpgradeStartURL(jwt) — canonical builder for /start?t=<jwt>, replaces
12 sites that had identical fmt.Sprintf calls.
Call sites refactored:
- 12 fmt.Sprintf upgrade-URL calls across 6 provisioning handlers
→ urls.UpgradeStartURL(jwtToken)
- proxiedInternalURL in handlers/internal_url.go → uses 4 urls.Internal*
- upgradeNote / limitExceededNote bare links → urls.StartURLPrefix
- canonicalAPIBase (handlers/auth.go) → alias of urls.PublicAPIBase
- defaultCanonicalResourceURL (middleware/auth.go) → alias of
urls.PublicAPIBase (eliminates the long-standing duplication of the
same string in two different files)
- 15 user-facing error strings ("Sign up at https://instanode.dev/start")
→ string concat with urls.StartURLPrefix
Audit results:
Before: 28+ occurrences of "instanode.dev/start" in non-test handler code
After: 1 occurrence (an inline example URL inside the OpenAPI JSON
description string — appropriate to leave as a literal since it's
sample documentation, not a runtime-constructed URL)
Before: 4 proxy FQDN string literals in handlers/internal_url.go
After: 0 (all 4 use urls.* constants)
Tests:
internal/urls/urls_test.go (12 sub-tests):
TestPublicHostnames_MatchExpectedShape — guards 5 public hosts
TestInternalProxyHostnames_CorrectPortsAndService — guards 5 internal
TestUpgradeStartURL_Composition — builder semantics
Existing tests still pass:
TestProxiedInternalURL — 7 sub-cases unchanged after refactor
TestUpgradeNote_DoesNotMentionTrial / TestLimitExceededNote_… — 6 cases
TestWhoami_*, TestDeployNew_EnvVars_*, all TestOpenAPI_* — pass
Live verification on v2.1.0-urls-package in prod:
POST /db/new (fresh) → upgrade host = "instanode.dev"
internal_url host = "instant-pg-proxy.instant.svc.cluster.local:5432"
note starts with "Works for 24h free"
GET /api/v1/whoami → 200 with team_id + plan_tier + team_name
(proves the middleware audience lookup still works
via the urls.PublicAPIBase alias)
Out of scope (separate follow-ups):
- Email templates in internal/email/email.go (45 occurrences) — these
are marketing copy strings with their own care; need different
extraction approach (probably a templated config).
- SDK references (sdk-go, sdk-node, mcp) — each is its own repo;
consolidating across modules needs a shared common/urls package and
cross-repo coordination.
- Worker / provisioner repos — they have far fewer URL string
instances and can do their own thing.
- The OpenAPI bearerAuth description's inline example URL — sample
documentation, not a runtime URL.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 tasks
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.
Summary
Every domain rename so far has been a multi-file sed sweep that missed corners. The `instant.dev → instanode.dev` rename touched 28 files and still left stragglers we're finding hours later. The "Use named constants, not inline strings" memo finally applies here.
New `internal/urls/urls.go` package centralises:
Call sites refactored
Audit before/after
Test plan
Out of scope (follow-ups noted in commit)
🤖 Generated with Claude Code