Altien is shipping one image to every customer

The fork's backend has been re-plumbed so a single deployable build can serve different firms without a rebuild.

multi-tenantinfrastructure

Altien restructured the server so the same backend image can be dropped onto any customer's infrastructure and pick up its identity - which login system it uses, which tenant it answers to - from environment variables at startup. The frontend now rides inside the same process as the backend rather than running as a separate service, which collapses two containers into one for ops teams to babysit.

This is the kind of plumbing that sounds dull until you're managing deployments across ten firms. One artifact, ten environments, no rebuilds when a new client signs on. The cost is a clean break in how the backend is addressed, so anything pointing at the old URLs will need to be re-pointed before it works again - not a shipper's problem if you're starting fresh, very much a shipper's problem if you've already integrated.

So what If you're running Mike-derived software for multiple firms or business units, this is the difference between maintaining one artifact and maintaining a fleet.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

2 commits from Altien/mikeOssAzure, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
acbb6cc7 feat(server): runtime /config + /api prefix + bundled static frontend Allen Morgan 2026-05-08 ↗ GitHub
commit body
Wires every router added in earlier commits into the Express app and
adds the runtime-config endpoint that the browser bundle reads at
startup.

  * routes/config.ts mounted at /config - returns
    { authProvider, entra: { tenantId, clientId } } from server env.
    Unauthenticated; lets the same Docker image ship to any tenant.

  * /api prefix shift - every existing API router moves under /api/* so
    the backend can also serve a static frontend bundle from the same
    process (the SPA shell at / would otherwise collide).
    /install and /config keep their current paths because they have
    independent meaning at the root.

  * Static frontend bundle.  When PUBLIC_DIR (../public relative to
    dist/index.js) exists, the backend serves the Next.js static export
    out of the same Express process.  findShell() resolves dynamic-
    segment routes like /projects/<id> back to the right shell file
    that Next.js export emits with `_` placeholders.  RSC `.txt`
    requests for unmapped routes 404 cleanly so Next falls back to a
    hard navigation.  When PUBLIC_DIR is absent (local backend dev),
    the static handler is skipped and the frontend dev server at :3000
    talks to this backend over CORS as before.

  * trust-proxy + cookie-parser + urlencoded body parser added to
    support OAuth state cookies, the configurator's signed sessions,
    and the bootstrap-token paste form respectively.
6697186c chore(backend): env example, dockerignore, regenerate lockfile Allen Morgan 2026-05-08 ↗ GitHub
commit body
  * backend/.env.example                - full set of env vars including
                                          AUTH_PROVIDER block (local /
                                          supabase / entra), Azure
                                          storage block, OpenAI/AOAI,
                                          download-signing secret,
                                          observability connection
                                          string.  Sanitized - concrete
                                          identifiers replaced with
                                          placeholders.

  * backend/.dockerignore               - standard Node ignore set so
                                          docker build doesn't blow up
                                          the image with node_modules.

  * backend/package-lock.json           - regenerated to match the
                                          dependency set added across
                                          earlier commits (azure SDKs,
                                          pg / node-pg-migrate, openai,
                                          cookie-parser).

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-198.md from inside the repo you want the changes in.

⬇ Download capture-thread-198.md