feat: restructure instant-lite-api for open-source release#4
Merged
mastermanas805 merged 6 commits intomasterfrom Apr 23, 2026
Merged
feat: restructure instant-lite-api for open-source release#4mastermanas805 merged 6 commits intomasterfrom
mastermanas805 merged 6 commits intomasterfrom
Conversation
Prepares the repo for open-sourcing. The 32-file flat root of package main moves wholesale to internal/server with no logic changes — just package rename and the main() → Run() conversion needed so cmd/server can import it. - cmd/server/main.go: thin entrypoint that calls server.Run() - internal/server/*: all former root .go files (auth, billing, handlers, config, observability, postgres, redis, reaper, ratelimit, dashboard, openapi, email, inbound, razorpay). Tests move alongside their sources and stay package-private. - //go:embed assets (llms.txt, schema.sql, openapi.json) move into internal/server alongside the files that embed them. - Dockerfile: build ./cmd/server and COPY internal/server/schema.sql. go build ./..., go vet ./..., go test ./... all pass.
billing.go was 981 LOC doing orders, webhooks, subscriptions, migration, and shared helpers all at once. Split into: - billing_orders.go (121 LOC): CreateOrder flow + planPricing - billing_webhook.go (340 LOC): Razorpay webhook dispatcher, payment.captured, signature verification, payment-failed emails - billing_subscriptions.go (364 LOC): Create + lifecycle (activated/charged/halted/cancelled/completed) - billing.go (184 LOC): shared helpers (userIDFromNotes, unixToTime, periodFromSubscription), pure helpers (planConfig, normalizeCurrency, pickPlanID, subscriptionStatusBlocksNew), deprecated migrate shim No behaviour change — same package, same symbols, content preserved line-for-line. go build / go vet / go test all pass.
Three new ServerConfig fields + a paths.go constants file so self-hosters can point the binary at their own marketing site and cookie domain without patching Go source. ServerConfig additions: - MarketingURL: public website host for post-OAuth redirects, upgrade links, email CTAs. Empty = marketing redirects 404. - CookieDomain: session cookie Domain attribute. Empty = scoped to API host (right default for single-host + local dev). - AllowedOrigins: exact-match CORS allowlist, iterated instead of hardcoded switch. Replaced call sites use these plus new route-path constants (pathMarketingDashboard, pathMarketingPricing, pathAPIWebhookReceive etc.) so URL fragments aren't scattered as string literals. Also: - Email FromAddress default: no-reply@instanode.dev → no-reply@example.com (config-driven already; neutralising the baked-in default) - User-visible "contact contact@instanode.dev" error strings → "contact support" (brand-neutral) - handlers.go: removed the instanode.dev→api.instanode.dev receive-URL swap (redundant once BaseURL is configured correctly) - email.go: TODO comment flagging the remaining URL/brand hardcoding in HTML templates — deferred to a proper templating abstraction. go build / go vet / go test all pass. Only remaining instanode.dev references are in email templates (TODO'd) and test fixtures.
Introduces a Payment interface (internal/server/payment.go) with two shipping implementations: - razorpayPayment (razorpay_client.go): wraps razorpay-go, runs each SDK call in a goroutine and selects on ctx.Done so the 15s timeouts the handlers pass in actually land on the wire. - noopPayment (payment_noop.go): returns ErrPaymentNotConfigured from every call so self-hosters can run the API (provisioning, auth, webhooks) without signing up for Razorpay. main.Run picks between them based on RAZORPAY_KEY_ID + RAZORPAY_KEY_SECRET being set. Endpoints that require billing now check s.payment.Configured() up-front and return 503 when the noop is installed. Handler callsites replaced: - billing_orders.go: newRazorpayClient → s.payment.CreateOrder - billing_webhook.go: signature check → s.payment.VerifyWebhookSignature; 3× Order.Fetch → s.payment.FetchOrder - billing_subscriptions.go: goroutine+select pattern → s.payment.CreateSubscription (pattern now lives inside the impl) - main.go: /debug/razorpay-ping → /debug/payment-ping using s.payment.ListSubscriptions Kept for backwards compat: - liveRazorpayCreateSub / liveRazorpayCancelSub (used by the reconciler as function values) continue to call newRazorpayClient directly. Tests in billing_razorpay_sdk_test.go still pass unchanged. - s.computeSignature method retained for unit tests that sign fixture webhook bodies; production code uses VerifyWebhookSignature. go build / go vet / go test all pass.
Everything needed to open-source the repo without losing context:
- LICENSE (MIT)
- README.md: rewritten — one-curl demo up top, what ships today,
docker + bare-go quick starts, project layout, endpoint table,
links to CONTRIBUTING + LICENSE
- CONTRIBUTING.md: dev setup, test commands, code layout tour,
PR conventions, code style
- Makefile: run / build / test / vet / fmt / lint / docker targets
- config.example.yaml: sanitised template with env-override notes
per field — points self-hosters at the values they must set
- .github/workflows/ci.yml: go vet + gofmt check + go test + build
- .github/ISSUE_TEMPLATE/{bug,feature}.md + pull_request_template.md
Also:
- .gitignore: add bin/, config.yaml, IDE noise; remove stale
"single binary" comment
- docker-compose.yml: fix schema.sql path (moved to
internal/server/ with the package restructure)
go build / go vet / go test pass; no code changes.
Brings every .go file under gofmt's rules — some files had pre-existing misalignments (struct tag columns, tab/space mixes in const blocks, missing trailing newlines) that the OSS CI workflow now catches. No code changes.
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.
Prepares the repo to be open-sourced under MIT. Six atomic commits —
each self-contained and reviewable on its own.
Changes
fd6f649 — Package restructure. 32 flat
.gofiles at root move tointernal/server/withpackage server; a thincmd/server/main.goimports and calls
server.Run(). Embed assets (llms.txt,schema.sql,openapi.json) move alongside.Dockerfileupdatedto build
./cmd/serverand COPYinternal/server/schema.sql.45a3251 —
billing.go(981 LOC) split into focused files:billing_orders.go,billing_webhook.go,billing_subscriptions.go,and a trimmed
billing.goholding shared helpers + the deprecatedmigrate shim + pure helpers (
planConfig,normalizeCurrency,subscriptionStatusBlocksNew). No behaviour change.66c8f59 — Parametrize hardcoded
instanode.devURLs. Three newServerConfigfields (MarketingURL,CookieDomain,AllowedOrigins) and a newpaths.gowith route constants so pathfragments aren't scattered as string literals. Marketing redirects
fall through to 404 when
MarketingURLis empty. Cookie domain isempty by default (host-only), correct for single-host + local dev.
cfb7c9e — Extract
Paymentinterface. Two shipping impls:razorpayPayment(production) andnoopPayment(self-hosterswithout Razorpay).
main.Runpicks between them based on whetherRAZORPAY_KEY_ID+RAZORPAY_KEY_SECRETare set. Billingendpoints return 503 via
Configured() == falseinstead of crashing.Handler callsites replaced;
liveRazorpay*functions kept for thereconciler's function-value plumbing so those tests pass unchanged.
7f8bcc1 — OSS scaffolding:
LICENSE(MIT), rewrittenREADME.md,CONTRIBUTING.md,Makefile,config.example.yaml,.github/workflows/ci.yml,.github/ISSUE_TEMPLATE/*,.github/pull_request_template.md. Fixeddocker-compose.ymlschema path after the package move.
7613cfe —
gofmt -wacross the package to satisfy the new CIworkflow's formatting gate. Some pre-existing misalignments (struct
tag columns, tab/space mixes, missing trailing newlines) picked up.
Verification
go build ./...— cleango vet ./...— cleangofmt -l .— emptygo test ./...— all passmake lint— passesPost-merge action items
in the private
gtm-opsrepo — treat as compromised)- Email templates in
internal/server/email.gostill hard-codeURLs; see the
TODO(self-hoster)comment. Worth lifting to aproper templating layer after the first external contributor.
-
config.yamlis still tracked (now also in.gitignore); canbe removed in a follow-up since
config.example.yamlcovers it.