feat(openviking): deploy maelstrom-ui Web Studio frontend
- Build/push image: the-seas.local.mk-labs.cloud/library/maelstrom-ui:v0.3.17-1 (upstream volcengine/openviking web-studio/, pinned to commit 3cd1d4e9) - Deployment + Service serving the static SPA via nginx (reverse-proxies /api, /health, /ready to openviking backend; /bot deliberately NOT proxied) - Ingress at maelstrom.local.mk-labs.cloud (TLS via letsencrypt-internal) - ExternalSecret wiring scoped maelstrom-ui-key from op://mk-labs/openviking/maelstrom-ui-key into the pod env (MAELSTROM_UI_KEY) Per approved plan: inbox/ryan/2026-08-14-maelstrom-ui-deployment-plan.md Key mint + approval: system/inbox/agents/nick-fury/2026-08-14-maelstrom-ui-key-mint-complete.md Ryan approval: inbox/ryan/2026-08-14-maelstrom-key-approval.md
This commit is contained in:
37
cluster/platform/openviking/deployment-maelstrom.yaml
Normal file
37
cluster/platform/openviking/deployment-maelstrom.yaml
Normal file
@@ -0,0 +1,37 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: maelstrom-ui
|
||||
namespace: openviking
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels: { app: maelstrom-ui }
|
||||
template:
|
||||
metadata:
|
||||
labels: { app: maelstrom-ui }
|
||||
spec:
|
||||
containers:
|
||||
- name: maelstrom-ui
|
||||
image: the-seas.local.mk-labs.cloud/library/maelstrom-ui:v0.3.17-1
|
||||
ports: [{ containerPort: 80 }]
|
||||
env:
|
||||
- name: MAELSTROM_UI_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: maelstrom-ui-credentials
|
||||
key: maelstrom_ui_key
|
||||
resources:
|
||||
requests: { cpu: 50m, memory: 64Mi }
|
||||
limits: { cpu: 200m, memory: 128Mi }
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: maelstrom-ui
|
||||
namespace: openviking
|
||||
spec:
|
||||
selector: { app: maelstrom-ui }
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
30
cluster/platform/openviking/externalsecret-maelstrom.yaml
Normal file
30
cluster/platform/openviking/externalsecret-maelstrom.yaml
Normal file
@@ -0,0 +1,30 @@
|
||||
# ExternalSecret - maelstrom-ui scoped API key
|
||||
# Per inbox/ryan/2026-08-14-maelstrom-key-approval.md: Ryan approved pre-seeding
|
||||
# via ExternalSecret (option b) since Ryan is the sole user of the pilot.
|
||||
# Scoped key (resources/search/tasks read-only, no bot/admin) minted by Nick Fury,
|
||||
# see system/inbox/agents/nick-fury/2026-08-14-maelstrom-ui-key-mint-complete.md
|
||||
apiVersion: external-secrets.io/v1beta1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: maelstrom-ui-credentials
|
||||
namespace: openviking
|
||||
annotations:
|
||||
argocd.argoproj.io/sync-wave: "-1"
|
||||
description: "Scoped read-only API key for maelstrom (Web Studio UI)"
|
||||
spec:
|
||||
refreshInterval: "1h"
|
||||
secretStoreRef:
|
||||
kind: ClusterSecretStore
|
||||
name: onepassword-connect
|
||||
target:
|
||||
name: maelstrom-ui-credentials
|
||||
creationPolicy: Owner
|
||||
template:
|
||||
engineVersion: v2
|
||||
data:
|
||||
maelstrom_ui_key: "{{ .MAELSTROM_UI_KEY }}"
|
||||
data:
|
||||
- secretKey: MAELSTROM_UI_KEY
|
||||
remoteRef:
|
||||
key: openviking
|
||||
property: maelstrom-ui-key
|
||||
25
cluster/platform/openviking/ingress-maelstrom.yaml
Normal file
25
cluster/platform/openviking/ingress-maelstrom.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: maelstrom-ui
|
||||
namespace: openviking
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||
spec:
|
||||
ingressClassName: nginx
|
||||
tls:
|
||||
- hosts:
|
||||
- maelstrom.local.mk-labs.cloud
|
||||
secretName: maelstrom-ui-tls
|
||||
rules:
|
||||
- host: maelstrom.local.mk-labs.cloud
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: maelstrom-ui
|
||||
port:
|
||||
number: 80
|
||||
25
cluster/platform/openviking/maelstrom-ui/Dockerfile
Normal file
25
cluster/platform/openviking/maelstrom-ui/Dockerfile
Normal file
@@ -0,0 +1,25 @@
|
||||
# maelstrom-ui — OpenViking Web Studio static frontend
|
||||
# Built per finalized plan: inbox/ryan/2026-08-14-maelstrom-ui-deployment-plan.md (Option B)
|
||||
#
|
||||
# Source: volcengine/openviking upstream, subdirectory web-studio/, pinned to
|
||||
# commit 3cd1d4e9acdfcc2567fd78da95339c3b18936c1c (2026-08-14).
|
||||
# NOT vendored into this repo (GitOps manifests stay app-source-free) — the
|
||||
# build context is the upstream web-studio/ directory checked out at that
|
||||
# commit. Image built + pushed manually for this deployment; see
|
||||
# system/inbox/agents/peter-parker/ for the build log if promoted to CI.
|
||||
#
|
||||
# Stage 1: build the SPA
|
||||
FROM node:22-alpine AS build
|
||||
WORKDIR /app
|
||||
COPY web-studio/package.json web-studio/package-lock.json* web-studio/pnpm-lock.yaml* ./
|
||||
RUN if [ -f pnpm-lock.yaml ]; then corepack enable && corepack prepare pnpm@latest --activate && pnpm install --no-frozen-lockfile && pnpm approve-builds --all || true; \
|
||||
else npm ci; fi
|
||||
COPY web-studio/ .
|
||||
RUN if [ -f pnpm-lock.yaml ]; then pnpm run build; else npm run build; fi
|
||||
|
||||
# Stage 2: serve with nginx, proxying /api/, /health, /ready to the openviking Service.
|
||||
# /bot/ is deliberately NOT proxied (bot.enabled: false, defense-in-depth per plan §2).
|
||||
FROM nginx:alpine
|
||||
COPY --from=build /app/dist /usr/share/nginx/html
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||
EXPOSE 80
|
||||
34
cluster/platform/openviking/maelstrom-ui/nginx.conf
Normal file
34
cluster/platform/openviking/maelstrom-ui/nginx.conf
Normal file
@@ -0,0 +1,34 @@
|
||||
# maelstrom-ui nginx config
|
||||
# Per plan §2: proxy /api/, /health, /ready to the openviking Service.
|
||||
# /bot/ is deliberately NOT proxied — bot stays disabled (scope decision #3);
|
||||
# any Web Studio call to /bot/v1/* 404s at this layer instead of reaching a disabled backend.
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
location /api/ {
|
||||
proxy_pass http://openviking.openviking.svc.cluster.local:1933/api/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
location /health {
|
||||
proxy_pass http://openviking.openviking.svc.cluster.local:1933/health;
|
||||
proxy_set_header Host $host;
|
||||
}
|
||||
|
||||
location /ready {
|
||||
proxy_pass http://openviking.openviking.svc.cluster.local:1933/ready;
|
||||
proxy_set_header Host $host;
|
||||
}
|
||||
|
||||
# bot stays disabled — no proxy for /bot/, static 404 by default nginx behavior.
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user