foundation/documentation/000_TOPOLOGY.md
Andreas Niemann f18676e6b3 chore: scaffold olsitec-foundation mono-repo
Repo topology, baseline overlay, planning docs (PLAN-001/002), ADR-004/005,
and the bootstrap/packages/documentation skeleton. Implementation (T00+) not started.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 17:10:46 +02:00

8.9 KiB

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, PLAN-002.


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-<x>/.
                             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-<x>@<semver> 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/<x> to @olsitec/pulumi-<x>@<version> 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/<x> 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.