Investigate: Deployment pipeline
IMPLEMENTATION RULES: Before implementing this plan, read and follow:
- WORKFLOW.md - The implementation process
- PLANS.md - Plan structure and best practices
Status: Backlog
Goal: Decide how every Atlas-side deployable artefact — the Docusaurus site (which also hosts the Scalar API playground and dbt-docs) and the atlas-data polyglot image that registers as a Dagster code location — goes from a developer's commit to running on UIS. Covers CI test gates, image build + registry, hostnames, secrets, database migrations, rollback, the cross-repo handshake with the UIS Dagster install, and which environments exist (prod-only or also staging / PR previews).
Last Updated: 2026-05-11 (third full rewrite — see "What's changed since the previous draft").
Origin: Atlas was pre-production when the original draft was written (2026-04-23). Since then PostgREST has shipped and become UIS-owned (PLAN-004), the frontend has split into two apps (PLAN-005), the source catalogue has grown to ~38 sources (PLAN-007), the docs tree has moved under website/docs/ (PLAN-003), and UIS has begun documenting how Dagster will run in their stack (urbalurba-infrastructure/.../INVESTIGATE-dagster.md). The high-level deploy architecture is settled in docs/stack/suggested-stack.md; what's still missing is the CI side, the release flow for Atlas-owned artefacts, and the cross-repo handshake with UIS Dagster. This investigation enumerates what to build and what to decide so we can split it into ordered PLANs.
What's changed since the previous draft
The earlier version (2026-04-23, status-updated 2026-04-27) framed Atlas as having two deployable artefacts (one Next.js frontend + the atlas-data image) running on a Dagster-deferred v1 stack. Nine things have shifted:
- PostgREST shipped and is UIS-owned (PLAN-004, #29, #30) — the API service is no longer hypothetical and is not in Atlas CI scope. UIS deploys and operates it. Atlas's responsibility ends at writing
marts.*and theapi_v1.*wrapper views. - Frontend split (PLAN-005, #33) —
atlas-frontendbecame two apps:atlas-frontend/(customer, PostgREST consumer) andatlas-contributor-frontend/(contributor diagnostics, direct Postgres). - Docs are under
website/docs/(PLAN-003 phase 1, #27) — every relative path in the previous draft's cross-references was stale. Docusaurus is now in the repo aswebsite/and will be a deployable artefact when its build is wired up. - Source catalogue grew — bufdir, ssb-crime, ssb-10826, ssb-13995, Red Cross supply (#36, #38, #57, #58, #71, etc.). The
atlas-dataimage is now real workload; CI needs to handle ≥38 ingest scripts and a non-trivial dbt project. - v1 deploy surface narrowed (2026-05-11) — both Next.js frontends are kept in the repo but not deployed in v1. The customer surface for humans is the Docusaurus site (hostname pivoted to
atlas.sovereignsky.noin item 9 below). - Dagster is back in v1 (2026-05-11) —
suggested-stack.mdpreviously deferred Dagster to v2 with v1 ingest running as "CLI scripts under cron." UIS has since draftedINVESTIGATE-dagster.md. Atlas's v1 ingest plan is now Dagster-driven, not cron-driven. No K8s CronJobs in this design. Theatlas-dataimage becomes a Dagster code-location image (polyglot Python + Node + dbt + dagster). - Scalar + dbt-docs collapse into Docusaurus (2026-05-11) — rather than separate
developer-atlas.helpers.no(Scalar) anddbt-atlas.helpers.no(dbt-docs) hostnames, both ship as pages/subpaths inside the Docusaurus site: Scalar at/api, dbt-docs at/lineage/. One container, one hostname, one deploy. Thedeveloper-atlashostname is dropped from the plan; the<role>-atlasconvention only applies to UIS-owned platform components (api-atlas, etc.). - No Cloudflare Tunnel in v1 (2026-05-11) — earlier framing assumed Atlas's public surface would be exposed via Cloudflare Tunnel. v1 drops the Tunnel; everything goes through UIS's standard Traefik ingress, with the
atlas.*host rule coveringatlas.helpers.no(prod) andatlas.localhost(UIS local dev). Cloudflare Tunnel remains an option for later but is not assumed. - Docusaurus deploy moves to GitHub Pages at
atlas.sovereignsky.no(2026-05-12) — UIS itself ships its docs atuis.sovereignsky.novia GitHub Pages; Atlas follows the same sister-project pattern. The Docusaurus row in the artefacts table is no longer UIS-Traefik-served; it'sactions/deploy-pages@v4with a custom-domain CNAME. The dynamic services (PostgREST, Dagster, atlas-data) remain on UIS — only the static docs pivot. The earlieratlas.helpers.no-via-UIS-Traefik plan is deferred; could revisit if there's ever a reason to migrate docs to helpers.no infrastructure.
What's already settled (don't re-litigate)
From docs/stack/suggested-stack.md and urbalurba-infrastructure/.../INVESTIGATE-dagster.md:
- Hosting platform: UIS (Kubernetes, Traefik ingress, observability stack). No Cloudflare Tunnel in v1.
- Postgres: shared UIS instance; Atlas owns
raw.*,marts.*, andapi_v1.*schemas. Dagster gets its own database (dagster) on the same instance for run metadata. - PostgREST: deployed by UIS (Helm chart). Reads
api_v1.*by default; other schemas reachable viaAccept-Profileheader. Not an Atlas CI concern. Exposed atapi-atlas.helpers.no/api-atlas.localhostvia UIS ingress. - Dagster: deployed by UIS via the official
dagster/dagsterHelm chart (OSS distribution). Webserver + daemon + run pods all live in adagsternamespace owned by UIS. Atlas contributes a code location (a polyglot Docker image) that Dagster registers viadagster-user-deployments.deployments[]in the Helm values. Atlas does not deploy or operate the Dagster platform — that's UIS's responsibility. - No CronJobs. Scheduling is owned by Dagster (
@scheduledeclarations inside Atlas's Python module). - No ArgoCD for the data side in v1 — per UIS Dagster doc, Atlas image updates happen via manual
helm upgradeof the UIS Helm release after the Atlas image tag is bumped in values. ArgoCD remains an option for the Docusaurus deploy but is not assumed. - Observability: Loki / Prometheus / Grafana, already in UIS. Dagster exposes Prometheus metrics on the webserver and daemon.
- Internal admin access: Dagster UI is internal-only day 1 (network-gated via the UIS cluster); Authentik OIDC via Traefik middleware later.
From the implementation work since:
dbt buildis the test gate for any pipeline change — seeproject-atlas.md.- dbt invocation pattern:
uv run --env-file ../ingest/.env dbt <cmd>— locally and in CI. Inside the polyglot image,dagster-dbtinvokes dbt natively (no shell wrapper). - PostgREST schema routing:
api_v1is the default;marts.*andraw.*needAccept-Profileper request. - Neither Next.js frontend is deployed in v1 —
atlas-frontend/andatlas-contributor-frontend/stay in the repo as runnable local-dev surfaces, with the deploy story deferred.
v1 deployable artefacts
The complete set of things that go from commit to running. Two deployed, two kept-in-repo-but-not-deployed, two UIS-owned for context.
| Artefact | Type | Owner | Production hostname | Local dev hostname | Notes |
|---|---|---|---|---|---|
| Docusaurus (with Scalar + dbt-docs as pages) | Static site, GitHub Pages with custom domain | Atlas | atlas.sovereignsky.no | localhost:3000 (Docusaurus dev server) | Single Docusaurus site exposes everything human-facing for Atlas: / landing + narrative docs, /api Scalar interactive playground (loads PostgREST OpenAPI spec from api-atlas.helpers.no/), /lineage/ dbt-docs static site. Not UIS-served: ships via GitHub Pages, matching the sister-project pattern (UIS itself ships uis.sovereignsky.no this way). Static docs don't need K8s/observability; the dynamic services that do (PostgREST, Dagster, atlas-data) stay on UIS. |
atlas-data polyglot image | Docker image registered as Dagster code location (no HTTP exposed) | Atlas (image); UIS (registration) | n/a — addressed inside Dagster as code location atlas-data | n/a | Python 3.11 + Node 20 + uv + dbt + dagster + dagster-dbt + dagster-k8s + dagster-pipes + the ingest TS + the dbt project. Same image runs as two pod types: the always-on code-location pod (dagster api grpc) and the ephemeral run pods that Dagster's K8sRunLauncher spawns on materialisation. Built and tagged in Atlas CI, pushed to GHCR; deployed by bumping the tag in UIS Helm values + helm upgrade. |
| PostgREST | K8s deployment, public | UIS | api-atlas.helpers.no | api-atlas.localhost | Listed for context; not in Atlas CI/CD. UIS Traefik ingress. |
| Dagster (platform) | Webserver + daemon + metadata DB, K8s deployment, internal | UIS | dagster.<uis-domain> (TBD) | dagster.localhost | Listed for context; not in Atlas CI/CD. UIS PLAN-001 stands the platform up empty; Atlas PLAN-002 registers the first code location. |
atlas-frontend (customer) | Next.js — not deployed in v1 | Atlas | (not deployed) | localhost:3001 (direct, no UIS routing) | Customer Next.js consumer of PostgREST. Kept in repo as a runnable local surface and code reference; deploy story revisited later. |
atlas-contributor-frontend | Next.js — not deployed in v1 | Atlas | (not deployed) | localhost:4000 (direct, no UIS routing) | Contributor diagnostics with direct Postgres role. Local-dev only by design. |
Hostname convention: Atlas has one human-facing hostname at atlas.sovereignsky.no (mirrors uis.sovereignsky.no). UIS-owned platform components addressed in the Atlas context use the <role>-atlas.helpers.no prefix pattern — currently just api-atlas.helpers.no (PostgREST). UIS's own components (Dagster UI, Grafana, etc.) keep their UIS-scoped hostnames. Atlas itself is one site at one hostname; Scalar and dbt-docs live as subpaths under that site, not as separate hostnames. The earlier plan to serve Atlas docs at atlas.helpers.no via UIS Traefik is deferred — possibly a future migration once helpers.no DNS is in our control; for now sovereignsky.no is the docs home, matching what the sister projects already do.
Ingress: standard UIS Traefik for UIS-owned components (PostgREST, Dagster UI). The Docusaurus site is on GitHub Pages and does not go through UIS ingress at all.
API URL versioning (decision 2026-05-12): Atlas's public API uses URL-prefix versioning — every endpoint lives under /v1/<endpoint> (matches Stripe, OpenAI, the modern-API convention). The v1 prefix decouples URL versioning from PostgREST's schema-based routing: the api_v1 Postgres schema is mapped from the URL prefix by a UIS-side Traefik path-rewrite (strip /v1/, forward to PostgREST, api_v1 is already PostgREST's default schema). When v2 ships later (breaking changes), a parallel /v2/ Traefik rule routes to Accept-Profile: api_v2 and both versions run in parallel. Atlas is pre-release — every consumer (Scalar curls, atlas-frontend URLs, future external developers) sees only the versioned URLs. Coordinated with UIS in talk.md Message 5.
What's missing — the CI + release questions
Components and what each needs
| Artefact | Build | Test gate | Package | Deploy |
|---|---|---|---|---|
| Docusaurus (with Scalar + dbt-docs as pages) | npm run build (in website/); pull latest dbt-docs artefact and unpack into static/lineage/ before the Docusaurus build; the /api route uses @scalar/api-reference-react (or a <script>-tag page) pointed at api-atlas.helpers.no/ | Link-check, build-must-pass (enforced by onBrokenLinks: 'throw'); verify the Scalar spec URL is reachable at build/deploy time | Static site uploaded as GitHub Pages artefact (actions/upload-pages-artifact@v3) | actions/deploy-pages@v4 on every push to main. Custom domain atlas.sovereignsky.no via website/static/CNAME + DNS CNAME + repo Pages settings. |
atlas-data polyglot image | Multi-stage Dockerfile: Node 20 deps (pnpm install in ingest/, includes @dagster-io/dagster-pipes) → Python 3.11 deps (pip install dagster dagster-dbt dagster-k8s dbt-postgres) → runtime layer with both + atlas-data/dbt/ + Dagster definitions.py | (a) tsc --noEmit (ingest); (b) dbt parse; (c) full dbt build against ephemeral Postgres in CI; (d) dagster definitions validate (or equivalent — verifies the Python module imports cheaply); (e) dagster api grpc smoke test in CI (boot the gRPC server, confirm it responds) | Single image tagged ghcr.io/helpers-no/atlas-data:vX.Y.Z. ~1.5–2 GiB. Multi-stage + BuildKit cache critical. | Atlas CI pushes the image to GHCR with a unique tag. UIS-side: bump dagster-user-deployments.deployments[].image.tag in the Dagster Helm values; helm upgrade. Dagster's webserver/daemon reconnect to the new gRPC server automatically. |
raw.* migrations | n/a (SQL files in atlas-data/migrations/) | Apply to ephemeral Postgres in CI | Bundled inside the polyglot image | Runs as a Dagster asset (with downstream-dependency edges so it executes before any ingest asset), or as a one-shot kubectl run against the polyglot image. See Q7. |
Both Next.js apps still get CI typecheck/build gates (cheap, prevents regression for the local-dev surfaces) but no Dockerfile, no image push, no UIS deploy in v1.
Decisions to make
-
CI host — GitHub Actions, GitLab CI, or self-hosted runner inside UIS? Atlas's repo is on GitHub. GHA is the obvious default; self-hosted-on-UIS is more sovereign-stack-aligned but adds operational surface. UIS may already have a preference — check before deciding.
-
Image registry — UIS's Dagster doc names GHCR (
ghcr.io/helpers-no/atlas-data) as the expected registry for the polyglot image. Confirm GHCR is the chosen registry for the Docusaurus image too (consistency), or whether UIS prefers a UIS-hosted registry (Harbor) for some/all. -
Deploy mechanism for the Docusaurus image — UIS's Dagster doc commits to manual
helm upgradefor theatlas-datacode location in v1 (no ArgoCD-driven tag-following). Docusaurus is a simpler workload; it could follow the same manual pattern, use ArgoCD if UIS has it wired up for other apps, or use UIS's existing service-deployment playbook. Decide before the Docusaurus deploy PLAN. -
Branch / release strategy — trunk-based (every
maincommit publishes a new image + auto-deploys) or release branches / tags? Atlas is small + single-developer; trunk-based is simplest. Caveat for the polyglot image: per UIS Dagster doc, every image must have a unique tag (Helm only rolls a Deployment if the image field changes), solatestis not a safe default —vX.Y.Zorsha-<commit>per build. -
Environments — prod-only, dev + prod, dev + staging + prod, or PR-preview environments? Pre-production status argues for prod only now; preview environments add real value when external reviewers join. Note:
atlas.localhostis the natural UIS local-dev environment for the Docusaurus image;dagster.localhostfor the code-location image. -
Secrets management — sealed-secrets, external-secrets-operator, ArgoCD's vault plugin, or 1Password Connect? UIS likely already has a pattern — check before inventing.
-
Database migrations — when and how does
npm run migraterun? Three options:- (a) Dagster asset with dependency edges — declare a
raw_schema_migrationsasset that every ingest asset depends on. Dagster guarantees it runs first. Idempotent migration runner makes this safe to fire on every materialisation. - (b) One-shot
kubectl runagainst the polyglot image — operator runskubectl run --image=ghcr.io/helpers-no/atlas-data:vX.Y.Z -- npm run migratebefore doing the Helm upgrade. Explicit, manual, clear. - (c) Image entrypoint side-effect — migrations run when the code-location pod starts. Rejected (violates the "keep
definitions.pycheap to import" discipline from the UIS Dagster doc). Recommend (b) for the very first deploy and (a) oncedagster-dbtis wired and asset dependencies are reliable. Migration runner already implemented inatlas-data/ingest/scripts/migrate.ts.
- (a) Dagster asset with dependency edges — declare a
-
CI test gates per artefact — minimum bar:
- Both Next.js apps:
tsc --noEmit+npm run buildon PR + main (cheap regression gate; no deploy). atlas-datapolyglot image:tsc --noEmit+dbt parse+ Python module import-smoke on PR; fulldbt buildagainst ephemeral Postgres +dagster api grpcsmoke + image build on main.- Docusaurus:
npm run build+ link-check + verify Scalar spec URL responds.
- Both Next.js apps:
-
Ephemeral Postgres in CI — service container in GHA running the same Postgres major version as UIS. dbt seed + build against it; tear down after. Also serves the
dagster api grpcsmoke test if any boot-time queries are needed. -
Image build cache for the polyglot image — uv venv + dbt + Node deps + dagster pip layers all slow cold. BuildKit cache to GHCR is the obvious answer; verify the GHA runner has enough disk for layer caching.
-
Image tagging for
atlas-data— per UIS Dagster doc, unique tags are mandatory (Helm rollout depends on the image field changing). Use semver (v1.2.3) for human-readable rollbacks + commit SHA (sha-abc1234) for traceability. Never uselatestfor this image. Docusaurus tagging is less critical and can follow the same pattern for consistency. -
Rollback for
atlas-data— UIS-sidehelm rollbackon the Dagster release reverts the image tag and re-rolls the code-location pod. dbt-model rollback is harder (data already transformed); convention: never destructivedbt run --full-refreshfrom CI; only manual + reviewed. -
PR validation vs main jobs — PR: typecheck + dbt parse +
dagster definitions validate+ Docusaurus build (fast, advisory). Main: fulldbt build+ image build + push + (manual) Helm-values bump (slow, blocking on the push). -
Next.js test runners — neither frontend has Vitest/Playwright. Worth adding now? Probably wait until either app actually starts shipping again; typecheck + build is the minimum bar.
-
Secrets needed at runtime:
- Docusaurus: none (Scalar spec URL is public; dbt-docs is static).
atlas-datapolyglot image:ATLAS_DATABASE_URL(owner role forraw.*+marts.*); no API keys for current sources (Brreg / FHI / SSB are all open). Secret name and shape coordinated with UIS Helm values (per the Dagster doc'scode-location-values.yamlfragment).- Both Next.js apps: not deployed in v1; secrets are local-dev only.
-
The atlas-data repo split —
atlas-data/README.mdlists trigger conditions for moving it out of the monorepo. The polyglot-image deploy story is the strongest signal yet for splitting — but for v1 it's still cheaper to keep everything in the monorepo and let the Atlas CI build the image from there. Revisit if/when CI complexity makes the split worth it. -
Schema-change coordination — when a
marts.*orapi_v1.*change ships, the Scalar page at/apiauto-reflects it (loads the spec live fromapi-atlas.helpers.no) and dbt-docs at/lineage/rebuilds on the next Docusaurus deploy. No human coordination needed for v1 because neither Next.js frontend is deployed. -
Drift detection — depends on Q3. ArgoCD-managed Docusaurus deploys get drift detection free; manual
kubectl applydeploys do not. -
dbt-docs artefact source — two ways to produce the bundle that ships into Docusaurus at
/lineage/:- (a) From CI — Atlas CI runs
dbt docs generate --staticagainst the ephemeral Postgres afterdbt build; emits a static bundle; Docusaurus build pulls it intowebsite/static/lineage/. - (b) From
dagster-dbt— the manifest produced bydagster-dbtat code-location load time is the canonical source; a small CI job (or a Dagster asset) runsdbt docs generate --staticagainst the live manifest and publishes the bundle. Recommend (a) for v1 — decouples docs publishing from Dagster runtime. Revisit whendagster-dbtis wired if (b) becomes more attractive.
- (a) From CI — Atlas CI runs
-
dbt-docs freshness — should the bundle update on every
atlas-datamain commit (tight coupling, every schema change rebuilds docs) or on a daily/weekly schedule (looser, possibly stale)? Probably every main commit; the build is fast. -
PostgREST CORS / spec exposure — for the Scalar page at
atlas.sovereignsky.no/apito call PostgREST onapi-atlas.helpers.nofrom the browser, PostgREST needs CORS configured to allow theatlas.sovereignsky.noorigin (andhttp://localhost:3000for local Docusaurus dev). Coordinate with UIS — likely a one-line config change in their Helm values.Concrete finding from 2026-05-12 (during Scalar PLAN implementation): the current UIS PostgREST instance (PostgREST 14.10 reached at
http://api-atlas.localhost/) sendsAccess-Control-Allow-Origin: *only on the OPTIONS preflight response, not on the actual GET response. Reproducible with:curl -i -H "Origin: http://localhost:3000" http://api-atlas.localhost/ # no ACAO header
curl -i -X OPTIONS -H "Origin: http://localhost:3000" \
-H "Access-Control-Request-Method: GET" http://api-atlas.localhost/ # ACAO: *Browsers require
Access-Control-Allow-Originon the actual response, not just the preflight, so client-side fetches from Scalar (and any future Atlas client-side consumer) fail. atlas-frontend doesn't hit this because its fetches happen in Next.js RSCs — server-side, no CORS involved.What UIS needs to change: configure PostgREST to send
Access-Control-Allow-Origin(and the relatedAccess-Control-Allow-Methods,Access-Control-Allow-Headers,Access-Control-Expose-Headers) on all responses, not just OPTIONS. In PostgREST 14, this is thecors-allow-originconfig knob (or the equivalent UIS Helm values entry). Until this lands, Atlas's Scalar page at/apiloads the OpenAPI spec from a same-origin snapshot inwebsite/static/openapi.json— "Try it out" requests still fail.Atlas-side workaround:
npm run api:snapshot(inwebsite/) refreshes the committed snapshot from the local PostgREST. Removable once UIS ships the CORS fix. -
Scalar pinning strategy — pin a specific
@scalar/api-referenceversion (reproducible, requires manual bumps) or@latest(always fresh, can break silently)? Default to pinned with a quarterly bump. Pinning lives in Docusaurus'spackage.json(if using the React component) or in the<script>src=attribute (if using the CDN bundle). -
@dagster-io/dagster-pipespinning — UIS Dagster doc notes the npm package is at0.1.0with slower cadence than the Python SDK. Pin the version explicitly iningest/package.json; bump deliberately when needed. -
definitions.pyimport discipline — per UIS Dagster doc, the module must stay cheap to import (no DB connections, no eager I/O at module scope) because every run pod cold-starts by importing it. Worth codifying as a CI lint or code-review rule in Atlas's Dagster PLANs.
Cross-repo coordination (Atlas ↔ UIS)
The polyglot image's deploy involves both repos. The UIS Dagster doc lays out the phasing; here's how it lands on the Atlas side:
| Phase | UIS repo | Atlas repo |
|---|---|---|
| Today | nothing about Dagster | nothing about Dagster |
| UIS PLAN-001 done | Dagster deployed with empty deployments[]; dagster.<uis-domain> reachable | unchanged |
| Atlas PLAN-002 done | deployments[] references new Atlas image tag; helm upgrade applied | @dagster-io/dagster-pipes added; one source Pipes-enabled; polyglot image built and published; definitions.py cheap-to-import |
| Atlas PLAN-003 done | image tag bumped in deployments[]; helm upgrade applied | remaining 40+ sources Pipes-enabled; schedules defined in @schedule declarations; dbt assets wired via dagster-dbt |
The phasing assumes UIS PLAN-001 ships first (Dagster platform up, empty workspace). The order is still being discussed — see Open Question 1. Atlas can do prep work (building the polyglot image, wiring @dagster-io/dagster-pipes into one source, drafting definitions.py) before UIS PLAN-001 ships; the dependency only fires when there's an actual Dagster instance to register the code location with.
Recommended v1 priority order
Independent of the cross-repo Dagster track (which runs on its own timeline), the Atlas-side work order is:
- Docusaurus skeleton + deploy — landing page + nav stub, live at
atlas.sovereignsky.novia GitHub Pages. Gets the deploy plumbing proven (GHA build →actions/deploy-pages@v4→ custom-domain CNAME) on the lowest-stakes content. ~1–2 days. - Scalar page at
/api— first real Docusaurus page. Half a day. Suddenly the playground is live. - dbt-docs at
/lineage/— CI step:dbt docs generate --static→ unpack intowebsite/static/lineage/. Half a day. - Fill in Docusaurus content over time — getting-started, concepts, forking guide. Content-writing pace, not infra.
- Dagster (cross-repo) — independent track from #1–4. Can start prep in parallel.
Open Questions
- Sequencing — Atlas-side Dagster prep first, or UIS Dagster install first? UIS Dagster doc assumes UIS PLAN-001 ships before Atlas PLAN-002 (so there's an empty Dagster to register against). Discussion in progress with UIS contributor: can Atlas usefully build the polyglot image, wire Pipes into one source, draft
definitions.py, and validate it locally (viadagster dev) before the UIS install lands? If yes, the order can flip — Atlas ships first; UIS PLAN-001 + Atlas's code-location registration ship together. Resolve before drafting PLAN-002. - GitHub Actions vs self-hosted CI? UIS philosophy is sovereign Kubernetes. A self-hosted GHA runner inside UIS is a reasonable middle ground. Worth asking before defaulting to GHA cloud.
- Does UIS already have a sealed-secrets / external-secrets pattern Atlas should follow? Check the UIS repo before proposing one.
- Where do deploy manifests for Docusaurus live? In the Atlas repo (Atlas-side), in the UIS repo (centralised), or both (Atlas-side templates referenced by UIS-side apps)? Convention varies by UIS install. For the polyglot image this is settled (UIS Helm values own the registration); for the Docusaurus deploy it's open.
- Should
dbt seedre-run on every deploy or only when seed CSVs change? Re-running is safe (idempotent) and keepsdim_kommunein sync if a seed gets bumped. The cost is a few seconds per deploy. Default to always-run. - When does either Next.js frontend get a deploy story? Currently both are local-dev only. Triggers worth watching: a real need to demo
/dataover the internet, a contributor who needs the diagnostics UI off their own machine, or a fork-ready audience who wants a live reference site. Revisit then. - Should Atlas have its own pre-deploy migration runner pod, or rely on the operator to invoke it manually before
helm upgrade? The UIS Dagster doc is silent on this; tied to decision Q7 above.
Cross-references
Atlas-internal
docs/stack/suggested-stack.md— high-level deployment architecture (PostgREST, Dagster).website/docs/ai-developer/project-atlas.md— command reference, marts contract, devcontainer-or-not.atlas-data/README.md—atlas-datapurpose; theatlas-data/dagster/slot reserved for Dagster@assetdefinitions.atlas-data/ingest/scripts/migrate.ts— existing migration runner; the migration-deploy PLAN wires it into either a Dagster asset (Q7a) or a one-shot pod (Q7b).atlas-frontend/README.md— customer Next.js app; not deployed in v1, retained as a local-dev reference.atlas-contributor-frontend/README.md— contributor diagnostics; local-dev only by design.website/docs/ai-developer/plans/completed/INVESTIGATE-public-api-surface.md— why PostgREST and how it's exposed (UIS-owned).website/docs/ai-developer/plans/backlog/INVESTIGATE-developer-docs-surface.md— narrative-docs content scope. Now served from Docusaurus root onatlas.sovereignsky.no(via GitHub Pages); the file needs reconciling (it still names a separatedeveloper-atlas.helpers.nohostname that this plan no longer uses).website/docs/ai-developer/plans/backlog/PLAN-008-developer-discovery-surface.md— Scalar + lineage panel insideatlas-frontend; v1 ship paused becauseatlas-frontendisn't deployed. Phase 3 (dbt-docs hosting) supersedes into the Docusaurus deploy described here.
UIS-side (cross-repo)
- UIS repo — sovereign K8s stack Atlas runs on.
- UIS PostgREST install — the deployed
api-atlas.helpers.no/api-atlas.localhostinstance. urbalurba-infrastructure/website/docs/ai-developer/plans/backlog/INVESTIGATE-dagster.md— UIS Dagster install (Helm chart, resource sizing, code-location pattern, manualhelm upgrade). The authoritative source for everything about how Dagster runs in UIS; this doc defers to it.
External
- Scalar API Reference — MIT-licensed; embedded in the Docusaurus
/apipage. - Dagster OSS — orchestration platform UIS will install.
@dagster-io/dagster-pipes— official TypeScript Pipes SDK; pinned version added toingest/package.jsonin Atlas PLAN-002.- GitHub Actions services — ephemeral Postgres in CI.
Not in scope for this investigation
- PostgREST CI/CD — UIS owns it.
- Dagster platform install — UIS owns it. Tracked in their INVESTIGATE-dagster.md.
- Cloudflare Tunnel — not used in v1; everything goes through standard UIS Traefik ingress. Revisit later if there's a reason to expose Atlas surfaces outside the UIS ingress.
- Authentik / Okta / Gravitee / Azure APIM — v1.5+; not v1.
- Building any of this — this is task enumeration. Implementation PLANs follow.
- Picking a release-versioning convention — defer to the CI-bootstrap PLANs once they're drafted (within the constraint that
atlas-datatags must be unique). - Deciding whether
atlas-data/splits into its own repo — tracked inatlas-data/README.md. Polyglot-image complexity is a new pressure but not a v1 forcing function. - A standalone Scalar deployment — Scalar ships as
/apiinside the Docusaurus site; no separate hostname, app, or pipeline.developer-atlas.helpers.nois dropped from the plan. - A standalone dbt-docs deployment — dbt-docs ships as
/lineage/inside the Docusaurus site; no separate hostname, app, or pipeline. - Deploying either Next.js frontend in v1 — both stay in the repo as local-dev surfaces. Re-evaluate when there's a concrete need to expose them publicly.
- Reconciling PLAN-008 and INVESTIGATE-developer-docs-surface.md to this new picture — tracked separately; mentioned here in cross-references for awareness.
- The Dagster
@assetcontent itself — schedules, asset bodies, lineage wiring belong in Atlas PLAN-002 / PLAN-003 (counterparts to UIS PLAN-002 / PLAN-003 in the UIS doc), not in this deployment-pipeline investigation.