# 000 — `olsitec-foundation` Repository Topology > **Purpose**: define what lives where under `~/work/olsitec-foundation`, which directories are > independent git repositories vs. one mono-repo, and how shared Pulumi modules are vendored now and > consumed from the foundation later. > **Status**: Active. **Companion**: [ADR-005](decisions/ADR_005_repo_topology.md), > [PLAN-002](planning/PLAN-002-foundation-implementation.md). --- ## 1. The workspace root is NOT a git repo `~/work/olsitec-foundation/` is a **workspace root**, following the Olsitec convention (baseline PD-2: "the workspace root is usually not a git repository"). It holds **two** independent git repositories: ``` ~/work/olsitec-foundation/ # workspace root — NOT a git repo ├── foundation/ # GIT REPO #1 — the platform mono-repo (the DR unit) └── ai-baseline/ # GIT REPO #2 — the cross-project agentic workflow pattern ``` Both repos are hosted in **foundation-Forgejo** once it exists (`forge.olsitec.de/olsitec/foundation`, `forge.olsitec.de/olsitec/ai-baseline`). Until then they live locally + an offsite git mirror (DR). --- ## 2. Why two repos (the mono-repo vs single-repo decision) | Repo | Kind | Why this boundary | |------|------|-------------------| | **`foundation`** | **Mono-repo** (Bun workspaces) | The egg (`bootstrap/`) and the shared Pulumi modules it needs (`packages/`) **must be co-versioned and present without a registry at day-zero** (the registry doesn't exist yet — bootstrap paradox). One `git clone` = the full DR unit. Project docs travel with it. | | **`ai-baseline`** | **Single small repo** | Consumed by **every** Olsitec project (foundation + all Layer-1 products), on an **independent release cadence**. It should not drag the platform's weight, and ADR-003 already specced it as standalone. | **What is deliberately NOT in here:** downstream **consumer projects** (the existing olsicloud4 K8s platform, products like seaspots, olsitrack2…). They are their own repos and consume the foundation's **published** packages — they do not vendor or sit inside this workspace. > Rule of thumb: **co-version what must boot together (mono-repo); separate what is consumed on its > own cadence (its own repo + published artifact).** --- ## 3. `foundation` mono-repo layout ``` foundation/ # GIT REPO #1 (mono-repo, Bun workspaces) ├── package.json # workspace root (defines packages/* + bootstrap) ├── VERSIONS # pinned image+tool digests (determinism) ├── README.md ├── bootstrap/ # ── THE EGG ── single Pulumi project (DR unit core) │ ├── Pulumi.yaml │ ├── Pulumi.foundation.yaml # passphrase-encrypted config + secrets │ ├── index.ts # phase orchestration │ ├── components/ # network, postgres, rustfs, vault, credentials, proxy, forgejo, runner │ ├── phases/ lib/ config.ts │ └── config/ # template SOURCES (app.ini.tmpl, Caddyfile.tmpl, pg-init.sql) ├── packages/ # ── SHARED PULUMI MODULES ── each independently publishable │ ├── pulumi-docker/ # @olsitec/pulumi-docker │ ├── pulumi-vault/ # @olsitec/pulumi-vault │ ├── pulumi-tls/ # @olsitec/pulumi-tls │ ├── pulumi-hetzner/ # @olsitec/pulumi-hetzner │ ├── pulumi-cloudflare/ # @olsitec/pulumi-cloudflare │ ├── pulumi-rustfs/ # @olsitec/pulumi-rustfs (new) │ ├── pulumi-postgres/ # @olsitec/pulumi-postgres (new) │ ├── pulumi-forgejo/ # @olsitec/pulumi-forgejo (new) │ ├── pulumi-caddy/ # @olsitec/pulumi-caddy (new) │ └── pulumi-runner/ # @olsitec/pulumi-runner (new) ├── preflight/ # tooling/host validation ├── backup/ dr/ # backup + disaster-recovery automation ├── .forgejo/workflows/ # CI (preflight, pulumi preview/up, backup-verify) └── documentation/ # ── PROJECT DOCS ── (this folder) ├── 000_TOPOLOGY.md # this file ├── 000_baseline.md # thin overlay → ai-baseline + foundation deviations ├── planning/ # PLAN-001 (vision), PLAN-002 (strategy) ├── decisions/ # ADRs (004 layered platform, 005 topology, …) ├── contracts/ agents/ sessions/ knowledge_base/ retrospectives/ _templates/ ``` ### Why `bootstrap/` and `packages/` share one repo Day-zero, the egg cannot pull `@olsitec/pulumi-vault` from a registry — **the registry is part of what it is building**. With Bun workspaces, `bootstrap/` resolves `@olsitec/pulumi-*` from `packages/*` **locally on disk**. No registry needed to bootstrap. This is the concrete resolution of the "registry hosts the modules that build the registry" paradox (PLAN-002 §5.2). --- ## 4. `ai-baseline` repo layout ``` ai-baseline/ # GIT REPO #2 ├── 000_baseline.md # the CANONICAL full agentic baseline (single source of truth) ├── _templates/ # ADR, contract, session, snapshot templates └── README.md # what this is + how projects consume it ``` This is ADR-003's `ai-baseline`, **re-homed from gitlab.com to foundation-Forgejo**. Every project's `documentation/000_baseline.md` becomes a **thin overlay** that references this canonical file and lists only project-specific deviations. --- ## 5. Module vendoring & distribution strategy The lifecycle of a shared module has **three stages**: ``` STAGE 1 VENDOR (now) Copy the existing olsicloud4 module → foundation/packages/pulumi-/. Pin it. bootstrap/ consumes it via Bun workspace (local, no registry). STAGE 2 PUBLISH (after egg) Once foundation-Forgejo npm registry is live, CI publishes each package as @olsitec/pulumi-@ to it (semantic-release-monorepo, Conventional Commits — see memory: olsitec-charts-conventional-commits). STAGE 3 CONSUME (steady) Downstream projects switch their imports from the old olsicloud4/pulumi/modules/ to @olsitec/pulumi-@ pulled from the foundation registry. The old modules are frozen, then removed. ``` This is exactly the user's intent: *"a copy placed there… later hosted via the foundation… existing uses of vault modules will then use the module hosted from the foundation."* ### 5.1 Mapping: existing olsicloud4 module → foundation package | `olsicloud4/pulumi/modules/` | → `foundation/packages/` | Day-zero need | Notes | |---|---|---|---| | `docker` | `pulumi-docker` | **Yes** | Egg orchestration (`@pulumi/docker` over SSH). Reuse `DockerDeployments` wrapper. | | `vault` | `pulumi-vault` | **Yes** | Includes `policy.ts`. Core of the secret layer. | | `tls` | `pulumi-tls` | Maybe | Cert helpers; may defer to Caddy/Vault-PKI. | | `hetzner` | `pulumi-hetzner` | Phase 0 | VM provisioning + offsite host. | | `cloudflare` | `pulumi-cloudflare` | Networking | DNS records + ACME DNS-01 token. | | `olsitec` | `pulumi-olsitec` | Partial | The `OlsitecProject` feature-flag component (ADR-002). Layer-1 oriented (K8s); the egg uses a lighter subset. Vendor for reference, refactor for Layer 0. | | `minio` | — (superseded) | No | Foundation uses **RustFS**, not MinIO → new `pulumi-rustfs`. | | `gitlab` | — (retired) | No | GitLab is what the foundation **replaces**. | | `kubernetes`, `k3s`, `libvirt`, `baremetal` | — (Layer 1) | No | Belong to Layer-1 / legacy provisioning, not the egg. | ### 5.2 New packages (no existing module) `pulumi-rustfs`, `pulumi-postgres`, `pulumi-forgejo`, `pulumi-caddy`, `pulumi-runner` — authored fresh as foundation tasks (PLAN-002 §10: T03/T04/T05/T07/T08/T10). > **Do not copy module code yet.** Stage-1 vendoring of `docker` + `vault` (+ `hetzner`, `cloudflare`) > is a deliberate task with its own commit, to be done when T00 starts — not blindly bulk-copied with > `node_modules`. This doc defines the destinations; the copy is gated on the contracts (T00). --- ## 6. DR implication The DR unit is **the `foundation` mono-repo + master passphrase + offsite backup bundle** (PLAN-002 §6). Because `packages/` is inside the mono-repo, a single clone restores both the egg and the exact module sources it was built from — no registry, no external module fetch required to recover. `ai-baseline` is operationally useful but **not** required to recover the platform.