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>
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 withnode_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.