How a Project portal reaches a client

Each Project has its own source repository — neon-law/spotonix, 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/spotonix"]
    src["portal/ — React + Vite"]
    ci["CI on push to main:<br/>validate + application-publish"]
    src --> ci
  end
  subgraph gcp["Deployment project — neon-law"]
    bucket[("neon-law-prod-applications<br/>spotonix/portal/ — private, UBLA")]
  end
  subgraph nav["Navigator — neon-server"]
    web["web streams the bundle at<br/>/app/projects/spotonix/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/spotonix/portal/" --> web
  web -- "check session + participation" --> web
  web -- "stream objects, same-origin" --> bucket