Skip to content

feat: restructure instant-lite-api for open-source release#4

Merged
mastermanas805 merged 6 commits intomasterfrom
feat/oss-restructure
Apr 23, 2026
Merged

feat: restructure instant-lite-api for open-source release#4
mastermanas805 merged 6 commits intomasterfrom
feat/oss-restructure

Conversation

@mastermanas805
Copy link
Copy Markdown
Member

Prepares the repo to be open-sourced under MIT. Six atomic commits —
each self-contained and reviewable on its own.

Changes

  1. fd6f649 — Package restructure. 32 flat .go files at root move to
    internal/server/ with package server; a thin cmd/server/main.go
    imports and calls server.Run(). Embed assets (llms.txt,
    schema.sql, openapi.json) move alongside. Dockerfile updated
    to build ./cmd/server and COPY internal/server/schema.sql.

  2. 45a3251billing.go (981 LOC) split into focused files:
    billing_orders.go, billing_webhook.go, billing_subscriptions.go,
    and a trimmed billing.go holding shared helpers + the deprecated
    migrate shim + pure helpers (planConfig, normalizeCurrency,
    subscriptionStatusBlocksNew). No behaviour change.

  3. 66c8f59 — Parametrize hardcoded instanode.dev URLs. Three new
    ServerConfig fields (MarketingURL, CookieDomain,
    AllowedOrigins) and a new paths.go with route constants so path
    fragments aren't scattered as string literals. Marketing redirects
    fall through to 404 when MarketingURL is empty. Cookie domain is
    empty by default (host-only), correct for single-host + local dev.

  4. cfb7c9e — Extract Payment interface. Two shipping impls:
    razorpayPayment (production) and noopPayment (self-hosters
    without Razorpay). main.Run picks between them based on whether
    RAZORPAY_KEY_ID + RAZORPAY_KEY_SECRET are set. Billing
    endpoints return 503 via Configured() == false instead of crashing.
    Handler callsites replaced; liveRazorpay* functions kept for the
    reconciler's function-value plumbing so those tests pass unchanged.

  5. 7f8bcc1 — OSS scaffolding: LICENSE (MIT), rewritten README.md,
    CONTRIBUTING.md, Makefile, config.example.yaml,
    .github/workflows/ci.yml, .github/ISSUE_TEMPLATE/*,
    .github/pull_request_template.md. Fixed docker-compose.yml
    schema path after the package move.

  6. 7613cfegofmt -w across the package to satisfy the new CI
    workflow's formatting gate. Some pre-existing misalignments (struct
    tag columns, tab/space mixes, missing trailing newlines) picked up.

Verification

  • go build ./... — clean
  • go vet ./... — clean
  • gofmt -l . — empty
  • go test ./... — all pass
  • make lint — passes

Post-merge action items

  • Flip the GitHub repo to public
  • Rotate the NR license key and Razorpay test keys (still sitting
    in the private gtm-ops repo — treat as compromised)
  • Follow-ups deferred from this branch:
    - Email templates in internal/server/email.go still hard-code
    URLs; see the TODO(self-hoster) comment. Worth lifting to a
    proper templating layer after the first external contributor.
    - config.yaml is still tracked (now also in .gitignore); can
    be removed in a follow-up since config.example.yaml covers it.

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.
@mastermanas805 mastermanas805 merged commit a182600 into master Apr 23, 2026
1 check passed
@mastermanas805 mastermanas805 deleted the feat/oss-restructure branch April 23, 2026 17:21
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