How a Project portal reaches a client
Each Project has its own source repository — neon-law/acme, say — holding a React application under portal/. That
bundle is never committed anywhere in Navigator, and it never touches git on the way to a client. It is built in the
Project repository's own CI, published to the deployment's private -applications bucket, and streamed from there by
web — same-origin, and only after the session and Project participation row are checked.
flowchart LR
subgraph repo["Project repo — neon-law/acme"]
src["portal/ — React + Vite"]
ci["CI on push to main:<br/>validate + application-publish"]
src --> ci
end
subgraph gcp["Deployment project — neon-law"]
bucket[("<deployment>-applications<br/>acme/portal/ — private, UBLA")]
end
subgraph nav["Navigator — neon-server"]
web["web streams the bundle at<br/>/app/projects/acme/portal/"]
end
client(["Client browser"])
ci -- "keyless WIF (navigator-app-publisher):<br/>upload dist/ — hashed assets first,<br/>index.html last, never delete" --> bucket
client -- "GET /app/projects/acme/portal/" --> web
web -- "check session + participation" --> web
web -- "stream objects, same-origin" --> bucket