Neon Law
  • Fractional CTO
  • Litigation
  • Fractional GC
  • Legal Services
  • Sign in
← Operating Neon Law Navigator

Provision the Infrastructure

Chapter 3 of 7 · Section 16 of 44

Sections

1. Intro

  • 1. Deploy your own
  • 2. Agenda

2. Prepare Google Cloud

  • 3. Bring your own project
  • 4. Dry-run first
  • 5. Private assets and domain restricted sharing
  • 6. The one project that is public on purpose
  • 7. The Navigator deployment matrix
  • 8. The `/app` mount and HTTP route ownership
  • 9. `neon` — the whole brand seam
  • 10. Live rollout checkpoint
  • 11. Set one site to one version

3. Provision the Infrastructure

  • 12. The APIs that light up
  • 13. Network and five buckets
  • 14. How a Project portal reaches a client
  • 15. One matter's document never backs another matter's
  • 16. A private image registry
  • 17. The cluster comes up

4. Environment Matrix

  • 18. Three operating modes, two deployment profiles
  • 19. Configuration precedence: the first source wins
  • 20. Local dev controls: inputs read by `navigator dev`
  • 21. Local runtime: what `.devx/env` generates
  • 22. The store: SurrealDB
  • 23. Where SurrealDB authorization lives
  • 24. Deployed runtime: core web and worker wiring
  • 25. Deployed runtime: identity and access
  • 26. Deployed runtime: email, signatures, and billing
  • 27. Deployed runtime: repositories, content, AI, and scheduled work
  • 28. Provision and ship: variables read by the operator CLI
  • 29. Ancillary operations and opt-in test controls
  • 30. When simulated data appears

5. Configure the Trust Boundaries

  • 31. Secrets: the invariants that gate the boot
  • 32. Sign-in: bring an OIDC provider; passwords live there, not here
  • 33. Role rings: who can do what
  • 34. Provider signup and parity across the deployments
  • 35. The external surface — every third party, in one place
  • 36. The two service deployments
  • 37. Security architecture

6. Ship the Instance

  • 38. Ship and verify
  • 39. Post the verified handoff in `#navigator`
  • 40. Point your domain at the instance (optional)
  • 41. Drive it from the CLI
  • 42. Make it yours — white-label under your own brand
  • 43. This is how we set up Neon Law Foundation

7. Wrap Up

  • 44. Canonical references

A private image registry

With storage in place, the provisioner creates the one private Artifact Registry repository that every navigator container image lives in, and the identities that push to and pull from it:

  • A Docker-format repository (default navigator) at your-region-docker.pkg.dev/your-project-id/navigator.
  • A keep-the-last-10-versions cleanup policy — a KEEP rule retaining the last 10 versions of each image plus a DELETE rule for everything else. Retention is a count rather than an age on purpose: an age-based rule is only safe while releases outrun it, and releases are tag-driven, so a quiet fortnight under the old 7-day rule would have let the registry delete the versions production was running. A count cannot expire. Keep policies take precedence over delete policies, which is what makes the pair mean "keep ten, delete the rest" — the delete half matches every version, so it is never applied alone.
  • A CI push identity (navigator-ci-pusher service account) with a repo-scoped roles/artifactregistry.writer binding, plus a GitHub Workload Identity federation pool and provider so CI authenticates keyless — no downloaded service-account key — pinned to this one repository and to the refs allowed to publish.
  • A repo-scoped roles/artifactregistry.reader binding for the GKE Autopilot node identity, so the cluster can pull.

Two values decide whether that federation works at all, and both are easy to get wrong in a way nothing reports:


issuerUri           https://token.actions.<your-tenant>.ghe.com   # NOT token.actions.githubusercontent.com
attributeCondition  assertion.repository == '<owner>/<repo>'
                        && (assertion.ref == 'refs/heads/main' || assertion.ref.startsWith('refs/tags/'))

Presenter notes

The registry is private: only principals inside this project may pull, which is why the cluster's node service account gets an explicit reader binding rather than relying on a public image. The repository create is a long-running operation that treats a 409 Conflict as already-exists, and the cleanup policy is a PATCH; both are safe to re-apply, keeping this step as idempotent as the rest.

Push access is keyless, and the two values above are where a day disappears. A GitHub Enterprise data-residency tenant issues its own OIDC tokens. If your repository lives on <tenant>.ghe.com, the pool must trust that tenant's issuer; every public federation tutorial assumes github.com, and a pool pinned to token.actions.githubusercontent.com is accepted at create time, reports ACTIVE, and then fails every single token exchange. Nothing warns you, because nothing is wrong until a workflow asks for a token. Read the issuer off the tenant instead of copying one:


curl https://token.actions.<your-tenant>.ghe.com/.well-known/openid-configuration

The condition pins the full owner/repo, not the owner alone. Owner-scoping sounds equivalent and is not: it admits every repository in the org, so any one of them can mint a token that pushes your production images. Pinning the whole slug also refuses a fork for free, because a fork carries its own repository claim. The ref clause is the second half — only main and release tags may publish, so an arbitrary branch is refused too.

Both refusals happen at the token exchange, which is the property worth internalising: a run that should not publish fails at the authenticate step and never reaches the push. When you verify this, check which step failed. A run that fails at docker push instead means the condition let the token through and the IAM binding caught it — the right outcome by luck rather than by design, and a condition still to fix.

One last trap, and the reason the provisioner is worth re-running rather than hand-fixing: an ensure that only ever creates cannot repair any of this. A provider built against the wrong issuer answers the create with 409, so a create-only provisioner reports "already exists" over a resource that can never authenticate. ops gcp hub setup converges instead — it PATCHes the existing provider onto the current issuer and condition, and it replaces the impersonation binding rather than appending to it, so a principal left behind by an org rename actually loses access. An additive binding can never revoke, and a rename is exactly when you need it to.

View all slidesOpen display
← PreviousNext →
Neon Law
BlogContactFoundationNavigatorPresentationsWorkshops
Contact us — contact@neonlaw.com+1 510 800 2080
  • Nevada
    5150 Mae Anne AveSte 405-9002Reno, NV 89523
  • New York
    12 E 49th St18th FloorNew York, NY 10017
  • Washington
    720 Seneca StSte 107-715Seattle, WA 98101

© 2026 Shook Law PLLC and Neon Law Foundation

This is attorney advertisement. Nothing on this site is legal advice. Neon Law is the trade name of Shook Law PLLC, and an attorney-client relationship begins only with a signed retainer between you and Shook Law PLLC. Published flat fees cover the scope each one names and do not include third-party filing fees. Every legal matter is different, and past results do not guarantee a similar result.

Shook Law PLLC is a proud supporter of the Neon Law Foundation , a 501(c)(3) nonprofit.

Neon Law Foundation is a Nevada nonprofit corporation and a 501(c)(3) tax-exempt organization. It does not practice law and cannot represent you.

Nothing on this site is legal advice, and nothing here creates an attorney-client relationship.

5150 Mae Anne Ave Ste 405-9999, Reno, NV 89523
support@neonlaw.orgTransparency & public disclosures

Powered by Neon Law Navigator #26.8.20-hotfix.4

Open source — neon-law-foundation/navigator GitHub stars 2