mirror of
https://github.com/hanzoai/agency.git
synced 2026-11-02 19:13:28 +00:00
The onboarding checkout POSTed the mint straight from the browser to commerce /v1/checkout/sessions. commerce v1.46.4 (P0) closed that anonymous path, so the browser POST now 401s and checkout is broken. Fix: a small stdlib-only Go server (server/) serves the embedded Vite SPA AND a single server-side checkout entry POST /v1/checkout. The browser holds no token and can choose no org/price/redirect — it only names a plan. The BFF calls commerce with a per-org Published storefront token from KMS; org is derived from the token, prices from the server-side plans map, success/cancel URLs from PUBLIC_BASE_URL (https://hanzo.agency). Fails closed (503) without the token — never an anon mint. - server/main.go, checkout.go, spa.go, embed.go — BFF + SPA server - server/checkout_test.go — authed mint, no client override, fail-closed, wire - src/lib/commerce.ts — browser now calls same-origin /v1/checkout - Dockerfile — node build (dist) -> go build (embed) -> alpine - pairs with commerce v1.46.7 (adds hanzo.agency to the redirect allowlist)
43 lines
1.8 KiB
Docker
43 lines
1.8 KiB
Docker
# Hanzo Agency — SPA + server-side checkout BFF, one image.
|
|
#
|
|
# NOTE: agency is no longer a pure static SPA (it was served by ghcr.io/hanzoai/spa).
|
|
# The onboarding checkout needs a server-side authed BFF holding a KMS storefront
|
|
# token — a static server cannot hold a secret — so agency now ships a small Go
|
|
# server that serves the embedded SPA AND the /v1/checkout BFF. Same pattern as
|
|
# the commerce checkout binary.
|
|
#
|
|
# Stage 1 builds the Vite SPA. Stage 2 embeds that bundle into a static Go binary.
|
|
# Stage 3 is a minimal runtime.
|
|
|
|
# ─── Stage 1: build the Vite SPA ──────────────────────────────────────────────
|
|
FROM node:22-alpine AS spa
|
|
WORKDIR /app
|
|
RUN corepack enable
|
|
COPY package.json pnpm-lock.yaml ./
|
|
RUN pnpm install --frozen-lockfile
|
|
COPY . .
|
|
RUN pnpm build
|
|
|
|
# ─── Stage 2: build the Go server with the SPA embedded ───────────────────────
|
|
FROM golang:1.26-alpine AS server
|
|
WORKDIR /src
|
|
COPY go.mod ./
|
|
COPY server/ ./server/
|
|
# Overwrite the committed placeholder with the real Vite output so go:embed
|
|
# ships the hashed assets.
|
|
RUN rm -rf ./server/static && mkdir -p ./server/static
|
|
COPY --from=spa /app/dist/ ./server/static/
|
|
ARG VERSION=""
|
|
RUN CGO_ENABLED=0 GOOS=linux go build -trimpath \
|
|
-ldflags="-s -w -X main.version=${VERSION}" \
|
|
-o /out/agency ./server
|
|
|
|
# ─── Stage 3: runtime ─────────────────────────────────────────────────────────
|
|
FROM alpine:3.21
|
|
RUN apk add --no-cache ca-certificates && adduser -D -u 10001 app
|
|
USER app
|
|
COPY --from=server /out/agency /usr/local/bin/agency
|
|
ENV PORT=3000
|
|
EXPOSE 3000
|
|
ENTRYPOINT ["/usr/local/bin/agency"]
|