From c8f46341cc19b475d6fdc0bdd6c1dab4ac707bf8 Mon Sep 17 00:00:00 2001 From: fargo Date: Wed, 19 Aug 2026 15:54:44 -0500 Subject: [PATCH] fix(#1320): placeholder-ize private-network topology, drop raw-curl force-merge recipe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements the rev-security-01 verdict on #1320 (comment 23282): Should Fix (first, per tasking): mosaic-deploy's branch-protected-repos section shipped a working recipe for both failure modes the estate removes identity that is not the actor's (a legacy shared credential path, ~/.config/mosaic/credentials/gitea.env, which no longer exists in the credential system) and a quality gate routed around (raw curl + force_merge:true, no queue guard, no head pin). Replaced with wrapper-only merge guidance: protection blocks are signals to fix, not to bypass. Placeholder-ized estate RFC1918 topology and hostnames (six carriers, one more than the verdict's five — the original scan missed guides/): - skills/mosaic-portainer: Portainer URL, Docker host - skills/mosaic-gitea: SSH resolution target - skills/mosaic-deploy: Docker node, stack-name map (now generic example shape; estate mappings belong in skills-local overrides, which link with precedence) - tools/coolify/README: base URL - guides/INFRASTRUCTURE: cloudflare example moved from 10.0.0.5 to the RFC 5737 documentation range (192.0.2.5), the unambiguous example form Left as-is per the verdict's split: estate DNS endpoints (e.g. git.mosaicstack.dev, ci.mosaicstack.dev) pass as examples. Rescan of the whole shipped framework tree for RFC1918, estate hosts, and stack-name patterns: zero remaining hits. The gate defect itself is filed separately as #1321 (cross-referenced on #1320, comment 23285). --- .../mosaic/framework/guides/INFRASTRUCTURE.md | 2 +- .../framework/skills/mosaic-deploy/SKILL.md | 30 +++++++++---------- .../framework/skills/mosaic-gitea/SKILL.md | 2 +- .../skills/mosaic-portainer/SKILL.md | 4 +-- .../mosaic/framework/tools/coolify/README.md | 2 +- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/packages/mosaic/framework/guides/INFRASTRUCTURE.md b/packages/mosaic/framework/guides/INFRASTRUCTURE.md index adb4f033..48dc1b97 100644 --- a/packages/mosaic/framework/guides/INFRASTRUCTURE.md +++ b/packages/mosaic/framework/guides/INFRASTRUCTURE.md @@ -219,7 +219,7 @@ Use the Cloudflare tools for any DNS configuration: pointing domains at services # Update an existing record (get record ID from record-list first) ~/.config/mosaic/tools/cloudflare/record-update.sh \ - -z example.com -r -t A -n myapp -c 10.0.0.5 -p + -z example.com -r -t A -n myapp -c 192.0.2.5 -p ``` **DNS + Deployment integration**: When deploying a new service via Coolify or Portainer that needs a public domain, the typical sequence is: diff --git a/packages/mosaic/framework/skills/mosaic-deploy/SKILL.md b/packages/mosaic/framework/skills/mosaic-deploy/SKILL.md index d520a709..2182a033 100644 --- a/packages/mosaic/framework/skills/mosaic-deploy/SKILL.md +++ b/packages/mosaic/framework/skills/mosaic-deploy/SKILL.md @@ -42,14 +42,12 @@ cd ~/src/ ~/.config/mosaic/tools/git/pr-merge.sh -n -d ``` -For branch-protected repos (force merge): - -```bash -GITEA_TOKEN=$(cat ~/.config/mosaic/credentials/gitea.env | grep TOKEN | cut -d= -f2) -curl -X POST "https://git.mosaicstack.dev/api/v1/repos///pulls//merge" \ - -H "Authorization: token $GITEA_TOKEN" -H "Content-Type: application/json" \ - -d '{"Do":"squash","force_merge":true}' -``` +Always merge through `pr-merge.sh`: it runs the CI queue guard first and pins +the merge to the reviewed head. If branch protection blocks the merge, that is +a gate telling you something — a failing check, a moved head, or a missing +review. Fix the cause; never route around it with a raw API call, a shared +credential, or `force_merge`. Exceptional cases go to the operator or the +coordinating seat, still merged through the wrapper. ### Step 4: Redeploy Portainer stack @@ -67,16 +65,18 @@ Check deployment: ## Stack Name Map -| Project | Stack Name | -| ------------ | -------------- | -| mosaic-stack | `mosaic-stack` | -| sage-phr | `sage-phr` | -| openbrain | `openbrain` | -| firefly | `firefly` | +Maintain your estate's project → stack-name mapping in a skills-local override of +this skill (local copies take precedence over the shipped canonical one). Example +shape: + +| Project | Stack Name | +| ------------ | ----------------- | +| `sample-app` | `sample-app` | +| `sample-api` | `sample-api-prod` | ## Notes - Workers open PRs but **never merge** — orchestrator or Merge Guard handles step 3+ -- Docker Swarm image pinning: if `-p` doesn't pull a new image, SSH to `w-docker0` (10.1.1.45) and run `docker pull ` manually, then redeploy +- Docker Swarm image pinning: if `-p` doesn't pull a new image, SSH to the Docker node (e.g. `node-01`) and run `docker pull ` manually, then redeploy - Worktrees: all coding work in `~/src/-worktrees/`, never in main checkout - Always clean up worktree after push: `git worktree remove ~/src/-worktrees/` diff --git a/packages/mosaic/framework/skills/mosaic-gitea/SKILL.md b/packages/mosaic/framework/skills/mosaic-gitea/SKILL.md index cfb20b82..fd1a8818 100644 --- a/packages/mosaic/framework/skills/mosaic-gitea/SKILL.md +++ b/packages/mosaic/framework/skills/mosaic-gitea/SKILL.md @@ -98,5 +98,5 @@ curl -X POST "https://git.mosaicstack.dev/api/v1/repos///pulls//m ## Notes - Mosaic policy: squash merges only, targeting `main` -- Gitea SSH: `git@git.mosaicstack.dev` → resolves via `~/.ssh/config` to `10.1.1.90:2222` +- Gitea SSH: `git@git.mosaicstack.dev` → resolves via `~/.ssh/config` to the Gitea host's SSH port (e.g. `gitea.example.internal:2222`) - Workers push branches and open PRs but **never merge** — orchestrator handles merges diff --git a/packages/mosaic/framework/skills/mosaic-portainer/SKILL.md b/packages/mosaic/framework/skills/mosaic-portainer/SKILL.md index b0c5353a..cdb62b22 100644 --- a/packages/mosaic/framework/skills/mosaic-portainer/SKILL.md +++ b/packages/mosaic/framework/skills/mosaic-portainer/SKILL.md @@ -56,7 +56,7 @@ source ~/.config/mosaic/tools/_lib/credentials.sh && load_credentials portainer ## Notes -- Portainer URL: `https://10.1.1.43:9443` -- Primary Docker host: `w-docker0` (10.1.1.45) managed via Portainer agent +- Portainer URL: `https://portainer.example.internal:9443` +- Primary Docker host: `node-01`, managed via Portainer agent - Docker Swarm image updates: `stack-redeploy.sh -p` does NOT guarantee new image pull if digest is pinned; SSH to node and `docker pull` first if needed - Credentials: `load_credentials portainer` (framework credentials store) diff --git a/packages/mosaic/framework/tools/coolify/README.md b/packages/mosaic/framework/tools/coolify/README.md index 9e1eb826..d4b5ef0f 100644 --- a/packages/mosaic/framework/tools/coolify/README.md +++ b/packages/mosaic/framework/tools/coolify/README.md @@ -27,7 +27,7 @@ Manage Coolify container deployment platform (projects, services, deployments, e ## API Reference -- Base URL: `http://10.1.1.44:8000` +- Base URL: `http://coolify.example.internal:8000` - API prefix: `/api/v1/` - Auth: Bearer token in `Authorization` header - Rate limit: 200 requests per interval -- 2.54.0