Commit graph

14 commits

Author SHA1 Message Date
Doxa Maps
6df2da9c99 Cloud container: OIDC_AUTO_SIGNIN, so the Studio can sign in inside a dashboard frame
With it on, oauth2-proxy skips its button page. For a user already signed in to the provider the sign-in is
then redirects only, and the provider's no-framing headers never apply, so a framed Studio signs itself in.

UNVERIFIED: never run live in a framed dashboard (written 2026-09-28 04:32Z, not landed until the 14:38Z merge-all order).
Checked only statically: bash -n passes, and the argument switch yields --skip-provider-button for 1 and nothing for unset or 0 under set -u.
Replayed onto development: AUTO is now defined inside the OIDC gate block (ACCESS != public), next to the ALLOW list, and passed before --upstream="$ROOT".
Default off, so no running container changes.
2026-09-29 14:40:58 +00:00
Doxa Maps
e34fac45d4 Cloud container: DEV_SERVER=off runs a tenant without the Plugin Studio dev server
No Vite, no pull loop and no Rudder: /cdn, PocketBase, the admin router and the sign-in stay, and / redirects to
/cdn/. The default stays on, so running containers are unchanged. Off without OIDC_ISSUER refuses to start,
because /pb and /admin would then have nothing in front of them.

Replayed onto development after the public Studio mode landed. Off together with ACCESS=public is refused
too, because the public Studio is the dev server itself. PULL_INTERVAL=0 still means no pulls, whatever
DEV_SERVER says. The setting is in the cloud README's table.
2026-09-29 07:31:17 +00:00
Doxa Maps
f1500a37c2 Cloud container: ACCESS=public, a public Plugin Studio with the admin parts behind a password
The container needed an OIDC provider to run PocketBase at all. With ACCESS=public:
- The Studio, every map and the backend's public API are open, with no sign-in. Vite owns
  the public port and forwards /cdn/, /api-prod/, /pb/ and /admin/ to admin.mjs, whose gates
  decide.
- /admin/ (publishing), PocketBase's dashboard and _superusers ask for ADMIN_USER /
  ADMIN_PASSWORD over HTTP Basic, compared in constant time. The container refuses to start
  without ADMIN_PASSWORD. In this mode X-Forwarded-Groups is never read: with no oauth2-proxy
  in front, it is whatever a visitor sends.
- Rudder's voice engine stays off. Gated bundles (gatedProfiles) are refused even by URL:
  source, @fs, dev leaf. Vite's /__open-in-editor is refused.
OIDC stays the other mode, unchanged. In BOTH modes the Studio's own /api/pb (the dev backend
plugin) now goes through admin.mjs's /pb (DX_PB_URL). The dashboard and _superusers stay
behind the same gates, and plugins that use PocketBase work in the container's Studio; they
got a 503 before.

Checked: bash -n; the mode selection (public / gated / open); a missing password stops the
container. The admin gate and the public guard, taken from these files, pass 20/20:
- password right / wrong / wrong user;
- a spoofed groups header ignored;
- 401 + Basic prompt;
- gated mode unchanged;
- no password = no admin;
- every form of a gated path refused and the rest passed.
2026-09-29 05:31:37 +00:00
Doxa Maps
e9e16c7aaf Cloud container: PULL_INTERVAL=0 never pulls, so a mounted checkout is never reset
The pull loop follows BRANCH with `git reset --hard FETCH_HEAD` whenever the branch moves.
In the cloud that is the point. On a checkout mounted from someone's machine it would wipe
their commits and uncommitted work. PULL_INTERVAL=0 now skips the loop entirely: no fetch,
no reset, one line in /tmp/pull.log saying so. Every other value behaves as before.

Checked both ways on a throwaway repo whose remote had moved on and whose working copy held an
uncommitted edit: with 0 the commit and the edit stay; with 1 (the control) the loop resets
both, as it always has.
2026-09-29 03:46:37 +00:00
Doxa Maps
101928ebbf Production PocketBase takes its schema from the production branch, never from the dev server's checkout
pb-prod (the public API) ran the migrations in the pulled checkout, which follows the table (development), so a
restart moved production's schema to unpublished work. It now reads /data/pb-prod-migrations/current: a snapshot
of PRODUCTION_BRANCH's migrations taken at start (the ref build-cdn.sh uses) and refreshed from the very snapshot
a publish builds. Only a change restarts pb-prod, and the restart is local: pb-prod runs in a loop, so the
container stays up. It fails closed: an error keeps the last good snapshot, and with none it is an empty folder,
never the development checkout. --automigrate=false, so a change made in prod's dashboard writes no migration.
/admin/status shows prodSchema next to published.
2026-09-29 01:38:08 +00:00
Doxa Maps
71d4c1817c Cloud container: pb-dev as the team's shared PocketBase, signed in through the team OIDC provider
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
Laptops reach pb-dev's API without the site sign-in; PocketBase signs people in itself through the same
OIDC provider (its own client), members of OIDC_ALLOWED_GROUPS only, password sign-in off. The group check
is ONE hook baked into the image and pinned by SHA-256; hooks from the pulled repo still never run. The
dashboard, _superusers and system collections stay behind the site sign-in for admins. It fails closed:
without the baked gate or a working OIDC setup, /pb/ stays behind the site sign-in as before.
2026-09-27 23:41:53 +00:00
Doxa Maps
b03c8d4bd4 Cloud container: Rudder accepts every host the container serves, not only the sign-in host
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
With two domains on one container, the engine answered the second one 403 "forbidden host", so Rudder
showed offline there. The allowed list now defaults to the hosts Coolify gives the container
(COOLIFY_FQDN), then the OIDC redirect host; always an explicit list, never a wildcard.
2026-09-27 23:08:21 +00:00
Doxa Maps
8ef7d337d2 Cloud container: a rebuilt Rudder engine replaces the running one once nobody is dictating
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
The pull loop rebuilt the engine when its source changed, but the old process kept running until the
next container start. Now, when the engine reports it is not in use, the old process is stopped by its
own PID and the dev server starts the new binary.
2026-09-27 22:45:22 +00:00
Doxa Maps
18152f0387 Cloud container: the site serves at once while Rudder sets up, and its model is in the image
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
Rudder's setup ran before Vite and the sign-in proxy, so the whole site answered 502 for minutes on every
start while the engine built and ~742 MB downloaded; on the first start the download was reset mid-file and
Rudder stayed offline. Now the runtime and pinned model are baked into an early image layer (SHA-256
checked, resumed and retried on a stall), setup runs in the background, /api/rudder answers "starting"
meanwhile, and the dev server restarts once when setup ends so the engine starts.
2026-09-27 22:32:22 +00:00
Doxa Maps
a5759491d0 Cloud container: RUDDER_ALLOW_HOST (the public host Rudder's engine accepts), defaulting to OIDC_REDIRECT_URL's host; 2 vCPUs advised
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
The engine now refuses non-loopback Host headers and Vite's proxy passes the public host through, so
without this every /api/rudder call is 403 (studio, RUDSRV-STU2). entry.sh derives it from
OIDC_REDIRECT_URL when unset; the README documents it and the CPU need (it ran ~1.5x behind real time
on a loaded box).
2026-09-27 21:53:03 +00:00
Doxa Maps
c0487bb39d Cloud container: Rudder's engine inside (RUDDER_ENGINE=1), fed by the browser's microphone
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
Go 1.22 in the image; on start, backend/rudder-engine/setup-runtime.sh fetches its pinned runtime and
model (SHA-256 checked, skipped when present) into RUDDER_HOME (default /data/rudder, meant for the
persistent volume) and builds the engine; RUDDER_AUDIO=browser. The pull loop rebuilds the untracked
engine binary when backend/rudder-engine changes. /api/rudder stays behind the sign-in: it is served
by Vite on the gated / route, and the only public routes remain /cdn/ and /api-prod/api/. README:
the flag, and 3.5 GB with it on.
2026-09-27 21:43:30 +00:00
Doxa Maps
14a25b6b59 README: Security controls (bundle integrity with the real manifest fields; the v1 backend posture), and PocketBase hooks switched off
Bundle integrity: all 25 bundles carry bundles[].integrity (sha384) and every profiles[].embed.script
already includes integrity + crossorigin=anonymous (checked on main); the section shows the snippet,
what the browser does with it, the CORS header it needs, and check:sri. The container's PocketBase:
locked-by-default collections, the prod dashboard blocked and the dev one admin-only, and hooks OFF,
now true in code: both instances get --hooksDir pointing at a path that never exists, so a pb_hooks/
folder added to the repo can't run. Per-plugin locks and isolated edge functions are stated as not
built.
2026-09-27 21:43:05 +00:00
Doxa Maps
3f8790ffce Cloud container v1: PocketBase dev + prod, a public CDN of the last good build, and an admin-only build trigger
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
deployment/cloud: PocketBase (pinned, sha256-checked) as dev (/pb/, signed in; its /_/ dashboard for
OIDC_ADMIN_GROUPS only) and prod (/api-prod/api/ public, dashboard never exposed), with the schema
as migrations in backend/pocketbase/pb_migrations and data on the /data volume; superuser from env.
admin.mjs routes /cdn/, /api-prod/, /pb/ and /admin/ behind oauth2-proxy (public: /cdn/ and
/api-prod/api/ only). build-cdn.sh: flock (409 on a second build), a snapshot of the pulled commit,
the public exclusions applied BEFORE the build, a heap-capped build, a check of the output that
REFUSES the swap if anything excluded remains (proved with planted fixtures: a field-access file,
'Visa Requirements' content, and key-cities one level down each fail; clean passes), then an atomic
swap; runtime-config.js carries the public API URL. public-exclusions.txt is the ONE list the
giveaway export and the CDN build share. Any git host via REPO_URL/BRANCH/GIT_TOKEN.
2026-09-27 21:32:46 +00:00
Doxa Maps
f57435253c Cloud dev server recipe in the repo, with an optional OIDC sign-in
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
deployment/cloud/: a bootstrap Dockerfile (Bun, git, oauth2-proxy v7.15.3) that clones the repo
and runs deployment/cloud/entry.sh from it, so the recipe updates with git; the Vite overlay
(host, allowed hosts, HMR over wss); and the pull loop that follows the branch. With no OIDC env it
serves Vite directly (laptop default unchanged). With OIDC_ISSUER set, oauth2-proxy owns the port
and Vite listens on localhost behind it: Studio, maps and the HMR websocket all sit behind one
sign-in, with PKCE S256, a confidential client and a REQUIRED group allow-list (it refuses to
start without one). Secrets reach oauth2-proxy through its environment only. README gets a short
'Run it in the cloud' section linking the recipe.
2026-09-27 07:50:45 +00:00