mirror of
https://github.com/luxfi/aml.git
synced 2026-09-24 00:25:20 +00:00
Two changes that are really one: stop owning things that are already owned. AUTH. Deleted ui/src/auth.ts — a local PKCE implementation with its own token storage, its own refresh, its own state handling and its own idea of what signing out means. @hanzo/iam/browser is that, for every Hanzo app: configureIam + startLogin + handleCallback + getSession + getUser + logout. There is now no auth code in this repo to review, drift, or get wrong, and when IAM's end-session behaviour improves every app gets it without a line changing here. Verified against production IAM: hanzo.id reflects https://aml.hanzo.ai on discovery, token and userinfo, so the flow works from the console's origin. CONFIGURATION. Dropped config.json and the SPA_* env with it. The console derives its API from the host it is served on — aml.hanzo.ai can only ever talk to api.hanzo.ai — and reads its brand, issuer and IAM clientId from that API's /v1/aml/config, which now carries client_id because that route already answers 'which identity does this surface have'. So there is no setting that points authenticated requests somewhere, which is the setting worth attacking; the same image is every brand's; and nothing writes the served root, which is what lets the container run read-only and unprivileged. The derivation is deliberate about what it refuses: an address literal has three labels and no parent domain, so 127.0.0.1 would have become api.0.0.1. Every host shape is asserted — brand hosts, a bare domain, localhost, IPv4, IPv6. Also here, from the same review: one replay per tenant on /v1/aml/rules/test, because an empty sample opens every retained record and a handful at once occupies the engine that still has to answer ingest; and the CI smoke now asserts the invariants that replaced the old ones — no config.json is served, and the bundle names no clientId. CSP unchanged and re-proven: 7 routes, zero violations, zero console errors, still no 'unsafe-inline'. Go build/vet/gofmt clean, 18 packages green, api race-clean. Co-authored-by: Hanzo Dev <[email protected]>
29 lines
1.3 KiB
Docker
29 lines
1.3 KiB
Docker
# The AML console: a compiled bundle, served by the house static server.
|
|
#
|
|
# It is its own image because it is its own deploy unit. The API is reached at
|
|
# api.<brand>/v1/aml and this bundle is served on its own host — one door for
|
|
# data, one for the console, and neither inside the other. Building it into the
|
|
# daemon would put them back in one pod and one blast radius.
|
|
#
|
|
# npm with the committed lockfile: `npm ci` fails on lockfile drift rather than
|
|
# resolving fresh, and needs nothing in the image but the node base.
|
|
FROM node:22-alpine AS build
|
|
WORKDIR /ui
|
|
COPY package.json package-lock.json ./
|
|
RUN npm ci
|
|
COPY . .
|
|
RUN npm run build
|
|
|
|
# ghcr.io/hanzoai/static serves it. -spa sends unknown paths to index.html, which
|
|
# is what makes /cases/… and /callback resolve on a hard refresh; the security
|
|
# headers and the CSP come from the server.
|
|
#
|
|
# Nothing is templated into the bundle at startup and no SPA_* env is set, so the
|
|
# served root is never written and the container runs read-only and unprivileged.
|
|
# The console derives its API from the host it is served on and reads its brand,
|
|
# issuer and clientId from that API — so this image is every brand's, unchanged.
|
|
FROM ghcr.io/hanzoai/static:v0.5.1
|
|
COPY --from=build /ui/dist /public
|
|
EXPOSE 3000
|
|
ENTRYPOINT ["/static", "-port", "3000", "-root", "/public", "-spa"]
|