feat: add reader vote widget and vote-service
The skills-review desk is static, so "which draft would you ship?" needs a stateful counterpart. vote-service is a small Go API on its own pod backed by a JSON file on a ReadWriteOnce PVC, with one active vote per skill per source IP as the anti-abuse rule and CORS (ALLOWED_ORIGIN) as the caller boundary. Deployment notes that differ from the obvious path, all confirmed against the live cluster: the image is side-loaded with `ctr image import` plus `imagePullPolicy: Never` because kubelet has no credentials for the Nexus ref; the pod is pinned to `kubernets` because the hostpath PV takes a nodeAffinity for whichever node first binds it; and public exposure is Caddy on the VPS, not the cloudflared tunnel. The ingress controller runs with `use-forwarded-headers` off, so nginx overwrites X-Forwarded-For with its own peer — every visitor would collapse into one voter and each skill would cap at one vote overall. Caddy stamps the true remote address into X-Client-IP, which nginx forwards untouched, and clientIP() reads that first. Scoped to this app rather than flipping the global flag, which would change client-IP handling for every other ingress. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
# Public exposure is required: the vote widget runs in each visitor's
|
||||
# browser (client-side JS on a static Pages site), so it calls this API
|
||||
# straight from the internet — it cannot reach a cluster-internal-only
|
||||
# Service. CORS (ALLOWED_ORIGIN in deployment.yaml) is the real boundary:
|
||||
# it restricts which origin's browser code may call the API, not which
|
||||
# network can reach it.
|
||||
#
|
||||
# No `tls:` block here on purpose: TLS is terminated upstream by Caddy on the
|
||||
# Oracle VPS, which reverse-proxies over Tailscale to this node's port 80
|
||||
# (the nginx ingress runs on hostNetwork and routes by Host). That is how all
|
||||
# ~21 public hosts in this account are served. Reaching this host publicly
|
||||
# needs the DNS record plus the Caddy block — see vote-service/README.md:
|
||||
# cf-dns add ai-for-dummies-vote A 129.148.56.8
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: ai-for-dummies-vote
|
||||
namespace: ai-for-dummies
|
||||
spec:
|
||||
ingressClassName: public
|
||||
rules:
|
||||
- host: ai-for-dummies-vote.marcospaulo.dev.br
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: ai-for-dummies-vote
|
||||
port:
|
||||
number: 80
|
||||
Reference in New Issue
Block a user