Serve compliance-portal instead of trust

Embed and build @probo/compliance-portal for the
/trust path and custom-domain SPA so production
ships the v2 portal. Keep apps/trust in the repo
for local use on port 5175; portal takes 5174.

Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
Émile Ré
2026-07-20 17:38:45 +02:00
parent 70d0424022
commit 26595b724f
18 changed files with 96 additions and 60 deletions

View File

@@ -18,7 +18,7 @@
# ── Base URL & ports ──────────────────────────────────────────────────
# PROBOD_BASE_URL=http://localhost:8080
# PROBOD_API_ADDR=:8080
# PROBOD_API_CORS_ALLOWED_ORIGINS=http://localhost:8080,http://localhost:5173,http://localhost:5174
# PROBOD_API_CORS_ALLOWED_ORIGINS=http://localhost:8080,http://localhost:5173,http://localhost:5174,http://localhost:5175
# PROBOD_TRUST_CENTER_HTTP_ADDR=:10080
# PROBOD_TRUST_CENTER_HTTPS_ADDR=:10443

View File

@@ -32,16 +32,16 @@ jobs:
run: |
npm --workspace @probo/console run check
NODE_ENV=production npm --workspace @probo/console run build
- name: "Build trust"
- name: "Build compliance-portal"
run: |
npm --workspace @probo/trust run check
NODE_ENV=production npm --workspace @probo/trust run build
npm --workspace @probo/compliance-portal run check
NODE_ENV=production npm --workspace @probo/compliance-portal run build
- uses: "actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a" # v7
with:
name: "frontend-apps"
path: |
apps/console/dist/
apps/trust/dist/
apps/compliance-portal/dist/
packages/emails/dist/
retention-days: 1
@@ -245,8 +245,9 @@ jobs:
node: "false"
- name: "Create placeholder dist files"
run: |
mkdir -p apps/console/dist apps/trust/dist packages/emails/dist
mkdir -p apps/console/dist apps/compliance-portal/dist apps/trust/dist packages/emails/dist
echo dev-server > apps/console/dist/index.html
echo dev-server > apps/compliance-portal/dist/index.html
echo dev-server > apps/trust/dist/index.html
echo dev-server > packages/emails/dist/placeholder
- name: "Generate Go code"
@@ -309,8 +310,9 @@ jobs:
- uses: reviewdog/action-setup@d8a7baabd7f3e8544ee4dbde3ee41d0011c3a93f # v1.5.0
- name: "Create placeholder dist files"
run: |
mkdir -p apps/console/dist apps/trust/dist packages/emails/dist
mkdir -p apps/console/dist apps/compliance-portal/dist apps/trust/dist packages/emails/dist
echo dev-server > apps/console/dist/index.html
echo dev-server > apps/compliance-portal/dist/index.html
echo dev-server > apps/trust/dist/index.html
echo dev-server > packages/emails/dist/placeholder
- name: "Generate Go code"
@@ -369,7 +371,7 @@ jobs:
env:
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
for dir in apps/console apps/trust packages/ui packages/eslint-config; do
for dir in apps/console apps/trust apps/compliance-portal packages/ui packages/eslint-config; do
(cd "$dir" && npx eslint . --concurrency 4 --format stylish 2>/dev/null) | \
reviewdog -f=eslint -reporter=github-pr-review -filter-mode=nofilter -name="eslint ($dir)" || true
done
@@ -387,8 +389,9 @@ jobs:
- uses: "./.github/actions/setup"
- name: "Create placeholder dist files"
run: |
mkdir -p apps/console/dist apps/trust/dist
mkdir -p apps/console/dist apps/compliance-portal/dist apps/trust/dist
echo dev-server > apps/console/dist/index.html
echo dev-server > apps/compliance-portal/dist/index.html
echo dev-server > apps/trust/dist/index.html
- run: "npm --workspace @probo/emails run build"
- run: "make test"

View File

@@ -28,16 +28,16 @@ jobs:
run: |
npm --workspace @probo/console run check
NODE_ENV=production npm --workspace @probo/console run build
- name: "Build trust"
- name: "Build compliance-portal"
run: |
npm --workspace @probo/trust run check
NODE_ENV=production npm --workspace @probo/trust run build
npm --workspace @probo/compliance-portal run check
NODE_ENV=production npm --workspace @probo/compliance-portal run build
- uses: "actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a" # v7
with:
name: "frontend-apps"
path: |
apps/console/dist/
apps/trust/dist/
apps/compliance-portal/dist/
packages/emails/dist/
retention-days: 1

View File

@@ -5,7 +5,7 @@ Each release track now keeps its own changelog. The history below 0.173.0 of the
## Per-track changelogs
- `prb` (CLI) — [cmd/prb/CHANGELOG.md](cmd/prb/CHANGELOG.md)
- `probod` (server, including bundled `@probo/console`, `@probo/trust`, `@probo/ui`) — [cmd/probod/CHANGELOG.md](cmd/probod/CHANGELOG.md)
- `probod` (server, including bundled `@probo/console`, `@probo/compliance-portal`, `@probo/ui`) — [cmd/probod/CHANGELOG.md](cmd/probod/CHANGELOG.md)
- `probod-bootstrap` — [cmd/probod-bootstrap/CHANGELOG.md](cmd/probod-bootstrap/CHANGELOG.md)
- `@probo/n8n-nodes-probo` — [packages/n8n-node/CHANGELOG.md](packages/n8n-node/CHANGELOG.md)
- `@probo/cookie-banner` — [packages/cookie-banner/CHANGELOG.md](packages/cookie-banner/CHANGELOG.md)

View File

@@ -71,6 +71,7 @@ GENERATED= pkg/server/api/connect/v1/schema/schema.go \
pkg/server/api/mcp/v1/types/types.go
EMBEDDED= apps/console/dist/index.html \
apps/compliance-portal/dist/index.html \
apps/trust/dist/index.html \
@probo/emails
@@ -94,7 +95,7 @@ ifdef WITH_APPS
GENERATED += relay
EMBEDDED += \
@probo/console \
@probo/trust
@probo/compliance-portal
endif
.PHONY: all
@@ -210,7 +211,7 @@ cfg/dev.yaml: bin/probod-bootstrap $(CFG_DEV_OAUTH2_KEY) compose/pebble/certs/ro
PROBOD_AUTH_PASSWORD_PEPPER="this-is-a-secure-pepper-for-password-hashing-at-least-32-bytes"; \
PROBOD_AUTH_COOKIE_SECURE=false; \
PROBOD_OAUTH2_SERVER_SIGNING_KEY="$$($(CAT) $(CFG_DEV_OAUTH2_KEY))"; \
PROBOD_API_CORS_ALLOWED_ORIGINS="http://localhost:8080,http://localhost:5173,http://localhost:5174"; \
PROBOD_API_CORS_ALLOWED_ORIGINS="http://localhost:8080,http://localhost:5173,http://localhost:5174,http://localhost:5175"; \
PROBOD_PG_ADDR=localhost:5432; \
PROBOD_PG_USERNAME=postgres; \
PROBOD_PG_PASSWORD=postgres; \
@@ -333,6 +334,12 @@ pkg/server/api/trust/v1/schema.graphql: pkg/server/api/trust/v1/graphql $(TRUST_
$(NPM) --workspace $@ run check
$(NPM) --workspace $@ run build
.PHONY: @probo/compliance-portal
@probo/compliance-portal: NODE_ENV=production
@probo/compliance-portal: relay
$(NPM) --workspace $@ run check
$(NPM) --workspace $@ run build
.PHONY: generate
generate: $(GENERATED)
@@ -385,7 +392,7 @@ fmt-go: ## Format Go code
clean: ## Clean the project (node_modules and build artifacts)
$(RM) -rf bin/*
$(RM) -rf node_modules
$(RM) -rf apps/{console,trust}/{dist,node_modules}
$(RM) -rf apps/{console,trust,compliance-portal}/{dist,node_modules}
$(RM) -rf packages/emails/{dist,node_modules}
$(RM) -rf sbom-docker.json sbom.json
$(RM) -rf coverage.out coverage.html coverage-e2e.out coverage-e2e.html coverage-combined.out coverage-combined.html
@@ -433,7 +440,7 @@ compose/keycloak/probo-realm.json: compose/keycloak/probo-realm.json.tmpl compos
-e "s|PRIVATE_KEY_PLACEHOLDER|$$(awk 'NR==1 {printf "%s", $$0; next} {printf "\\\\n%s", $$0}' compose/keycloak/certs/private-key.pem)|g" \
$@.tmpl > $@
apps/console/dist/index.html apps/trust/dist/index.html:
apps/console/dist/index.html apps/compliance-portal/dist/index.html apps/trust/dist/index.html:
$(MKDIR) $(dir $@)
$(ECHO) dev-server > $@

View File

@@ -0,0 +1,26 @@
// Copyright (c) 2025-2026 Probo Inc <hello@probo.com>.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
package complianceportalstatics
import "embed"
//go:embed dist
var StaticFiles embed.FS

View File

@@ -4,7 +4,7 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite --port 5175",
"dev": "vite --port 5174",
"build": "tsc -b && vite build",
"check": "tsc --noEmit -p tsconfig.app.json",
"preview": "vite preview"

View File

@@ -55,7 +55,7 @@ export default defineConfig({
},
base: "./",
server: {
port: 5175,
port: 5174,
proxy: {
"^/trust/[^/]+/api": {
target: "http://localhost:8080",

View File

@@ -4,7 +4,7 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite --port 5174",
"dev": "vite --port 5175",
"build": "tsc -b && vite build",
"check": "tsc --noEmit -p tsconfig.app.json",
"preview": "vite preview"

View File

@@ -39,7 +39,7 @@ export default defineConfig({
},
base: "./",
server: {
port: 5174,
port: 5175,
proxy: {
"^/trust/[^/]+/api": {
target: "http://localhost:8080",

View File

@@ -1,6 +1,6 @@
# Changelog
All notable changes to `probod` (the server, including the bundled `@probo/console`, `@probo/trust`, and `@probo/ui` frontends) will be documented in this file.
All notable changes to `probod` (the server, including the bundled `@probo/console`, `@probo/compliance-portal`, and `@probo/ui` frontends) will be documented in this file.
## Unreleased

View File

@@ -53,9 +53,9 @@ track's paths:
git log $(git describe --tags --abbrev=0 --match='prb/v*')..HEAD --oneline \
-- cmd/prb pkg/cli pkg/cmd
# probod (server group: probod + console + trust + ui)
# probod (server group: probod + console + compliance-portal + ui)
git log $(git describe --tags --abbrev=0 --match='probod/v*')..HEAD --oneline \
-- cmd/probod apps/console apps/trust packages/ui pkg
-- cmd/probod apps/console apps/compliance-portal packages/ui pkg
# probod-bootstrap
git log $(git describe --tags --abbrev=0 --match='probod-bootstrap/v*')..HEAD --oneline \

View File

@@ -1,8 +1,8 @@
# Release `probod` (server group)
This track ships `probod`, `@probo/console`, `@probo/trust`, and
`@probo/ui` together as the Docker image and accompanying binary archive.
They share the same version.
This track ships `probod`, `@probo/console`, `@probo/compliance-portal`,
and `@probo/ui` together as the Docker image and accompanying binary
archive. They share the same version.
After confirming commits below, follow the
[common steps](./README.md#3-common-steps-every-track).
@@ -15,13 +15,13 @@ After confirming commits below, follow the
- **Changelog**: `cmd/probod/CHANGELOG.md` (covers all four components)
- **Files to stage**: `cmd/probod/VERSION`, `cmd/probod/CHANGELOG.md`
- **Workflow**: `.github/workflows/release-probod.yaml`
- **Path filter**: `cmd/probod apps/console apps/trust packages/ui pkg`
- **Path filter**: `cmd/probod apps/console apps/compliance-portal packages/ui pkg`
## Detect commits
```shell
git log $(git describe --tags --abbrev=0 --match='probod/v*')..HEAD --oneline \
-- cmd/probod apps/console apps/trust packages/ui pkg
-- cmd/probod apps/console apps/compliance-portal packages/ui pkg
```
If empty or non-user-facing only, do not release this track.
@@ -29,7 +29,7 @@ If empty or non-user-facing only, do not release this track.
## Notes
The changelog covers changes across all four components (`probod`,
`@probo/console`, `@probo/trust`, `@probo/ui`).
`@probo/console`, `@probo/compliance-portal`, `@probo/ui`).
CI builds the frontends and Go binaries, builds and pushes the
multi-arch image to `artifact.probo.inc/probo/probo:v<version>` (and

View File

@@ -35,9 +35,9 @@ make sandbox-delete
After `make sandbox-status`, use the VM IP to access services from the host:
| Service | URL |
| ---------- | --------------------------- |
| ------------------ | --------------------------- |
| Console | `http://<vm-ip>:5173` |
| Trust | `http://<vm-ip>:5174` |
| Compliance Portal | `http://<vm-ip>:5174` |
| API | `http://<vm-ip>:8080` |
| Grafana | `http://<vm-ip>:3001` |
| Mailpit | `http://<vm-ip>:8025` |
@@ -49,7 +49,7 @@ After `make sandbox-status`, use the VM IP to access services from the host:
During provisioning, the sandbox automatically generates:
- **`/etc/probod/config.yml`** — probod config with the VM IP as cookie domain, `secure: false`, and correct CORS origins
- **`apps/console/.env`** and **`apps/trust/.env`** — `VITE_API_URL` pointing to the VM IP
- **`apps/console/.env`** and **`apps/compliance-portal/.env`** — `VITE_API_URL` pointing to the VM IP
Probod config is at `/etc/probod/config.yml`.
@@ -71,17 +71,17 @@ This file is sourced during provisioning before `probod-bootstrap` runs. Any var
The sandbox provisions four systemd services:
| Service | Description | Starts on boot |
| --------------- | ---------------------------------------------------------- | -------------- |
| -------------------------- | ---------------------------------------------------------- | -------------- |
| `probo-stack` | Docker Compose stack (Postgres, SeaweedFS, Keycloak, etc.) | Yes |
| `probod` | Probo API server (depends on `probo-stack`) | No |
| `probo-console` | Console frontend dev server | No |
| `probo-trust` | Trust frontend dev server | No |
| `probo-compliance-portal` | Compliance portal frontend dev server | No |
`probo-stack` starts automatically when the VM boots. `probod`, `probo-console`, and `probo-trust` must be started manually after building.
`probo-stack` starts automatically when the VM boots. `probod`, `probo-console`, and `probo-compliance-portal` must be started manually after building.
Manage them with `systemctl`:
```bash
./contrib/lima/sandbox.sh exec -- sudo systemctl start probod probo-console probo-trust
./contrib/lima/sandbox.sh exec -- sudo systemctl start probod probo-console probo-compliance-portal
./contrib/lima/sandbox.sh exec -- sudo systemctl stop probod
./contrib/lima/sandbox.sh exec -- sudo systemctl restart probod
./contrib/lima/sandbox.sh exec -- sudo systemctl status probod

View File

@@ -22,12 +22,12 @@ brew install lima jq
# Build the backend binary (probo-stack starts automatically on boot)
./contrib/lima/sandbox.sh exec -- make build
# Start probod, the console, and the trust dev servers
./contrib/lima/sandbox.sh exec -- sudo systemctl start probod probo-console probo-trust
# Start probod, the console, and the compliance-portal dev servers
./contrib/lima/sandbox.sh exec -- sudo systemctl start probod probo-console probo-compliance-portal
# Access services from your host browser using the VM IP
# e.g. http://192.168.105.2:5173 (console)
# e.g. http://192.168.105.2:5174 (trust)
# e.g. http://192.168.105.2:5174 (compliance-portal)
# e.g. http://192.168.105.2:8080 (API)
```

View File

@@ -141,7 +141,7 @@ cat > /etc/systemd/system/probo-node-modules.service << EOF
[Unit]
Description=Bind-mount VM-local node_modules over workspace
DefaultDependencies=no
Before=probo-console.service probo-trust.service
Before=probo-console.service probo-compliance-portal.service
[Service]
Type=oneshot
@@ -168,7 +168,7 @@ make -C /workspace generate WITH_APPS=1
make -C /workspace embed
echo "VITE_API_URL=http://${VM_IP}:8080" > /workspace/apps/console/.env
echo "VITE_API_URL=http://${VM_IP}:8080" > /workspace/apps/trust/.env
echo "VITE_API_URL=http://${VM_IP}:8080" > /workspace/apps/compliance-portal/.env
# Install systemd services for the sandbox
cat > /etc/systemd/system/probo-stack.service << EOF
@@ -229,9 +229,9 @@ RestartSec=3s
WantedBy=multi-user.target
EOF
cat > /etc/systemd/system/probo-trust.service << EOF
cat > /etc/systemd/system/probo-compliance-portal.service << EOF
[Unit]
Description=Probo Trust Dev Server
Description=Probo Compliance Portal Dev Server
Requires=probo-node-modules.service
After=probo-node-modules.service probod.service
@@ -239,7 +239,7 @@ After=probo-node-modules.service probod.service
Type=simple
User=${LIMA_USER}
WorkingDirectory=/workspace
ExecStart=/usr/bin/npm --workspace @probo/trust run dev -- --host 0.0.0.0
ExecStart=/usr/bin/npm --workspace @probo/compliance-portal run dev -- --host 0.0.0.0
Restart=on-failure
RestartSec=3s
@@ -249,4 +249,4 @@ EOF
systemctl daemon-reload
systemctl enable --now probo-stack.service
systemctl enable --now probod.service probo-console.service probo-trust.service
systemctl enable --now probod.service probo-console.service probo-compliance-portal.service

View File

@@ -129,7 +129,7 @@ cmd_status() {
echo ""
echo "Services (use VM IP to access from host):"
echo " Console: http://${ip}:5173"
echo " Trust: http://${ip}:5174"
echo " Compliance Portal: http://${ip}:5174"
echo " API: http://${ip}:8080"
echo " Grafana: http://${ip}:3001"
echo " Mailpit: http://${ip}:8025"

View File

@@ -28,7 +28,7 @@ import (
"io/fs"
"net/http"
truststatics "go.probo.inc/probo/apps/trust"
complianceportalstatics "go.probo.inc/probo/apps/compliance-portal"
"go.probo.inc/probo/pkg/server/statichandler"
)
@@ -59,7 +59,7 @@ func NewServer(headDataFunc HeadDataFunc) (*Server, error) {
}
spaServer, err := statichandler.NewServer(
truststatics.StaticFiles,
complianceportalstatics.StaticFiles,
"dist",
gzipOptions,
statichandler.WithFileRenderer("/index.html", renderer),
@@ -72,7 +72,7 @@ func NewServer(headDataFunc HeadDataFunc) (*Server, error) {
}
func buildIndexRenderer(headDataFunc HeadDataFunc) (statichandler.FileRenderer, error) {
subFS, err := fs.Sub(truststatics.StaticFiles, "dist")
subFS, err := fs.Sub(complianceportalstatics.StaticFiles, "dist")
if err != nil {
return nil, fmt.Errorf("cannot open dist: %w", err)
}