Tags give the ability to mark specific points in history as being important
-
v0.1.0
Release: gitlab-simulation v0.1.07a2045f5 · ·gitlab-simulation v0.1.0, tagged retroactively on 2026-09-28 for the 2026-07-06 release. ## [0.1.0] - 2026-07-06 ### Added - Initial release. GitLab self-managed and Duo simulation provisioner for Google Compute Engine, packaged as a Claude Code plugin. - Three install bases: `caproni` (helm/k3s cloud-native), single-VM `omnibus`, and `dev` (gitlab-org/gitlab source + build-images container, for `rspec`/`rubocop`/`rake` without a GDK). - Duo Agent Platform / AIGW seeding via canonical upstream primitives, self-hosted model wiring, and an 8-section verifier. - AIGW slow-model scenario: a custom/patched, non-mock image and a timeout harness. - Airgap/offline archetypes: single-plane (in-VM mirror, then seal) and the two-plane low-to-high diode (connected forge feeding a sealed enclave). - SDLC-utilization seeding layer: GPT for structure, an API-driven activity layer per SDLC stage, and per-persona shaping (see `gce/seeding.md`). Exercised end to end against a fresh `omnibus` instance seeded via `manifold seed --users 60 --yes`: 60 users / 224 MRs / 186 issues / 176 pipelines collected and 5 of 6 domains lit up (Security read zero -- no Ultimate license, no runner -- the expected result for a default instance). - Per-simulation Playwright MCP browser verification (the multiplexer). - Scheduled `drift-check` CI job: static upstream-symbol drift detection against `gitlab-org/gitlab` source, no VM required. - `sims/` routing and fidelity test batteries, plus a `just sims-check` gate that a tag-triggered CI job re-runs before release. - Runner registration: `just duo-runner-register` (tag-scoped `gitlab--duo`, for Duo workload jobs) and `just ci-runner-register` (general-purpose, `run_untagged: true`, for untagged CI/scan jobs), each binding a base-correct executor (shell on `omnibus`, podman-docker on `caproni`). - Contributor decision-record formats under `docs/`: ADR, RFC, and PRD templates with an index, and a `CONTRIBUTING.md` pointer. ADR-0001 records the single-front-door decision. - Brand assets (hero, avatar, favicon) following the GitLab Public Sector design language. - Backing-service access recipes in `gce/gce.md`: the `gdk psql` / `gdk rails c` / ClickHouse-client substitutes per base (omnibus wrappers, caproni `kubectl`/CNPG, dev's `bundle exec rails console`). Caproni's DB and ClickHouse recipes, and dev's `psql` database name and user, remain lab-pending per ADR-0002; dev's profiling-gem availability is flagged lab-pending rather than asserted. - Documented `caproni-dev` as a roadmap base: caproni's running services plus a source mount, the planned full-stack tier for operations `dev`'s source-only checkout cannot reach. Not a live `--base` yet. - Companion pointer to the official GitLab AI skills (`gitlab-org/ai/skills`): this environment is the GDK-free substitute their contribution workflows run against. ### Changed - Description tightened to a 491-character, trigger-dense form with an explicit SaaS/durable negative boundary (see `sims/fire-battery.md` for the routing battery that validated it). - Front matter scopes execution to `just` plus `Read`, making the justfile the enforced front door. - `just` is the single interface: every operation is a `just` recipe, and `simulation.sh` is the engine it wraps. A new `ssh-cmd` recipe carries a command with quotes or pipes to the VM intact, so ad-hoc access no longer drops to the engine directly. See ADR-0001. ### Fixed - Marketplace self-named `gitlab-simulation` (previously `gitlab-public-sector`) so the sibling repository's marketplace can be added alongside without a name collision; the install command is `/plugin install gitlab-simulation@gitlab-simulation`. - `just seed <scenario>` forwards the documented `GPT_*`/`SEED_*` knobs into the remote seed run (a declared `SEED_ENV_KNOBS` allowlist). Previously only `ACCESS_TOKEN`/`GITLAB_URL` reached the seed script's shell, so a knob set in front of `just seed` was silently dropped. - Corrected the seeding admin-PAT note (the laptop-state `root_pat` and the on-VM PAT are distinct tokens; `just seed` uses the laptop one), documented the `just ssh` quoting limitation with the `ssh-cmd` alternative, and raised the `omnibus` setup-time estimate to ~15-25 min. - `simulation.sh` `usage()` now lists every subcommand it dispatches (it had omitted `rails-config`, the `airgap-*` set, `two-plane`, `validate`, and `enable-flows`), and a `rails-config` recipe was added so every subcommand has a front-door recipe. - Documented the `enable-flow` precondition (the top-level group's foundational-flow allowlist must be populated first, via `enable-flows` or `dap-bootstrap`) and fixed a stale `enable_flow.rb` docstring that pointed at a file which never existed.
-
v0.2.0
Release: gitlab-simulation v0.2.00adbb92e · ·gitlab-simulation v0.2.0 ## [0.2.0] - 2026-09-28 ### Added - `just real-model` swaps the mock model for a real provider behind the same AI gateway, and `real-model off` swaps back. Two routes reach one, and both authenticate as the VM: Vertex through the instance service account, Bedrock through a federated role assumed with a GCE identity token a refresher keeps current, so neither leaves a long-lived secret on the VM. `just real-model proxy bedrock|vertex` puts a pinned LiteLLM container on the loopback interface between the gateway and the provider so the composed request becomes readable, and `just real-model param-strip` sends one request twice, once with `temperature` removed at the proxy, to demonstrate which one a provider that has stopped accepting the parameter refuses. - `just airgap-probe` reports the egress a VM actually has, on any base, without changing anything. It classifies exit codes rather than reading every failure as proof of isolation, and probes IP literals, a high port, and a second network so a dead resolver cannot decide the verdict. - The omnibus base has an airgap path of its own: `airgap-mirror` builds a dnf package repository served over loopback, and `airgap-verify` proves the instance stays healthy, that `dnf` reaches the mirror while the remote repositories are unreachable, and that `gitlab-ctl reconfigure` completes under the seal. - `just advanced-search` (omnibus) stands up a single-node OpenSearch or Elasticsearch on the VM, points GitLab at it, indexes the instance, and proves the result with `GET /groups/:id/search?scope=notes` -- a scope no other configuration serves. The engine major comes from the version matrix GitLab publishes, read at run time rather than transcribed. It refuses without a Premium or Ultimate license, and refuses on caproni and dev, where the settings would apply and nothing would index. `just advanced-search-status` reports engine health, the settings and index state without changing anything. - `SIM_OWNER` labels every created VM with whoever it belongs to, so a machine running several simulations shows which is which. Unset reads `unattributed`. - `just geo list` reports every Geo pair holding state on the machine. ### Fixed - The caproni base no longer sets `CLOUD_CONNECTOR_SELF_SIGN_TOKENS`, which caproni-demo's values carry and customer installs never do. With it, GitLab self-signed Cloud Connector tokens for every feature and the GitLab Duo health check ran its development probes, so a finding about token issuance or the health check did not describe a customer instance. Self-hosted features still self-sign, which is all the flow chain needs. The install fails if the key appears in a form the bootstrap cannot remove. - No command prints or keeps a minted credential's characters. `duo-runner-register` and `ci-runner-register` logged the first eight characters of the runner authentication token and now log only its length. The runner token and root PAT mints no longer write receipts, which held the full values under `~/.gitlab-simulation/receipts/` after teardown. The caproni install summary, which `up` shows, names the secret holding the root password instead of printing it, and the Geo failover report gives the registry notification secret's length instead of its value. - `dap-bootstrap` (through `self-hosted-model`) gives the self-hosted model to every feature a foundational flow on the running instance resolves to, read from its flow catalog, instead of `duo_agent_platform` alone. A flow such as `developer/v1` resolves its own feature, and with no model selected for it an offline-licensed instance sent the workflow token request to `cloud.gitlab.com` and failed with "Could not obtain Duo Workflow token". A feature the instance withholds or rejects is reported and skipped, and `trigger-preflight` now checks the flow's own feature. - `airgap-unseal` and `down` never delete a seal rule another simulation may still hold. Rules left under the pre-rename shared names (`sim-enclave-deny-egress`, `sim-enclave-allow-internal`) are deleted only when no other `sim-` instance exists and no instance carries the shared `sim-enclave` tag; otherwise they are left in place and reported with the instances that may depend on them. The shared tag is always removed from the instance being unsealed, so a simulation sealed before the rename unseals. - `airgap-seal` names its network tag and firewall rules for the instance it seals (`<instance>-sealed`, `<instance>-seal-allow-internal`, `<instance>-seal-deny-egress`), and `two-plane` names the forge's registry rule for its forge. Every sealed simulation in a project used to carry one shared tag and one shared pair of rules, so a second seal silently reused the first one's rules and tearing either simulation down unsealed the other. - `airgap-seal` waits until the seal is observably in effect rather than returning as soon as the firewall rules are recorded. Rules are enforced some seconds after `gcloud` returns, so a verify run in that window reported NOT_SEALED against a seal that was merely still landing. - The omnibus negative leg forces a metadata refetch. Plain `dnf makecache` refetches only what it considers expired, so shortly after the mirror step it exited 0 without contacting anything and reported the remote repositories as reachable on a sealed host: it was measuring cache freshness while claiming to measure reachability. - The omnibus package mirror serves on 18080 rather than 8080, which is Puma's. The collision surfaced as "the mirror is not answering", and had GitLab answered the mirror's health path at all the positive control would have been measuring the wrong process. The mirror step now refuses a busy port and names what holds it. - The airgap negative control is a comparison instead of an assertion, so it can now fail in both directions. `airgap-seal` records whether egress was reachable before it creates any firewall rule and refuses to seal when it was not, and `airgap-verify` refuses a verdict without that baseline and reports INCONCLUSIVE where it cannot tell a seal from a broken probe. Previously a host with egress wide open and only its resolver broken confirmed the airgap. - `airgap-mirror` and `airgap-verify` refuse on a base they do not fit, including an unknown base, where they used to half-run. On omnibus the base-agnostic negative control passed while every k3s step behind it no-opped or died, so the run confirmed the reassuring half and skipped the proving half. - caproni's mirror-pull check fails when the verify pod never starts. It ran a 20-iteration wait and then fell through printing nothing, so a mirror that served nothing produced no output and no failure. - `two-plane verify` uses the same negative control as `airgap-verify` rather than its own inline copy, which had the same defect. - A license file is applied through `GitlabSubscriptions::UploadLicenseService` rather than saved onto the `License` model directly, so an offline cloud license provisions its `add_on_products` into add-on purchases at upload instead of waiting for the nightly cron. The service declines an online cloud license, which belongs on the activation-code path, and `just license` names that cause rather than relaying the admin page's markup. - The add-on step no longer creates an add-on purchase when provisioning produced none. It prints what the license carried against what was provisioned and says the two disagree, because a purchase the harness made itself is indistinguishable from one the product produced. - The docs no longer imply a caproni simulation carries ClickHouse or NATS. The `gitlab-dev-stack` chart can ship both; the caproni-demo values the simulator installs it with disable both, so no base provides either. `just drift-check` now asserts those switches, and `MAINTENANCE.md` registers the absence. - `--gitlab-version` is documented per base: an exact package version on omnibus, the Helm chart version on caproni, a git branch on dev. Only omnibus reaches a chosen GitLab application version. - Geo state is per pair (`SIM_GEO_PAIR`), where a single `geo.json` previously made the archetype the one base two simulations could not share. A second `geo up` overwrote the instance names the first cluster's `geo down` reads, leaving two VMs running with nothing tracking them. `geo up` now refuses when the state file or either instance name is already taken, and a command run against a pair with no state names the pairs that do have some. - `bootstrap-gitlab-dev.sh`'s `run.sh` wrapper exports `PATH`/`GOFLAGS` and marks the bind-mounted clone a Git safe directory before the wrapped command runs inside the container. The container's Git refused the host-owned mount as "dubious ownership," which surfaced misleadingly as "fatal: not in a git directory" from TestEnv's Gitaly tasks. - The `dev` base's clone loop falls back to a commit-pinned archive tarball once its 20 retries are exhausted. `gitlab.com` sheds `git upload-pack` under load well before it sheds the API or archive endpoints, so the fallback resolves the branch to a SHA and downloads the archive instead of failing. - The `dev` base bootstrap removes `config/redis.yml` after generating the `.example` configs. Left in place, its cluster-ports template overrides `resque.yml`'s standalone Redis, which the rest of the setup assumes. Pre-1.0: under SemVer 0.x a minor version may carry breaking changes (ADR-0002).