diff --git a/.env.example b/.env.example index 1c024c7..fa1a481 100644 --- a/.env.example +++ b/.env.example @@ -58,7 +58,7 @@ # Set HOST_REPO_PATH in docker-compose.yml to enable the GUI upgrade button. # Without this, use SSH + ./upgrade.sh for server upgrades. # -# HOST_REPO_PATH=/home/jarrodl/bnk-forge-v2 +# HOST_REPO_PATH=/path/to/bnk-forge # ============================================================================ # ENVIRONMENT (development/staging/production) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d8f62e..b2da845 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -668,12 +668,17 @@ jobs: # dependencies. No `|| true` here: if this cannot run, the job has # nothing to say and must fail loudly rather than silently continue. # - # Known fragility, accepted deliberately: the floor's models are - # imported under CURRENT pins, so the gap widens every time a - # dependency moves. v3.0.1 pins cryptography 44 and staging is on 50 — - # six majors — and it holds only because the floor tree touches just - # Fernet, hazmat.primitives.serialization and Ed25519PrivateKey, all - # unchanged across that range. When it does bite, it bites as a + # Known limitation on this repo: f5devcentral/bnk-forge is a squashed + # public mirror and carries exactly ONE final tag, v3.1.6, so the floor + # is currently that tag and the upgrade window is one release wide — + # the degenerate case this check otherwise warns against. It can't be + # widened by naming an older tag (v3.0.1 etc. from the upstream history + # aren't reachable here); it widens only as more finals are cut on this + # repo. Accepted deliberately. + # + # The floor's models are imported under CURRENT pins, so a dependency + # gap can still bite once the window does widen. When it does, it bites + # as a # MANDATORY gate failing hard on a commit that changed nothing # relevant. The fix then is to raise MIN_UPGRADE_FROM to a release # whose models import cleanly, not to add `|| true` here: a floor that diff --git a/.trivyignore b/.trivyignore index 46fa12f..829c581 100644 --- a/.trivyignore +++ b/.trivyignore @@ -4,26 +4,28 @@ # projects rebuild with a patched Go version. # # Review this file periodically and remove entries when upstream fixes are available. +# Each entry carries an `exp:` review-by date — Trivy drops the suppression after it, +# forcing a re-check. Extend an entry only after re-confirming no upstream fix exists. # CVE-2025-68121: Go stdlib crypto/tls - Unexpected session resumption # Fixed in Go >= 1.24.13 / 1.25.7 / 1.26.0-rc.3 # Affects: helm (Go 1.25.0), kubectl, tofu (Go 1.25.6), infracost (Go 1.25.4) # All current latest releases use Go < 1.25.7 — no upstream fix available yet # Added: 2026-02-23 -CVE-2025-68121 +CVE-2025-68121 exp:2026-11-30 # CVE-2024-45337: golang.org/x/crypto/ssh - Misuse of ServerConfig.PublicKeyCallback # Present in infracost binary's bundled dependencies # Not exploitable in our context (we don't run an SSH server via infracost) # Added: 2026-02-23 -CVE-2024-45337 +CVE-2024-45337 exp:2026-11-30 # CVE-2026-33186: gRPC authorization bypass (google.golang.org/grpc < 1.79.3) # Affects: helm and tofu binaries in Docker image (grpc v1.76.0) # Status: Waiting for upstream helm/tofu releases with fixed grpc # Tracked: GitHub issue #50 # Added: 2026-04-15 -CVE-2026-33186 +CVE-2026-33186 exp:2026-11-30 # CVE-2026-7598: libssh2 — integer overflow via large username/password # Affects: libssh2-1t64 1.11.1-1 in Debian trixie base image @@ -32,11 +34,16 @@ CVE-2026-33186 # The vulnerable code path requires libssh2 to negotiate auth with a # malicious remote SSH server, which our HTTP backend never does. # Upstream: no Debian backport yet (Trivy reports empty fix column). -# REVISIT: monthly via https://security-tracker.debian.org/tracker/CVE-2026-7598 -# escalate to pin-from-sid if no fix by 2026-08-12 +# REVISIT: monthly. Do not extend this entry on the assertion that no fix exists — +# confirm it: re-run `trivy image` (or check the tracker) and only keep +# the ignore while the fix column is still empty for our base image's +# libssh2. https://security-tracker.debian.org/tracker/CVE-2026-7598 +# The 2026-08-12 deadline lapsed without that re-check; next check by +# 2026-09-12, and escalate to pin-from-sid if a fixed version is then +# available and we're still ignoring it. # Tracked: memory/followup_trivyignore_cve_2026_7598_revisit.md # Added: 2026-05-12 -CVE-2026-7598 +CVE-2026-7598 exp:2026-09-12 # CVE-2026-42010: GnuTLS Authentication Bypass via NUL Character in DN parsing # Affects: libgnutls30t64 in our Debian Trixie base image (3.8.9-3+deb13u2) @@ -49,7 +56,7 @@ CVE-2026-7598 # REVISIT: monthly via https://security-tracker.debian.org/tracker/CVE-2026-42010 # Pattern mirror of CVE-2026-33845 / CVE-2026-7598 suppressions. # Added: 2026-05-14 -CVE-2026-42010 +CVE-2026-42010 exp:2026-11-30 # CVE-2026-42496: perl — Archive::Tar < 3.08 extracts symlinks unsafely # CVE-2026-8376: perl — heap buffer overflow in the interpreter (<= 5.43.10) @@ -69,8 +76,8 @@ CVE-2026-42010 # https://security-tracker.debian.org/tracker/CVE-2026-8376 # Drop once Debian ships a trixie point-release with patched perl. # Added: 2026-06-02 -CVE-2026-42496 -CVE-2026-8376 +CVE-2026-42496 exp:2026-11-30 +CVE-2026-8376 exp:2026-11-30 # CVE-2026-13221: libperl5.40 — silently incorrect results in Perl <= 5.43.9 # Affects: libperl5.40 5.40.1-6 in the python:3.11-slim (Debian trixie) base image @@ -80,7 +87,7 @@ CVE-2026-8376 # REVISIT: monthly via https://security-tracker.debian.org/tracker/CVE-2026-13221 # drop once Debian ships a trixie update with a patched libperl5.40. # Added: 2026-07-15 -CVE-2026-13221 +CVE-2026-13221 exp:2026-11-30 # CVE-2026-60002: openssh-client — memory corruption in SSH client # Affects: openssh-client in the python:3.11-slim (Debian trixie) base image @@ -91,7 +98,7 @@ CVE-2026-13221 # REVISIT: monthly via https://security-tracker.debian.org/tracker/CVE-2026-60002 # drop once Debian ships a trixie update with a patched openssh-client. # Added: 2026-07-15 -CVE-2026-60002 +CVE-2026-60002 exp:2026-11-30 # CVE-2026-33845: GnuTLS DTLS — reachable-assert / auth bypass in DN parsing # Affects: libgnutls30t64 in our Debian Trixie base image (3.8.9-3+deb13u2) @@ -105,7 +112,7 @@ CVE-2026-60002 # Check: https://security-tracker.debian.org/tracker/CVE-2026-33845 # Tracked: GitHub issue #103 # Added: 2026-05-06 -CVE-2026-33845 +CVE-2026-33845 exp:2026-11-30 # CVE-2026-57433: perl Storable signed-integer flaw (Storable < 3.41) # Affects: libperl5.40, perl-base (5.40.1-6) in our Debian Trixie base image. @@ -117,4 +124,4 @@ CVE-2026-33845 # trixie-security. Check: https://security-tracker.debian.org/tracker/CVE-2026-57433 # Tracked: GitHub issue #492 # Added: 2026-07-22 -CVE-2026-57433 +CVE-2026-57433 exp:2026-11-30 diff --git a/CHANGELOG.md b/CHANGELOG.md index 294cdf6..03118a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,54 @@ # Changelog -All notable changes to BNK-Forge v2. +All notable changes to BNK-Forge. --- +## v3.1.6 (2026-08-10) — 3.1.x line + +Milestone `v3.1.6` — the last release before 4.0.0, and the initial public +release tag on `f5devcentral`. This mirror is squashed: the `v3.1.6` tag is a +single `feat: initial public release` commit, so there is no per-change history +behind it to link here. Work that came *after* this tag — including the +container-runner hardening series (#2, #123, #161) and the ADR-424 bare-metal/DPU +work — is part of 4.0.0, not v3.1.6, and is recorded under the 4.0.0 entry when +that release is cut. + +> **Heads-up for the 4.0.0 upgrade — two breaking changes:** +> +> 1. **Container runner non-root gate:** it now refuses *named* users — an image +> using the distroless-standard `USER nonroot` is rejected. Switch it to a +> numeric uid. Use **`USER 1000`**: the workspace is mounted from the host +> and chowned `1000:1000`, so uid 1000 is the only value that clears the gate +> *and* can write it. A higher uid such as `65532` passes the non-root gate but +> cannot write the workspace, so the step fails on its first write. +> 2. **`MCP_SERVICE_PASSWORD` becomes required in 4.0.0 (via bonnyr-f5 #188):** +> starting with 4.0.0 the backend refuses to boot in staging/production if it +> is unset or still a shipped default (`changeme` / `mcp-service-changeme`). +> That boot-time check ships in #188 — it is *not* in the 3.1.x line and is +> called out here only so the upgrade step is ready before #188 lands. Every +> existing install still carries one of those defaults, so before upgrading to +> 4.0.0 **set `MCP_SERVICE_PASSWORD` to a real secret** (the same value the MCP +> server receives as `BNK_FORGE_PASSWORD`); once #188 is in the tree, leaving +> it at a default will `SystemExit` the stack at startup. +> +> **Merge ordering (integration dependency).** The dist-bundle wiring these two +> steps assume — the dedicated `mcp` service account for the bundled MCP server, +> and the `MCP_SERVICE_PASSWORD` boot check — arrives in **bonnyr-f5 #186** (service +> account + removal of the shipped `changeme` / `mcp-service-changeme` defaults) and +> **#188** (boot check). This release documents them forward-looking and is therefore +> sequenced to merge **with or after #186 + #188**. Merged ahead of them, the +> `MCP_SERVICE_PASSWORD` guidance is inert for the dist stack (the compose file does +> not pass that variable to the backend) and #186 will conflict in +> `user-pack/install-guide.html` — resolve by taking #186's credential model, not by +> re-adding the `changeme` default this guide describes as a stopgap. + +## v3.0.1 — 3.0.x line + +The first 3.x release after the 2.x line below (upstream tag dated 2026-04-09). +Bridged entry; this repo is a squashed public mirror, so the `v3.0.1` tag and its +per-change history live upstream, not here. + ## v2.10.74 (2026-03-04) — TMM Debug Panel Enhancements: F5 Docs Commands, Netkvest, Bug Fix ### Bug Fixes diff --git a/backend/services/execution/container_runner.py b/backend/services/execution/container_runner.py index 79c2f61..ef1434e 100644 --- a/backend/services/execution/container_runner.py +++ b/backend/services/execution/container_runner.py @@ -550,7 +550,9 @@ def is_root_user(image_user: str | None) -> bool: An image that never declares USER reports an empty string and runs as root — that is the common case and must be caught. - Closes the numeric bypass only — see the KNOWN GAP note in the body. + Fails closed on anything that is not a bare non-zero decimal uid, + which also subsumes the named-alias case (see the body) — there is no + remaining KNOWN GAP. Only the uid half decides this. Docker's USER is ``[:]``, so an image declaring ``USER 0:100`` or ``USER root:wheel`` runs as uid 0 @@ -647,7 +649,8 @@ def _fail(message: str, stdout: str = "") -> StepResult: f"Artifact image {spec.image_digest} runs as root " f"(USER={image_user or ''}). Refusing to start it: the workspace is " f"mounted from the host, so a root container is a host-root write primitive. " - f"Rebuild the image with a NUMERIC non-root USER (e.g. `USER 65532`). " + f"Rebuild the image with a NUMERIC non-root USER — `USER 1000` matches " + f"the workspace owner (chowned 1000:1000), so the step can write it. " f"A named user is refused because it cannot be resolved to a uid " f"without the image's own /etc/passwd — `USER toor` may well be uid 0. " f"The Kubernetes substrate already enforces this: runAsNonRoot is " diff --git a/bin/roadmap-add.py b/bin/roadmap-add.py index eb65507..c4ddc83 100755 --- a/bin/roadmap-add.py +++ b/bin/roadmap-add.py @@ -75,7 +75,7 @@ def main(): ap = argparse.ArgumentParser(description="Append an item to docs/roadmap.yaml") ap.add_argument("--section", help="section id (see --list-sections)") ap.add_argument("--title") - ap.add_argument("--status", help="status key (shipped/in_progress/blocked/deferred/planned)") + ap.add_argument("--status", help="status key (shipped/merged/in_progress/blocked/deferred/planned)") ap.add_argument("--refs", default="", help='comma-separated, e.g. "#216,PR #188"') ap.add_argument("--note", default="") ap.add_argument("--group", default="") diff --git a/bin/roadmap-gen.py b/bin/roadmap-gen.py index 5dd30b0..77a3aae 100755 --- a/bin/roadmap-gen.py +++ b/bin/roadmap-gen.py @@ -395,11 +395,12 @@ def main(): print("Wrote %s" % MD_PATH) print("Wrote %s" % HTML_PATH) print( - "Stats: in_progress=%d planned=%d shipped=%d blocked=%d deferred=%d" + "Stats: in_progress=%d planned=%d shipped=%d merged=%d blocked=%d deferred=%d" % ( count_status(data["sections"], "in_progress"), count_status(data["sections"], "planned"), count_status(data["sections"], "shipped"), + count_status(data["sections"], "merged"), count_status(data["sections"], "blocked"), count_status(data["sections"], "deferred"), ) diff --git a/dist/.env.example b/dist/.env.example index 0eaa12b..6584d7a 100644 --- a/dist/.env.example +++ b/dist/.env.example @@ -15,8 +15,8 @@ COMPOSE_PROJECT_NAME=bnk-forge # ── Container Registry ────────────────────────────────────────────────────── # Where to pull BNK Forge images from (no trailing slash) -BNK_FORGE_REGISTRY=ghcr.io/your-org -BNK_FORGE_VERSION=3.0.1 +BNK_FORGE_REGISTRY=ghcr.io/f5devcentral +BNK_FORGE_VERSION=latest # ── Database ──────────────────────────────────────────────────────────────── POSTGRES_PASSWORD=bnkforge_dev_password diff --git a/dist/README.md b/dist/README.md index 7c0c011..a74fdce 100644 --- a/dist/README.md +++ b/dist/README.md @@ -3,7 +3,7 @@ ## Prerequisites - **Docker Engine 24+** with **Docker Compose v2.24+** -- Access to the BNK Forge container registry (if private) +- Network access to `ghcr.io` (images are public — no registry login required) - 4 GB RAM minimum (8 GB recommended) - 10 GB disk space @@ -12,8 +12,8 @@ ### 1. Download and extract ```bash -tar xzf bnk-forge-3.0.1.tar.gz -cd bnk-forge-3.0.1 +tar xzf bnk-forge-3.1.6.tar.gz +cd bnk-forge-3.1.6 ``` ### 2. Configure @@ -27,25 +27,12 @@ nano .env # Set BNK_FORGE_REGISTRY and passwords | Variable | Description | Example | |---|---|---| -| `BNK_FORGE_REGISTRY` | Container registry URL (no trailing slash) | `ghcr.io/your-org` | -| `BNK_FORGE_VERSION` | Image version tag | `3.0.1` | +| `BNK_FORGE_REGISTRY` | Container registry URL (no trailing slash) | `ghcr.io/f5devcentral` (public) | +| `BNK_FORGE_VERSION` | Image version tag | `3.1.6` | | `POSTGRES_PASSWORD` | PostgreSQL password | *(change for production)* | | `REDIS_PASSWORD` | Redis password | *(change for production)* | -### 3. Authenticate to registry (if private) - -```bash -# GitHub Container Registry -echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin - -# Docker Hub -docker login - -# AWS ECR -aws ecr get-login-password | docker login --username AWS --password-stdin ACCOUNT.dkr.ecr.REGION.amazonaws.com -``` - -### 4. Install +### 3. Install **Linux server** (host networking — production): ```bash @@ -59,7 +46,7 @@ chmod +x install.sh ./install.sh --local ``` -### 5. Access +### 4. Access - **Mac/Windows (`--local`):** open **https://localhost** - **Linux server:** open **https://\** — the installer prints the exact URL at the end @@ -183,7 +170,7 @@ gunzip -c backup_20260417.sql.gz | docker exec -i bnk-forge-postgres psql -U bnk ## File Structure ``` -bnk-forge-3.0.1/ +bnk-forge-3.1.6/ ├── docker-compose.yml # Main compose (Linux server — host networking) ├── docker-compose.local.yml # Overlay for macOS/Windows (bridge networking) ├── .env.example # Configuration template @@ -235,17 +222,17 @@ This creates `dist/bnk-forge-VERSION.tar.gz` containing all files needed for ins echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin # Build + push all images for amd64 + arm64 (default) -make push-images BNK_FORGE_REGISTRY=ghcr.io/your-org +make push-images BNK_FORGE_REGISTRY=ghcr.io/f5devcentral # Or push only amd64 (faster, if you don't need ARM) -make push-images BNK_FORGE_REGISTRY=ghcr.io/your-org PLATFORMS=linux/amd64 +make push-images BNK_FORGE_REGISTRY=ghcr.io/f5devcentral PLATFORMS=linux/amd64 ``` -This uses `docker buildx build --push` to build all 6 images (api, worker, beat, frontend, proxy, mcp) for both architectures and push **multi-arch manifest lists** to the registry. Each tag (e.g., `bnk-forge-api:3.0.1`) is a manifest that Docker automatically resolves to the correct platform on `docker pull`. +This uses `docker buildx build --push` to build all 7 images (api, worker, beat, frontend, proxy, mcp, operator) for both architectures and push **multi-arch manifest lists** to the registry. Each tag (e.g., `bnk-forge-api:3.1.6`) is a manifest that Docker automatically resolves to the correct platform on `docker pull`. **Verify the manifest:** ```bash -docker manifest inspect ghcr.io/your-org/bnk-forge-api:3.0.1 +docker manifest inspect ghcr.io/f5devcentral/bnk-forge-api:3.1.6 ``` You should see entries for both `linux/amd64` and `linux/arm64`. @@ -266,18 +253,21 @@ gh release create v${VERSION} dist/bnk-forge-${VERSION}.tar.gz \ ### What `gh release create` does -1. Creates a Git tag (`v3.0.1`) on the current commit -2. Creates a GitHub Release page at `https://github.com/your-org/bnk-forge/releases/tag/v3.0.1` +1. Creates a Git tag (`v3.1.6`) on the current commit +2. Creates a GitHub Release page at `https://github.com/f5devcentral/bnk-forge/releases/tag/v3.1.6` 3. Uploads the tarball as a downloadable release asset ### End-user download URL -After publishing, users can download and install with: +Once a full (non-prerelease) `vX.Y.Z` release with an attached tarball exists, users +download and install with the URL below — substitute the version you actually published +(the example `3.1.6` is illustrative; no release asset exists until you cut one): ```bash -# Download from GitHub Releases -curl -L https://github.com/your-org/bnk-forge/releases/download/v3.0.1/bnk-forge-3.0.1.tar.gz | tar xz -cd bnk-forge-3.0.1 +# Download from GitHub Releases — replace 3.1.6 with your published version +VERSION=3.1.6 +curl -L https://github.com/f5devcentral/bnk-forge/releases/download/v${VERSION}/bnk-forge-${VERSION}.tar.gz | tar xz +cd bnk-forge-${VERSION} ./install.sh ``` diff --git a/dist/docker-compose.yml b/dist/docker-compose.yml index 286b7de..36456d0 100644 --- a/dist/docker-compose.yml +++ b/dist/docker-compose.yml @@ -11,7 +11,7 @@ # # Prerequisites: # - Docker Engine 24+ with Compose v2.24+ -# - Authenticated to the container registry (if private) +# - Network access to ghcr.io (images are public — no registry login required) # # Configuration: # Copy .env.example to .env and set your passwords before first start. @@ -19,8 +19,8 @@ # ── Registry configuration ────────────────────────────────────────────────── # Set BNK_FORGE_REGISTRY and BNK_FORGE_VERSION in .env or environment: -# BNK_FORGE_REGISTRY=ghcr.io/your-org (no trailing slash) -# BNK_FORGE_VERSION=3.0.1 (or "latest") +# BNK_FORGE_REGISTRY=ghcr.io/f5devcentral (no trailing slash) +# BNK_FORGE_VERSION=3.1.6 (or "latest") x-backend-env: &backend-env DATABASE_URL: postgresql://bnkforge:${POSTGRES_PASSWORD:-bnkforge_dev_password}@localhost:5432/bnkforge @@ -160,7 +160,7 @@ services: memory: 32M backend: - image: ${BNK_FORGE_REGISTRY:-ghcr.io/your-org}/bnk-forge-api:${BNK_FORGE_VERSION:-latest} + image: ${BNK_FORGE_REGISTRY:-ghcr.io/f5devcentral}/bnk-forge-api:${BNK_FORGE_VERSION:-latest} container_name: bnk-forge-backend network_mode: host logging: *default-logging @@ -201,7 +201,7 @@ services: memory: 256M celery-worker: - image: ${BNK_FORGE_REGISTRY:-ghcr.io/your-org}/bnk-forge-worker:${BNK_FORGE_VERSION:-latest} + image: ${BNK_FORGE_REGISTRY:-ghcr.io/f5devcentral}/bnk-forge-worker:${BNK_FORGE_VERSION:-latest} container_name: bnk-forge-celery-worker network_mode: host logging: *default-logging @@ -233,7 +233,7 @@ services: memory: 512M celery-worker-2: - image: ${BNK_FORGE_REGISTRY:-ghcr.io/your-org}/bnk-forge-worker:${BNK_FORGE_VERSION:-latest} + image: ${BNK_FORGE_REGISTRY:-ghcr.io/f5devcentral}/bnk-forge-worker:${BNK_FORGE_VERSION:-latest} container_name: bnk-forge-celery-worker-2 network_mode: host logging: *default-logging @@ -265,7 +265,7 @@ services: memory: 512M celery-beat: - image: ${BNK_FORGE_REGISTRY:-ghcr.io/your-org}/bnk-forge-beat:${BNK_FORGE_VERSION:-latest} + image: ${BNK_FORGE_REGISTRY:-ghcr.io/f5devcentral}/bnk-forge-beat:${BNK_FORGE_VERSION:-latest} container_name: bnk-forge-celery-beat network_mode: host logging: *default-logging @@ -295,7 +295,7 @@ services: memory: 64M frontend: - image: ${BNK_FORGE_REGISTRY:-ghcr.io/your-org}/bnk-forge-frontend:${BNK_FORGE_VERSION:-latest} + image: ${BNK_FORGE_REGISTRY:-ghcr.io/f5devcentral}/bnk-forge-frontend:${BNK_FORGE_VERSION:-latest} container_name: bnk-forge-frontend network_mode: host logging: *default-logging @@ -321,7 +321,7 @@ services: memory: 32M proxy: - image: ${BNK_FORGE_REGISTRY:-ghcr.io/your-org}/bnk-forge-proxy:${BNK_FORGE_VERSION:-latest} + image: ${BNK_FORGE_REGISTRY:-ghcr.io/f5devcentral}/bnk-forge-proxy:${BNK_FORGE_VERSION:-latest} container_name: bnk-forge-proxy network_mode: host logging: *default-logging @@ -347,7 +347,7 @@ services: memory: 32M mcp: - image: ${BNK_FORGE_REGISTRY:-ghcr.io/your-org}/bnk-forge-mcp:${BNK_FORGE_VERSION:-latest} + image: ${BNK_FORGE_REGISTRY:-ghcr.io/f5devcentral}/bnk-forge-mcp:${BNK_FORGE_VERSION:-latest} container_name: bnk-forge-mcp network_mode: host logging: *default-logging diff --git a/dist/install.sh b/dist/install.sh index 2c8be22..a57cdb9 100644 --- a/dist/install.sh +++ b/dist/install.sh @@ -10,7 +10,7 @@ # # Prerequisites: # - Docker Engine 24+ with Compose v2.24+ -# - Authenticated to the container registry (if private) +# - Network access to ghcr.io (images are public — no registry login required) # set -euo pipefail diff --git a/docs/DOCKER.md b/docs/DOCKER.md index f25eaeb..65944d3 100644 --- a/docs/DOCKER.md +++ b/docs/DOCKER.md @@ -58,7 +58,7 @@ docker build --target worker --build-arg INSTALL_INFRACOST=true -t bnk-forge-wor ## Keyless Image Signing, SBOM, and Provenance -BNK Forge images published to the registry are signed with **keyless cosign** (Sigstore Fulcio + +BNK Forge images published **from v4.0.0 onward** (the first release cut through the signing pipeline) are signed with **keyless cosign** (Sigstore Fulcio + Rekor transparency log). No long-lived signing key is stored — the signature is bound to the OIDC identity of whoever ran the publish script at the time of signing. @@ -83,36 +83,43 @@ The script signs each image by digest (not tag) and attaches two attestations: ### Verifying signatures (consumers) -Replace `` with the email of the person who signed the images (visible in the -Rekor transparency log entry), and `` with the image digest. +Replace `` with the image digest you're verifying. You do **not** fill in a +signer — official images are signed by the release workflow (`release.yml`), and the +commands below already pin that identity with `--certificate-identity-regexp … release.yml@…`. + +> **Note:** this verifies images published by CI. If a maintainer signed an image +> locally via the manual path above (`SIGN_EXECUTE=1`), it is bound to *that +> person's* OIDC identity, not the workflow's, so it will not match the regexp +> here — verify it with `--certificate-identity ` instead. Official +> releases always go through `release.yml`. ```bash # Verify the signature cosign verify \ - ghcr.io/jlcode-tech/bnk-forge-api@ \ - --certificate-identity \ - --certificate-oidc-issuer https://github.com/login/oauth + ghcr.io/f5devcentral/bnk-forge-api@ \ + --certificate-identity-regexp 'https://github.com/f5devcentral/bnk-forge/\.github/workflows/release\.yml@.*' \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com # Verify + extract the SBOM attestation cosign verify-attestation \ --type cyclonedx \ - --certificate-identity \ - --certificate-oidc-issuer https://github.com/login/oauth \ - ghcr.io/jlcode-tech/bnk-forge-api@ \ + --certificate-identity-regexp 'https://github.com/f5devcentral/bnk-forge/\.github/workflows/release\.yml@.*' \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + ghcr.io/f5devcentral/bnk-forge-api@ \ | jq -r '.payload' | base64 -d | jq . # Verify + extract the SLSA provenance attestation cosign verify-attestation \ --type slsaprovenance \ - --certificate-identity \ - --certificate-oidc-issuer https://github.com/login/oauth \ - ghcr.io/jlcode-tech/bnk-forge-api@ \ + --certificate-identity-regexp 'https://github.com/f5devcentral/bnk-forge/\.github/workflows/release\.yml@.*' \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + ghcr.io/f5devcentral/bnk-forge-api@ \ | jq -r '.payload' | base64 -d | jq . ``` Apply the same commands to the other image names: `bnk-forge-worker`, `bnk-forge-beat`, `bnk-forge-frontend`, `bnk-forge-proxy`, -`bnk-forge-mcp`. +`bnk-forge-mcp`, `bnk-forge-operator`. ### OCI Labels diff --git a/docs/How to write CI container runner modules and blueprints for BNK Forge.md b/docs/How to write CI container runner modules and blueprints for BNK Forge.md index 4357830..48a4e79 100644 --- a/docs/How to write CI container runner modules and blueprints for BNK Forge.md +++ b/docs/How to write CI container runner modules and blueprints for BNK Forge.md @@ -654,9 +654,14 @@ The container engine is deliberately constrained: which is the default for most base images*). The workspace is mounted from the host, so a root container would be a host-root write primitive. Forge does **not** silently remap you to another uid with `--user`: that would override your image's `USER` and break your - own state writes. So: put `USER ` in your Dockerfile. uid **1000** matches the - workspace owner and is the safe choice. This mirrors Kubernetes `runAsNonRoot`, which the - Kubernetes runner applies to the same artifacts. + own state writes. So: put a **numeric** `USER` in your Dockerfile. The gate requires a bare + decimal uid — uid **1000** matches the workspace owner and is the safe choice. A **named** + user such as `USER nonroot` (the distroless default) is now **refused**: a name can't be + resolved to a uid without the image's own `/etc/passwd`, so it can't be proven non-root. + If you were on `USER nonroot`, switch to `USER 1000` — it matches the workspace owner (chowned + `1000:1000`), so your state writes under `mount_path` succeed. A higher uid such as `65532` clears + the non-root gate but cannot write the host-mounted workspace. + This mirrors Kubernetes `runAsNonRoot`, which the Kubernetes runner applies to the same artifacts. - **A dedicated network** — steps attach to the `bnk-forge-artifacts` bridge network rather than the daemon's default bridge, so artifact containers don't sit alongside unrelated containers. Egress still works (you can reach cloud control planes); you just don't share diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 12a346f..555a229 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -7,7 +7,7 @@ Source sweep: memories + ADRs (D-001…D-028) + GitHub issues + open PRs, 2026-06-12. **Deep doc sweep 2026-06-03:** swept `docs/specs/`, sprint plans, and strategic docs; statuses **code-verified** before assignment (many specs that read as "proposed" are in fact already built — see §10). New gap issues from the sweep: #216/#217/#218. **2026-06-09 sync:** D-021/D-022 fleet epics shipped (PRs #276/#277); D-027 zero-toast shipped (PRs #260/#261/#278); D-028 unified blueprint catalog shipped (PR #274); D-001 Phase 3 / D-019 E1/E3/E6 / Ops MCP+celery / AWS cred-expiry UX all shipped. D-023 (classic BIG-IP) + D-020 (F5 design-system) + benchmark experience remain in-flight. -**2026-06-12 sync:** cb-rebuild → staging de-stacking COMPLETE; new `customer-build` integration line live on localhost (staging + all open PRs + customer deltas); multi-arch images published `ghcr.io/jlcode-tech 3.1.6-cb.72b29dbb` + rolling `customer-build`. D-023 P1-P3 shipped (PR #280); alembic dedupe shipped (PR #283). 13 PRs in review: #282 (scenario override guard), #284 (BNK registry-driven GA/ReleaseRegistry), #285 (multiarch publish), #286 (benchmark remote agent-host + Slice-4 auth), #287 (AI-Analyzer rename + Migration tab fix), #288 (dist uninstall-purge fix), #290 (D-023 P4 CIS coverage), #291 (Dashboard Command Center fleet section), #292 (bfb-cache atime/LRU fix), #293 (runtime brand flag #289), #295 (CIS IngressClass kind-aware classify), #296 (top-level Infrastructure section), #297 (release automation — team decision pending). D-020 reskin branch fully rebuilt 2026-06-10/11 (complete reskin + anvil ForgeLogo general rebrand). +**2026-06-12 sync:** cb-rebuild → staging de-stacking COMPLETE; new `customer-build` integration line live on localhost (staging + all open PRs + customer deltas); multi-arch images published `ghcr.io/f5devcentral 3.1.6-cb.72b29dbb` + rolling `customer-build`. D-023 P1-P3 shipped (PR #280); alembic dedupe shipped (PR #283). 13 PRs in review: #282 (scenario override guard), #284 (BNK registry-driven GA/ReleaseRegistry), #285 (multiarch publish), #286 (benchmark remote agent-host + Slice-4 auth), #287 (AI-Analyzer rename + Migration tab fix), #288 (dist uninstall-purge fix), #290 (D-023 P4 CIS coverage), #291 (Dashboard Command Center fleet section), #292 (bfb-cache atime/LRU fix), #293 (runtime brand flag #289), #295 (CIS IngressClass kind-aware classify), #296 (top-level Infrastructure section), #297 (release automation — team decision pending). D-020 reskin branch fully rebuilt 2026-06-10/11 (complete reskin + anvil ForgeLogo general rebrand). **Human view (clickable):** `docs/roadmap.html` · **Contribution flow:** `docs/ROADMAP_PROCESS.md` · (local per-clone agent queue: `.agent/backlog/BACKLOG.md`). --- @@ -28,7 +28,7 @@ Source sweep: memories + ADRs (D-001…D-028) + GitHub issues + open PRs, 2026-0 | **Ops: MCP service account + celery-beat healthcheck** | ✅ Shipped | [PR #214](https://github.com/f5devcentral/bnk-forge/issues/214) | Shipped. PR #214 merged. Dedicated non-human `mcp` account (admin-rotation no longer breaks MCP auth) + mtime-freshness beat healthcheck. | | **Benchmark experience / security hardening** | 🟡 In progress | [PR #211](https://github.com/f5devcentral/bnk-forge/issues/211) · [PR #251](https://github.com/f5devcentral/bnk-forge/issues/251) · [PR #282](https://github.com/f5devcentral/bnk-forge/issues/282) · [PR #286](https://github.com/f5devcentral/bnk-forge/issues/286) · [#294](https://github.com/f5devcentral/bnk-forge/issues/294) | PR #282 (scenario override guard security fix) + PR #286 (remote agent-host provisioning + built-in agent + Slice-4 auth + ported tests) in review. PR #251 (authz/WS-auth/atomic-claim/TLS+SSRF) folds into #211; gated on a maintainer driving #211→staging. #294 (benchmarks page IA + New Run wizard port) deferred pending user decision. | | **GHCR customer-build publish target + postgres-backup compose drift fix** | ✅ Shipped | [PR #242](https://github.com/f5devcentral/bnk-forge/issues/242) · [PR #243](https://github.com/f5devcentral/bnk-forge/issues/243) | Shipped. PR #242 (postgres-backup compose drift fix) + PR #243 (GHCR customer-build publish target) merged. | -| **Multi-arch image publish + dist uninstall-purge fix + install messaging** | 🟡 In progress | [PR #285](https://github.com/f5devcentral/bnk-forge/issues/285) · [PR #288](https://github.com/f5devcentral/bnk-forge/issues/288) | PR #285 (push-customer-build-multiarch target: amd64+arm64 to ghcr.io/jlcode-tech) + PR #288 (uninstall --purge deletes wrong compose volumes fix + stale install messaging) in review. | +| **Multi-arch image publish + dist uninstall-purge fix + install messaging** | 🟡 In progress | [PR #285](https://github.com/f5devcentral/bnk-forge/issues/285) · [PR #288](https://github.com/f5devcentral/bnk-forge/issues/288) | PR #285 (push-customer-build-multiarch target: amd64+arm64 to ghcr.io/f5devcentral) + PR #288 (uninstall --purge deletes wrong compose volumes fix + stale install messaging) in review. | | **Alembic migration deduplication (v2_131)** | ✅ Shipped | [PR #283](https://github.com/f5devcentral/bnk-forge/issues/283) | Shipped. PR #283 merged. Deduped v2_130 collision (benchmark_run_groups renumbered → v2_131); broken staging migration head fixed. | | **Release automation — RC-on-staging / final-on-main (conventional-commit bumps)** | 🟡 In progress | [PR #297](https://github.com/f5devcentral/bnk-forge/issues/297) | PR #297 open; team decision pending — may be closed in favor of manual release flow. | | **D-021 — existing-proxy discovery & migration to BNK (P1+P2+P3)** | ✅ Shipped | [#233](https://github.com/f5devcentral/bnk-forge/issues/233) · [PR #276](https://github.com/f5devcentral/bnk-forge/issues/276) · ADR D-021 | Shipped. PR #276 consolidated (closes epic #233). Proxy discovery, migration path to BNK, P1/P2/P3 complete. | @@ -48,7 +48,7 @@ Source sweep: memories + ADRs (D-001…D-028) + GitHub issues + open PRs, 2026-0 | **awsbnkctl review follow-up** | 💤 Deferred | [#155](https://github.com/f5devcentral/bnk-forge/issues/155) | SimpleNamespace shim hardening + configured-shape contract test. (awsbnkctl side: SSO refresh-token bootstrap — sibling repo.) | | **Review follow-ups (deferred polish)** | 💤 Deferred | [#153](https://github.com/f5devcentral/bnk-forge/issues/153) · [#154](https://github.com/f5devcentral/bnk-forge/issues/154) · [#156](https://github.com/f5devcentral/bnk-forge/issues/156) · [#157](https://github.com/f5devcentral/bnk-forge/issues/157) | #153 (#144 TTFT/ports) · #154 (#146 _kind_to_snake) · #156 (#151 MCP envelope sweep) · #157 (#148 BNK substring/prefix). Non-blocking; created 2026-05-27. | | **Module catalog auto-sync on boot + wire blueprint wizard 'Sync' CTA** | ⚪ Planned | [#419](https://github.com/f5devcentral/bnk-forge/issues/419) | Fresh install / volume wipe leaves the git module catalog (bnk/app/infra packs) un-synced, so BNK/app blueprints are DOA until an operator runs Catalog→Advanced→Modules→'Sync all'. The wizard's 'requires sync' prompt is wired to no endpoint. Fix: (1) boot-time auto-sync step (non-fatal, ref-aware) after builtin seeders; (2) wire wizard CTA to POST /api/module-library/sync. Separate from the d019/adr-204 execution_engine seeder-guard fix. | -| **CI container runner engine — security hardening follow-ups** | ⚪ Planned | [#408](https://github.com/f5devcentral/bnk-forge/issues/408) · [PR #340](https://github.com/f5devcentral/bnk-forge/issues/340) | Non-blocking follow-ups from the #340 review (all prior blockers verified fixed pre-merge). Priority: non-root Docker gate bypass via `USER 0:` (host-root primitive), `state.outputs_file` path traversal (arbitrary worker-file read), registry `/test` cross-operator credential exfil + SSRF, install-script PAT/password xtrace leak, K8s deny-all egress netpol breaks the artifact. Plus same-project cluster-name clobber + nits. | +| **CI container runner engine — security hardening follow-ups** | 🟢 Merged (unreleased) | [#408](https://github.com/f5devcentral/bnk-forge/issues/408) · [PR #340](https://github.com/f5devcentral/bnk-forge/issues/340) | Non-blocking follow-ups from the #340 review (all prior blockers verified fixed pre-merge). Priority: non-root Docker gate bypass via `USER 0:` (host-root primitive), `state.outputs_file` path traversal (arbitrary worker-file read), registry `/test` cross-operator credential exfil + SSRF, install-script PAT/password xtrace leak, K8s deny-all egress netpol breaks the artifact. Plus same-project cluster-name clobber + nits. | | **Multi-version module catalog — immutable module versions, exact pin resolution (ADR D-033)** | 🟡 In progress | [#433](https://github.com/f5devcentral/bnk-forge/issues/433) · [PR #436](https://github.com/f5devcentral/bnk-forge/issues/436) | Module identity becomes (source, path, version); hashed rows immutable; blueprints resolve pins exactly (BLUEPRINT_MODULE_VERSION_MISSING); ProjectModule FK becomes a true pin with explicit change-version action + UI/MCP. Combined PR #436 (supersedes stacked #434/#435). ADR: docs/adr/D-033-multi-version-module-catalog.md (PR #432). | | **Module test actions — vendor-CLI e2e/scenario/bench tests via pipeline (ADR D-034)** | ⚪ Planned | [#454](https://github.com/f5devcentral/bnk-forge/issues/454) · [PR #453](https://github.com/f5devcentral/bnk-forge/issues/453) | Container-artifact manifests gain a declarative actions block; container engine gains one generic action dispatcher; UI offers actions on post-apply modules (per-scenario + run-all-green, amber behind warning). v1 results = logs + pass/fail. Scaling = edit vars + re-apply, not an action. Tool-embedded tests → pipeline; external load (aiperf agents) stays in Benchmarks. Slices: PR-1 backend, PR-2 UI, PR-3 packs/docs. ADR: docs/adr/D-034-module-test-actions.md (PR #453). Sibling: #452 cluster auto-registration. | | **Container-runner contract hardening — min_forge_version + declared capabilities** | ⚪ Planned | [#465](https://github.com/f5devcentral/bnk-forge/issues/465) | Phase 3 of the ctl-runner review. min_forge_version + capability requirements (e.g. wide docker-socket proxy) become machine-checkable artifact-manifest fields enforced at sync/import; Forge injects the proxy endpoint instead of external manifests hardcoding DOCKER_HOST; schema_version evolution policy lands in EXT-003. | diff --git a/docs/ROADMAP_PROCESS.md b/docs/ROADMAP_PROCESS.md index 8bdbe7a..7451532 100644 --- a/docs/ROADMAP_PROCESS.md +++ b/docs/ROADMAP_PROCESS.md @@ -34,7 +34,7 @@ backend/.venv/bin/python bin/roadmap-add.py \ ``` - `--list-sections` prints the available section ids + headings. -- `--status` must be one of: `shipped`, `in_progress`, `blocked`, `deferred`, `planned`. +- `--status` must be one of: `shipped`, `merged`, `in_progress`, `blocked`, `deferred`, `planned` (the keys in `status_legend`; `merged` = merged to staging but unreleased). - `--refs` is comma-separated; values like `#216` / `PR #188` become GitHub links. - `--group` (optional) buckets the item into a named card on the HTML view. - After adding, also update the **§12 issue index** (`render: raw`, edited by hand in the yaml) and re-run the generator so the index stays in sync. @@ -49,7 +49,7 @@ backend/.venv/bin/python bin/roadmap-add.py \ ## Status vocabulary -✅ shipped · 🟡 in-progress / partial · ⛔ blocked (state the blocker) · 💤 deferred (state the resume-trigger) · ⚪ not-started / proposed. +✅ shipped · 🟢 merged (merged to staging, unreleased) · 🟡 in-progress / partial · ⛔ blocked (state the blocker) · 💤 deferred (state the resume-trigger) · ⚪ not-started / proposed. ## Where things live diff --git a/docs/roadmap.html b/docs/roadmap.html index eb4ba5c..126ff53 100644 --- a/docs/roadmap.html +++ b/docs/roadmap.html @@ -68,7 +68,7 @@
23
In progress (tracked)
-
35
Planned (tracked)
+
34
Planned (tracked)
50+
PRs merged to staging
34
Issues closed
@@ -129,7 +129,7 @@

Active / next — issue-tracked, actionable now

Review follow-ups

    -
  • CI container runner engine — security hardening follow-ups#408 · PR #340
  • +
  • CI container runner engine — security hardening follow-ups#408 · PR #340
diff --git a/docs/roadmap.yaml b/docs/roadmap.yaml index fee9719..cab7ad4 100644 --- a/docs/roadmap.yaml +++ b/docs/roadmap.yaml @@ -17,7 +17,7 @@ # "AUTO:planned" are computed from item counts; any other # value (e.g. "25+") is a static meta number. # status_legend: key -> { emoji, dot, label } used for BOTH md + html. -# keys: shipped | in_progress | blocked | deferred | planned +# keys: shipped | merged | in_progress | blocked | deferred | planned # sections: ordered list of # - id: stable slug (used by roadmap-add.py --section) # number: section number for the md heading "## N. ..." @@ -55,7 +55,7 @@ meta: **2026-06-09 sync:** D-021/D-022 fleet epics shipped (PRs #276/#277); D-027 zero-toast shipped (PRs #260/#261/#278); D-028 unified blueprint catalog shipped (PR #274); D-001 Phase 3 / D-019 E1/E3/E6 / Ops MCP+celery / AWS cred-expiry UX all shipped. D-023 (classic BIG-IP) + D-020 (F5 design-system) + benchmark experience remain in-flight. - **2026-06-12 sync:** cb-rebuild → staging de-stacking COMPLETE; new `customer-build` integration line live on localhost (staging + all open PRs + customer deltas); multi-arch images published `ghcr.io/jlcode-tech 3.1.6-cb.72b29dbb` + rolling `customer-build`. D-023 P1-P3 shipped (PR #280); alembic dedupe shipped (PR #283). 13 PRs in review: #282 (scenario override guard), #284 (BNK registry-driven GA/ReleaseRegistry), #285 (multiarch publish), #286 (benchmark remote agent-host + Slice-4 auth), #287 (AI-Analyzer rename + Migration tab fix), #288 (dist uninstall-purge fix), #290 (D-023 P4 CIS coverage), #291 (Dashboard Command Center fleet section), #292 (bfb-cache atime/LRU fix), #293 (runtime brand flag #289), #295 (CIS IngressClass kind-aware classify), #296 (top-level Infrastructure section), #297 (release automation — team decision pending). D-020 reskin branch fully rebuilt 2026-06-10/11 (complete reskin + anvil ForgeLogo general rebrand). + **2026-06-12 sync:** cb-rebuild → staging de-stacking COMPLETE; new `customer-build` integration line live on localhost (staging + all open PRs + customer deltas); multi-arch images published `ghcr.io/f5devcentral 3.1.6-cb.72b29dbb` + rolling `customer-build`. D-023 P1-P3 shipped (PR #280); alembic dedupe shipped (PR #283). 13 PRs in review: #282 (scenario override guard), #284 (BNK registry-driven GA/ReleaseRegistry), #285 (multiarch publish), #286 (benchmark remote agent-host + Slice-4 auth), #287 (AI-Analyzer rename + Migration tab fix), #288 (dist uninstall-purge fix), #290 (D-023 P4 CIS coverage), #291 (Dashboard Command Center fleet section), #292 (bfb-cache atime/LRU fix), #293 (runtime brand flag #289), #295 (CIS IngressClass kind-aware classify), #296 (top-level Infrastructure section), #297 (release automation — team decision pending). D-020 reskin branch fully rebuilt 2026-06-10/11 (complete reskin + anvil ForgeLogo general rebrand). **Human view (clickable):** `docs/roadmap.html` · **Contribution flow:** `docs/ROADMAP_PROCESS.md` · (local per-clone agent queue: `.agent/backlog/BACKLOG.md`). @@ -77,6 +77,10 @@ status_legend: emoji: ✅ dot: d-ship label: Shipped + merged: + emoji: 🟢 + dot: d-ship + label: Merged (unreleased) in_progress: emoji: 🟡 dot: d-prog @@ -212,7 +216,7 @@ sections: refs: - 'PR #285' - 'PR #288' - note: 'PR #285 (push-customer-build-multiarch target: amd64+arm64 to ghcr.io/jlcode-tech) + PR #288 (uninstall --purge deletes wrong compose volumes fix + stale install messaging) in review.' + note: 'PR #285 (push-customer-build-multiarch target: amd64+arm64 to ghcr.io/f5devcentral) + PR #288 (uninstall --purge deletes wrong compose volumes fix + stale install messaging) in review.' group: Top of queue — PRs open (CI-green) - title: Alembic migration deduplication (v2_131) status: shipped @@ -353,7 +357,7 @@ sections: - '#419' note: 'Fresh install / volume wipe leaves the git module catalog (bnk/app/infra packs) un-synced, so BNK/app blueprints are DOA until an operator runs Catalog→Advanced→Modules→''Sync all''. The wizard''s ''requires sync'' prompt is wired to no endpoint. Fix: (1) boot-time auto-sync step (non-fatal, ref-aware) after builtin seeders; (2) wire wizard CTA to POST /api/module-library/sync. Separate from the d019/adr-204 execution_engine seeder-guard fix.' - title: CI container runner engine — security hardening follow-ups - status: planned + status: merged refs: - '#408' - 'PR #340' diff --git a/scripts/ibm_cloud_bnk_forge.sh b/scripts/ibm_cloud_bnk_forge.sh index 39d4ff5..34f562e 100644 --- a/scripts/ibm_cloud_bnk_forge.sh +++ b/scripts/ibm_cloud_bnk_forge.sh @@ -462,7 +462,7 @@ services: restart: unless-stopped backend: - image: ${BNK_FORGE_REGISTRY:-ghcr.io/your-org}/bnk-forge-api:${BNK_FORGE_VERSION:-latest} + image: ${BNK_FORGE_REGISTRY:-ghcr.io/f5devcentral}/bnk-forge-api:${BNK_FORGE_VERSION:-latest} container_name: bnk-forge-backend network_mode: host logging: *default-logging @@ -495,7 +495,7 @@ services: start_period: 30s celery-worker: - image: ${BNK_FORGE_REGISTRY:-ghcr.io/your-org}/bnk-forge-worker:${BNK_FORGE_VERSION:-latest} + image: ${BNK_FORGE_REGISTRY:-ghcr.io/f5devcentral}/bnk-forge-worker:${BNK_FORGE_VERSION:-latest} container_name: bnk-forge-celery-worker network_mode: host logging: *default-logging @@ -513,7 +513,7 @@ services: restart: unless-stopped celery-worker-2: - image: ${BNK_FORGE_REGISTRY:-ghcr.io/your-org}/bnk-forge-worker:${BNK_FORGE_VERSION:-latest} + image: ${BNK_FORGE_REGISTRY:-ghcr.io/f5devcentral}/bnk-forge-worker:${BNK_FORGE_VERSION:-latest} container_name: bnk-forge-celery-worker-2 network_mode: host logging: *default-logging @@ -531,7 +531,7 @@ services: restart: unless-stopped celery-beat: - image: ${BNK_FORGE_REGISTRY:-ghcr.io/your-org}/bnk-forge-beat:${BNK_FORGE_VERSION:-latest} + image: ${BNK_FORGE_REGISTRY:-ghcr.io/f5devcentral}/bnk-forge-beat:${BNK_FORGE_VERSION:-latest} container_name: bnk-forge-celery-beat network_mode: host logging: *default-logging @@ -547,7 +547,7 @@ services: restart: unless-stopped frontend: - image: ${BNK_FORGE_REGISTRY:-ghcr.io/your-org}/bnk-forge-frontend:${BNK_FORGE_VERSION:-latest} + image: ${BNK_FORGE_REGISTRY:-ghcr.io/f5devcentral}/bnk-forge-frontend:${BNK_FORGE_VERSION:-latest} container_name: bnk-forge-frontend network_mode: host logging: *default-logging @@ -563,7 +563,7 @@ services: start_period: 10s proxy: - image: ${BNK_FORGE_REGISTRY:-ghcr.io/your-org}/bnk-forge-proxy:${BNK_FORGE_VERSION:-latest} + image: ${BNK_FORGE_REGISTRY:-ghcr.io/f5devcentral}/bnk-forge-proxy:${BNK_FORGE_VERSION:-latest} container_name: bnk-forge-proxy network_mode: host logging: *default-logging @@ -575,7 +575,7 @@ services: restart: unless-stopped mcp: - image: ${BNK_FORGE_REGISTRY:-ghcr.io/your-org}/bnk-forge-mcp:${BNK_FORGE_VERSION:-latest} + image: ${BNK_FORGE_REGISTRY:-ghcr.io/f5devcentral}/bnk-forge-mcp:${BNK_FORGE_VERSION:-latest} container_name: bnk-forge-mcp network_mode: host logging: *default-logging diff --git a/scripts/publish-signed-images.sh b/scripts/publish-signed-images.sh index c3c0a02..79ed237 100755 --- a/scripts/publish-signed-images.sh +++ b/scripts/publish-signed-images.sh @@ -20,7 +20,7 @@ # BNK_FORGE_REGISTRY=ghcr.io/your-org BNK_FORGE_VERSION=3.1.6 ./scripts/publish-signed-images.sh --execute # # Environment variables: -# BNK_FORGE_REGISTRY — required; e.g. ghcr.io/jlcode-tech +# BNK_FORGE_REGISTRY — required; e.g. ghcr.io/f5devcentral # BNK_FORGE_VERSION — optional; defaults to contents of ./VERSION # DRY_RUN — set to 0 to execute (equivalent to --execute) # @@ -32,8 +32,8 @@ # # Consumer verification (see docs/DOCKER.md for full details): # cosign verify @ \ -# --certificate-identity \ -# --certificate-oidc-issuer https://github.com/login/oauth +# --certificate-identity-regexp 'https://github.com/f5devcentral/bnk-forge/\.github/workflows/release\.yml@.*' \ +# --certificate-oidc-issuer https://token.actions.githubusercontent.com set -euo pipefail @@ -294,14 +294,14 @@ else echo " Verify a signed image:" echo " cosign verify \\" echo " ${REGISTRY}/bnk-forge-api@ \\" - echo " --certificate-identity \\" - echo " --certificate-oidc-issuer https://github.com/login/oauth" + echo " --certificate-identity-regexp 'https://github.com/f5devcentral/bnk-forge/\.github/workflows/release\.yml@.*' \\" + echo " --certificate-oidc-issuer https://token.actions.githubusercontent.com" echo "" echo " Verify the SBOM attestation:" echo " cosign verify-attestation \\" echo " --type cyclonedx \\" - echo " --certificate-identity \\" - echo " --certificate-oidc-issuer https://github.com/login/oauth \\" + echo " --certificate-identity-regexp 'https://github.com/f5devcentral/bnk-forge/\.github/workflows/release\.yml@.*' \\" + echo " --certificate-oidc-issuer https://token.actions.githubusercontent.com \\" echo " ${REGISTRY}/bnk-forge-api@" fi echo "========================================================" diff --git a/user-pack/install-guide.html b/user-pack/install-guide.html index 1c2109c..f2b1aca 100644 --- a/user-pack/install-guide.html +++ b/user-pack/install-guide.html @@ -63,12 +63,6 @@ code{background:#eef0f2;border:1px solid var(--bd);border-radius:3px;padding:1px 5px; font-size:12.5px;color:var(--ink2);font-family:"SFMono-Regular",Consolas,"Liberation Mono",Menlo,monospace;} - /* ── Callout: credentials (red left border) ── */ - .callout-cred{background:#fff5f5;border-left:4px solid var(--f5red);border-radius:0 6px 6px 0; - padding:14px 18px;margin:14px 0;box-shadow:0 1px 2px rgba(20,30,40,.04);} - .callout-cred .callout-title{font-weight:700;color:var(--f5red);font-size:13px; - text-transform:uppercase;letter-spacing:.6px;margin-bottom:6px;} - /* ── Callout: warning (amber) ── */ .callout-warn{background:var(--warn-bg);border-left:4px solid var(--warn-bd);border-radius:0 6px 6px 0; padding:14px 18px;margin:14px 0;color:var(--warn);} @@ -100,7 +94,7 @@ @media print{ header{-webkit-print-color-adjust:exact;print-color-adjust:exact;} pre{white-space:pre-wrap;word-break:break-all;} - .callout-cred,.callout-warn,.callout-info{-webkit-print-color-adjust:exact;print-color-adjust:exact;} + .callout-warn,.callout-info{-webkit-print-color-adjust:exact;print-color-adjust:exact;} body{font-size:13px;} main{padding:10px 20px 30px;} } @@ -113,7 +107,7 @@ F5

BNK Forge — Install Guide

-
Private registry edition  |  customer-build distribution  |  registry: ghcr.io/jlcode-tech
+
Public registry edition  |  current-release distribution  |  registry: ghcr.io/f5devcentral
@@ -122,9 +116,9 @@

BNK Forge — Install Guide

- This guide walks you through installing BNK Forge from the private GitHub Container Registry. - You will authenticate to the registry using the read-only bot credential you were provided, - download the install package, make a small configuration change, and run a single script. + This guide walks you through installing BNK Forge from the public GitHub Container Registry. + You download the install package, make a small configuration change, and run a single + script. The images are public, so no registry login is required. The entire process takes under ten minutes on a fast connection; the first image pull may take a few minutes depending on bandwidth.
@@ -134,40 +128,12 @@

Prerequisites

  • Docker Engine 24+ — on macOS or Windows, Docker Desktop satisfies both this and the Compose requirement.
  • Docker Compose v2 (≥ 2.24) — verify with docker compose version.
  • -
  • Read-access token — the <READ_TOKEN> provided to you separately (see Step 1).
  • ~5–10 GB free disk space — for images and persistent data volumes.
  • Network access to ghcr.io — outbound HTTPS (port 443) must be allowed.
-

Step 1 — Authenticate to the registry

- -
-
Credentials — handle with care
- Your read-access token is provided separately (out-of-band). It is a GitHub PAT scoped to - read:packages for the ghcr.io/jlcode-tech registry. - Do not share it, commit it to version control, or embed it in scripts. - If you believe the token has been exposed, contact the person who gave it to you immediately. -
- -

Run the following command, replacing <READ_TOKEN> with the token you received. - The bot username is fixed — use it exactly as shown:

- -
$ echo '<READ_TOKEN>' | docker login ghcr.io -u jlcode-forgebot --password-stdin
- -

Expected output:

-
Login Succeeded
- -
-
Token stays cached
- Docker stores the credential in your OS keychain (or ~/.docker/config.json). - You only need to log in once per machine. If you later see a denied or - unauthorized error during a pull, re-run the command above — the token may have been - rotated. See the Troubleshooting section for details. -
- - -

Step 2 — Download & extract the package

+

Step 1 — Download & extract the package

You should have received a bnk-forge-<version>.tar.gz archive alongside this guide. Save it to a convenient location, then extract it:

@@ -177,8 +143,8 @@

Step 2 — Download & extract the package

All subsequent commands are run from inside this directory.

- -

Step 3 — Configure

+ +

Step 2 — Configure

Copy the example environment file and open it in your editor:

@@ -195,13 +161,13 @@

Step 3 — Configure

BNK_FORGE_REGISTRY - ghcr.io/jlcode-tech - Points to the private registry. + ghcr.io/f5devcentral + Points to the public registry. BNK_FORGE_VERSION - customer-build - Rolling latest build. To pin a specific build, use a tag like 3.0.1-cb.<sha>. + latest + Rolling latest release. To pin a specific version, use its tag, e.g. 3.1.6. POSTGRES_PASSWORD @@ -215,20 +181,46 @@

Step 3 — Configure

MCP_PASSWORD - your choice - Change from the default. Used by the MCP integration layer. + match the admin password + Must equal the password of the user in MCP_USERNAME. Credential the + bundled MCP server uses to authenticate to BNK Forge; it must match a real BNK Forge user + (the default MCP_USERNAME is admin, whose initial password is + changeme). Leave it at changeme for the first boot so it matches + the seeded admin account; it is re-read from .env on every boot, so after you + change the admin password (Step 4) set this to the same value and re-run + docker compose up -d (a plain docker compose restart does not + re-read .env). Setting it to an + independent secret before first login makes the MCP server 401 against the still-default + admin credential.
-
Change all three passwords
- The defaults in .env.example are well-known placeholders. - Replace POSTGRES_PASSWORD, REDIS_PASSWORD, and MCP_PASSWORD - before running the installer — they cannot be changed easily after the stack first starts. +
Set strong passwords before first start
+ POSTGRES_PASSWORD and REDIS_PASSWORD replace well-known + placeholder defaults, and they are baked in when the database and cache first + initialize — get them right before running the installer, as they cannot be changed + easily afterward. MCP_PASSWORD is different: it must always equal the password + of the admin account it authenticates as, so leave it at the shipped changeme + for first boot and rotate it together with the admin password afterward — it is + re-read on every boot, so edit .env and re-run docker compose up -d + to apply the new value (a plain docker compose restart does not re-read + .env). +

A second administrator ships seeded — mcp. Besides admin, + this build seeds an active admin-role account named mcp whose password is a shipped + default (mcp-service-changeme) published in the public repository. This compose file + wires no .env variable to the backend for it, and the backend reconciles its + password back to that default on every boot, so there is no supported way to rotate it in + this release — treat it as a live, publicly-known credential and keep the backend API off + untrusted networks until you upgrade. bonnyr-f5 #186 removes this shipped default and re-points + the bundled MCP server at this dedicated mcp service account, so that from 4.0.0 MCP + no longer borrows the human admin login; this release is sequenced to land with or + after #186. Until #186 is in the build you install, the bundled MCP server continues to + authenticate as admin via MCP_PASSWORD, as described above.

- -

Step 4 — Install

+ +

Step 3 — Install

Run the installer for your platform. It will pull the images and bring the full stack up. The first run may take a few minutes while images download.

@@ -251,8 +243,8 @@

Step 4 — Install

When the installer finishes you will see:

✅ Installation complete!
- -

Step 5 — First login

+ +

Step 4 — First login

  1. @@ -271,8 +263,8 @@

    Step 5 — First login

    Username: admin  /  Password: changeme

    Change the admin password immediately
    - The default password is well-known. Go to User menu → Change Password as your - very first action after login. + The default password is well-known — change it as your very first action after login, + via User menu → Change Password, before doing anything else.
  2. @@ -309,7 +301,7 @@

    Verify the stack is healthy

    Updating to a newer build

    -

    Because BNK_FORGE_VERSION=customer-build is a rolling tag, updating is simple. +

    Because BNK_FORGE_VERSION=latest is a rolling tag, updating is simple. From the install directory:

    # Recommended — uses the installer for any migration steps:
    @@ -322,6 +314,32 @@ 

    Updating to a newer build

    If you pinned a specific build tag in .env, update BNK_FORGE_VERSION to the new tag before running the command above.

    +
    +
    Before upgrading an older install to 4.0.0
    + If your .env predates this release, reconcile it first, or the upgrade will fail + to pull or refuse to boot: +
      +
    • Registry & version. Set BNK_FORGE_REGISTRY=ghcr.io/f5devcentral + (older packages pointed at a private org that no longer resolves), and replace any pinned + BNK_FORGE_VERSION such as 3.0.1 with latest or a + current tag like 3.1.6 — a stale pin pulls a tag that no longer exists.
    • +
    • Non-root artifact images. The container runner now refuses any image whose + USER is root or a named user (e.g. USER nonroot). Rebuild + your own runner images with a numeric USER 1000 before upgrading.
    • +
    • MCP service credential (from 4.0.0). In this bundle the MCP server authenticates + with MCP_PASSWORD (delivered to the MCP container as + BNK_FORGE_PASSWORD), so keep MCP_PASSWORD matching your admin + password as described in the settings table above. Setting MCP_SERVICE_PASSWORD + in this .env has no effect: this compose file does not pass that + variable to the backend, so the backend never reads it here. From 4.0.0, once bonnyr-f5 + #186 wires the MCP server to a dedicated mcp service account and #188 adds a + boot check, the backend will refuse to start in staging/production while + MCP_SERVICE_PASSWORD is unset or a shipped default — that is the point at + which you set that variable to a real secret. Neither mechanism ships in this bundle yet, + so this release is sequenced to land with or after #186 + #188.
    • +
    +
    +

    Uninstall

    @@ -335,10 +353,10 @@

    Troubleshooting

    • - denied: denied or unauthorized: unauthenticated during pull - Your docker login session has lapsed, or the token does not have the - read:packages scope. Re-run Step 1 with your current token. - If the problem persists, contact the person who issued the token. + manifest unknown, or a pull that hangs or times out + The images are public, so no login is required. Check that BNK_FORGE_REGISTRY + is ghcr.io/f5devcentral and that the version tag exists, and that outbound + HTTPS to ghcr.io (port 443) is allowed through any proxy or firewall.
    • Backend service not healthy @@ -358,8 +376,8 @@

      Troubleshooting