# T02 — Pulumi project skeleton + passphrase backend + `config.ts` — Subtask Outline **Task:** PLAN-002 §10 T02 · **Mode:** BUILD (scaffolding; no deploy) · **Date:** 2026-06-30 **Realizes:** CONTRACT_001 (config schema), 000_TOPOLOGY.md §5 Stage-1 vendoring, ADR-005. ## Goal Scaffold the Bun-workspace mono-repo + the `bootstrap/` Pulumi egg with a typed config layer (CONTRACT_001), and vendor the `pulumi-docker` + `pulumi-vault` shared modules into `packages/`. No real VM, no `pulumi up`. ## Subtasks 1. **Workspace root** — `foundation/package.json` with `workspaces: ["packages/*","bootstrap"]`. 2. **Vendor `@olsitec/pulumi-docker`** — copy olsicloud4 `modules/docker` source only; rename package; `VENDORED.md`. 3. **Vendor `@olsitec/pulumi-vault`** — copy `modules/vault` (incl. `policy.ts`) source only; rename; `VENDORED.md`. - Sub-issue: upstream `index.ts` imports 5 **type-only** decls from `../../modules/olsitec` (which pulls in minio/gitlab/kubernetes). Re-homed those types verbatim into a local `olsitec-types.ts`; re-pointed the one import. No logic change. 4. **`bootstrap/Pulumi.yaml`** — `name: foundation`, `runtime: nodejs` + `packagemanager: bun`. 5. **`bootstrap/config.ts`** — `FoundationConfig` interface + `loadConfig()` that reads flat dotted Pulumi keys and FAILS CLOSED listing all missing/malformed required keys. 6. **`bootstrap/index.ts`** — no-op scaffold; calls `loadConfig()` so preview exercises validation; creates no resources; exports a few non-secret outputs. 7. **`bootstrap/Pulumi.foundation.yaml`** — NON-secret placeholders only (CONTRACT_001 §1.2). No secrets, no encryptionsalt. 8. **Validate** — `bun install` links the workspace; `tsc --noEmit` on all three; `pulumi preview` under the **passphrase** provider + local file backend (`bootstrap/state/`, gitignored) + throwaway ENV passphrase. Demonstrate the fail-closed path. ## Key contracts honoured - CONTRACT_001 §1.1 shape; §1.2 non-secret keys under `foundation:`; §1.3 secrets deferred. - CONTRACT_003 fixed names/ports/network referenced by the placeholder config. - Image digests come from `VERSIONS` (T01), not config.