Conversation
Primary-source comparison of Portainer Agent, Komodo Periphery, Arcane Agent, Hawser, Docker-native access, socket proxies, and adjacent agents, plus the website and docs surfaces that carry those claims. - 📝 docs(landscape): add COMPETITIVE-LANDSCAPE.md and the docs page - ✨ feat(website): add the Arcane comparison route, sitemap entry, and llms.txt links - 🔄 refactor(website): fold comparison-rows.ts into per-competitor route data - 📝 docs(claims): correct stale Komodo auth/edge claims and separate agent features from Drydock controller responsibilities - 📝 docs(roadmap): record the pre-v1 competitive review gate, post-v1 candidates, and explicit security non-goals - 🔧 config(git): ignore the generated website/vercel.json
- 🐛 fix(compose): stat .env.drydock through os.Root so a planted symlink cannot redirect --env-file outside STACKS_DIR, and ignore non-regular files (go/path-injection, alert #18) - 🐛 fix(edge): sanitize execID and error on the initial resize-failure log, the only unsanitized log call in tunnel.go (go/log-injection, alert #190) - 🧪 test(compose): cover env-file symlink escape and non-regular env file
- 📦 deps(actions): repin every action to current, incl. actions/checkout v7 and actions/setup-go v7 (ESM migrations; no pull_request_target or workflow_run in any workflow, so the v7 fork-ref restriction is moot) - 📦 deps(docker): bump the wolfi-base digest - 📦 deps(npm): TypeScript 7, Next 16.3, @types/node 26, npm 12, plus the in-range tree - 🔧 config(ts): drop baseUrl from docs/tsconfig.json, removed in TypeScript 7, matching the paths-only form website/tsconfig.json already used - 🗑️ remove(npm): drop the dead js-yaml override, nothing resolves to it - 🔧 config(renovate): stop reporting stable-by-design libraries as abandoned
- 📝 docs(changelog): close the v0.9.2 entry and reopen Unreleased - 📝 docs(roadmap): mark v0.9.2 as the current pre-v1 release - 📝 docs(compare): retire the stale v0.8.1 version claims on the comparison pages
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThe pull request updates release metadata from v0.9.1 to v0.9.2, refreshes pinned CI and release actions, and updates Wolfi image digests. It secures Compose environment-file lookup, validates forwarded client IPs, preserves active rate-limit entries, and sanitizes resize-failure logs. It adds competitive-landscape documentation and comparison data for Arcane and Hawser. It updates website tooling, API examples, installation instructions, verification examples, and roadmap content. Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@COMPETITIVE-LANDSCAPE.md`:
- Line 43: Align the current comparison version scope across
COMPETITIVE-LANDSCAPE.md:43-43 and docs/design/ed25519-auth.md:406-410 by
changing each Portwing matrix label to the prepared v0.9.2 release version, or
consistently marking both matrices as historical. Ensure the current-comparison
heading and table labels use the same scope in both locations.
In `@internal/docker/compose.go`:
- Around line 360-363: Update the error handling around cm.rootedPath in the
compose setup flow to wrap failures with fmt.Errorf, adding clear context while
preserving the original error via %w before returning it.
In `@package.json`:
- Around line 20-25: Regenerate the dependency lockfiles for package.json (lines
20-25), docs/package.json (lines 18-31), and website/package.json (lines 22-34),
ensuring the root lockfile records both workspace lockfile entries; then run npm
ci to validate the combined installation.
In `@website/src/app/compare/page.tsx`:
- Around line 115-116: Update the comparison page content around the
reviewed-date text to identify the specific reviewed product releases and add a
visible link to the versioned comparison evidence record. Keep the existing
documentation-sourcing statement and review date, using the project’s
established evidence URL or reference symbol if available.
In `@website/src/lib/comparison-route-data/portainer.tsx`:
- Line 17: Update the Portainer Agent entry in the comparison route data to
remove the incorrect “~300 MB node image” implementation and size claim.
Preserve the existing “No” value if it represents container-only distribution,
and replace only the inaccurate descriptive text with a factually correct
description consistent with the official Go-based agent images.
In `@website/src/lib/comparison-route-data/watchtower.tsx`:
- Around line 24-26: Update the Watchtower metrics entries in the comparison
data: revise the activity highlight and the existing “Prometheus metrics|No”
table row to indicate that Watchtower provides an opt-in experimental Prometheus
endpoint at /v1/metrics enabled by --http-api-metrics, while preserving the
Portwing metrics description.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 93d1bdba-1e7b-4643-bf0e-9e839c3c3597
⛔ Files ignored due to path filters (3)
CHANGELOG.mdis excluded by!CHANGELOG.mdpackage-lock.jsonis excluded by!**/package-lock.json,!**/package-lock.jsonwebsite/public/llms.txtis excluded by!website/public/**
📒 Files selected for processing (43)
.github/workflows/ci.yml.github/workflows/quality-bench-monthly.yml.github/workflows/quality-fuzz-monthly.yml.github/workflows/quality-fuzz-nightly.yml.github/workflows/quality-integration.yml.github/workflows/quality-mutation-monthly.yml.github/workflows/quality-soak-weekly.yml.github/workflows/release-cut.yml.github/workflows/release.yml.github/workflows/security-grype.yml.github/workflows/security-scorecard.yml.gitignoreCOMPETITIVE-LANDSCAPE.mdDockerfileDockerfile.releaseREADME.mdROADMAP.mddocs/content/docs/competitive-landscape.mdxdocs/content/docs/index.mdxdocs/content/docs/meta.jsondocs/design/ed25519-auth.mddocs/package.jsondocs/tsconfig.jsoninternal/docker/compose.gointernal/docker/compose_helpers_test.gointernal/edge/tunnel.gopackage.jsonrenovate.jsonwebsite/package.jsonwebsite/src/app/compare/page.tsxwebsite/src/app/data/comparison-rows.tswebsite/src/app/data/roadmap.tswebsite/src/app/sitemap.tswebsite/src/components/compare-matrix.tsxwebsite/src/components/compare-section.tsxwebsite/src/lib/comparison-route-data.tsxwebsite/src/lib/comparison-route-data/arcane.tsxwebsite/src/lib/comparison-route-data/diun.tsxwebsite/src/lib/comparison-route-data/hawser.tsxwebsite/src/lib/comparison-route-data/komodo.tsxwebsite/src/lib/comparison-route-data/portainer.tsxwebsite/src/lib/comparison-route-data/watchtower.tsxwebsite/src/lib/comparison-route.tsx
💤 Files with no reviewable changes (2)
- docs/tsconfig.json
- website/src/app/data/comparison-rows.ts
| “Not documented” means the reviewed primary documentation did not establish | ||
| the capability. It is intentionally different from a definitive “no.” | ||
|
|
||
| | Capability | Portwing v0.8.1 | Portainer Agent | Komodo Periphery | Arcane Agent | Hawser | |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Use one Portwing version for current comparison claims.
The PR prepares v0.9.2, while these new current comparison tables identify Portwing as v0.8.1. This makes the reviewed capability scope ambiguous.
COMPETITIVE-LANDSCAPE.md#L43-L43: change the Portwing matrix label to the release version, or mark the matrix as historical.docs/design/ed25519-auth.md#L406-L410: align the current-comparison heading and Portwing table label with the same version scope.
📍 Affects 2 files
COMPETITIVE-LANDSCAPE.md#L43-L43(this comment)docs/design/ed25519-auth.md#L406-L410
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@COMPETITIVE-LANDSCAPE.md` at line 43, Align the current comparison version
scope across COMPETITIVE-LANDSCAPE.md:43-43 and
docs/design/ed25519-auth.md:406-410 by changing each Portwing matrix label to
the prepared v0.9.2 release version, or consistently marking both matrices as
historical. Ensure the current-comparison heading and table labels use the same
scope in both locations.
| rootedEnv, err := cm.rootedPath(stackDir, ".env.drydock") | ||
| if err != nil { | ||
| return "", err | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Wrap the rootedPath error.
Add context before returning this error.
Proposed change
rootedEnv, err := cm.rootedPath(stackDir, ".env.drydock")
if err != nil {
- return "", err
+ return "", fmt.Errorf("resolving env file path: %w", err)
}As per coding guidelines: **/*.go: Wrap errors with fmt.Errorf("context: %w", err) and use log/slog for structured logging only.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| rootedEnv, err := cm.rootedPath(stackDir, ".env.drydock") | |
| if err != nil { | |
| return "", err | |
| } | |
| rootedEnv, err := cm.rootedPath(stackDir, ".env.drydock") | |
| if err != nil { | |
| return "", fmt.Errorf("resolving env file path: %w", err) | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@internal/docker/compose.go` around lines 360 - 363, Update the error handling
around cm.rootedPath in the compose setup flow to wrap failures with fmt.Errorf,
adding clear context while preserving the original error via %w before returning
it.
Source: Coding guidelines
| "postcss": "^8.5.25", | ||
| "sharp": "^0.35.3" | ||
| }, | ||
| "packageManager": "npm@11.13.0", | ||
| "packageManager": "npm@12.0.2", | ||
| "engines": { | ||
| "node": ">=22.0.0" | ||
| "node": "^22.22.2 || ^24.15.0 || >=26.0.0" |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Manifest declarations:"
rg -n '"postcss"|"next"|"typescript"|"`@types/node`"|"`@types/react-dom`"|"packageManager"' \
package.json docs/package.json website/package.json
echo
echo "Committed lockfiles:"
fd -t f 'package-lock.json' . -x sh -c '
echo "== $1 =="
rg -n '"'"'"version": "(16\.3\.0|7\.0\.2|8\.5\.25)"|node_modules/(next|typescript|postcss)' "$1" || true
' sh {}Repository: CodesWhat/portwing
Length of output: 1100
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Lockfile candidates:"
git ls-files '*package-lock.json' || true
for f in $(git ls-files '*package-lock.json'); do
echo
echo "== $f =="
printf 'Lockfile lines: '
wc -l < "$f"
printf 'PostCSS/next/typescript/node package ref lines in lockfile:\n'
rg -n '"(postcss|next|typescript|`@types/node`|`@types/react-dom`|`@tailwindcss/postcss`|tailwindcss)",?|"version": "([0-9]+\.[0-9]+\.[0-9]+)",?|/node_modules/(postcss|next|typescript|`@types/node`|`@types/react-dom`|`@tailwindcss/postcss`|tailwindcss)'\''' "$f" || true
done
echo
echo "Diff summary:"
git diff --stat || true
echo
echo "Root package excerpt:"
sed -n '1,80p' package.jsonRepository: CodesWhat/portwing
Length of output: 16081
Regenerate the root package-lock.json.
npm ci will not install the changed workspaces from this combined lockfile because it only contains the root package metadata and cannot record website/package-lock.json / docs/package-lock.json entries. Add or refresh the workspace lockfiles, then run npm ci.
📍 Affects 3 files
package.json#L20-L25(this comment)docs/package.json#L18-L31website/package.json#L22-L34
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@package.json` around lines 20 - 25, Regenerate the dependency lockfiles for
package.json (lines 20-25), docs/package.json (lines 18-31), and
website/package.json (lines 22-34), ensuring the root lockfile records both
workspace lockfile entries; then run npm ci to validate the combined
installation.
| Current agent capabilities, controller tradeoffs, and deliberate non-goals — sourced | ||
| from published product documentation and reviewed July 28, 2026. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Link the reviewed versions and evidence.
Line 115 states a July 28, 2026 review date. This page does not show the reviewed product versions or link to the evidence record. Add a visible link to the versioned comparison evidence and identify the reviewed releases.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@website/src/app/compare/page.tsx` around lines 115 - 116, Update the
comparison page content around the reviewed-date text to identify the specific
reviewed product releases and add a visible link to the versioned comparison
evidence record. Keep the existing documentation-sourcing statement and review
date, using the project’s established evidence URL or reference symbol if
available.
| Host file APIs and Swarm aggregation|Yes|Intentional non-goals|competitor | ||
| Prometheus agent scrape endpoint|Not documented|Yes|self | ||
| MCP server (read-only)|Not documented|Yes|self | ||
| Single lightweight binary|No (~300 MB node image)|Yes (~10 MB Go binary)|self |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Correct the Portainer Agent deployment data.
Line 17 calls Portainer Agent a ~300 MB node image. The official v2.39.5 Linux AMD64 images are 32.38 MB and 35.95 MB, and the agent source is Go. Keep No if container-only distribution is the distinction, but remove the incorrect implementation and size claim. (hub.docker.com)
Proposed correction
-Single lightweight binary|No (~300 MB node image)|Yes (~10 MB Go binary)|self
+Single lightweight binary|No (containerized Go agent; 32–36 MB Linux AMD64 image)|Yes (~10 MB Go binary)|self📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Single lightweight binary|No (~300 MB node image)|Yes (~10 MB Go binary)|self | |
| Single lightweight binary|No (containerized Go agent; 32–36 MB Linux AMD64 image)|Yes (~10 MB Go binary)|self |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@website/src/lib/comparison-route-data/portainer.tsx` at line 17, Update the
Portainer Agent entry in the comparison route data to remove the incorrect “~300
MB node image” implementation and size claim. Preserve the existing “No” value
if it represents container-only distribution, and replace only the inaccurate
descriptive text with a factually correct description consistent with the
official Go-based agent images.
| packagecheck|Maintained Signed Releases|Watchtower's upstream repository is archived. Portwing remains actively maintained and every release ships per-archive CycloneDX SBOMs, an image SBOM attestation, cosign image signatures, and SLSA build provenance. This verifies Portwing itself; it is not workload image-signature enforcement. | ||
| activity|Prometheus Metrics|Portwing exposes agent health, request counts, and latency histograms. Watchtower has no metrics endpoint. | ||
| bot|MCP Server (AI-Native)|Portwing ships a read-only MCP server so AI tools can inspect containers and events. Watchtower has no MCP support. | ||
| bot|MCP Server (AI-Native)|Portwing ships five read-only MCP tools for container and host inspection. Watchtower has no documented MCP support. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Correct the Watchtower metrics claim.
Line 25 says Watchtower has no metrics endpoint. Upstream documents an opt-in experimental Prometheus endpoint at /v1/metrics behind --http-api-metrics. Update this highlight and the existing Prometheus metrics|No table row. (containrrr.dev)
Proposed correction
-Prometheus metrics|No|Yes|self
+Prometheus metrics|Yes (experimental, opt-in `/v1/metrics`)|Yes|tie
...
-activity|Prometheus Metrics|Portwing exposes agent health, request counts, and latency histograms. Watchtower has no metrics endpoint.
+activity|Prometheus Metrics|Portwing exposes agent health, request counts, and latency histograms. Watchtower exposes an opt-in experimental Prometheus endpoint at `/v1/metrics`.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@website/src/lib/comparison-route-data/watchtower.tsx` around lines 24 - 26,
Update the Watchtower metrics entries in the comparison data: revise the
activity highlight and the existing “Prometheus metrics|No” table row to
indicate that Watchtower provides an opt-in experimental Prometheus endpoint at
/v1/metrics enabled by --http-api-metrics, while preserving the Portwing metrics
description.
clientIP required every X-Forwarded-For hop to parse as an IP address but returned the X-Real-IP fallback verbatim. Behind a configured trusted proxy a caller could send a distinct arbitrary string per request, mint a fresh limiter bucket each time, and walk past the 10-failures-per-minute throttle on the auth path, while writing that string into audit records as the actor. The fallback now applies the same rules as the chain walk: parse as an IP and not itself a trusted proxy, else use the direct peer. - 🧪 test(server): cover non-IP and trusted-proxy X-Real-IP values - 🔧 config(lefthook): add -count=1 to the pre-push race run so a cached pass cannot mask a newly-introduced race
|
Found a third security issue while sweeping for more of the same class, so it's in this PR too.
The fallback now applies the same rules the chain walk already did: parse as an IP, and not itself a trusted proxy, otherwise fall back to the direct peer. Two regression tests cover non-IP values (including a newline-bearing one) and trusted-proxy values. CodeQL didn't flag this one — the logging path was already sanitized, so there was no taint sink for it to find. The bug was in what the value was used for, not where it was printed. Also added |
The release-contract gate caught a half-finished bump: ROADMAP.md had been moved to v0.9.2 while the other surfaces it pins still said v0.9.1. - 📝 docs(version): bump README, COMPATIBILITY, openapi, llms.txt, site-config, get-started, installation, verification, standalone-mode, api-reference, observability, security-model, and the observability example - 🔧 config(contract): pin the contract to 0.9.2 and derive the CHANGELOG date from a variable instead of a hardcoded one - ✨ feat(contract): reject any stale previous-version reference outside the changelog. The enumerated checks only cover surfaces someone remembered to enumerate — this immediately caught a "v0.9.1 is the current release" callout in README and an rpm example beside an already-checked deb example
|
The GoReleaser Config failure was real and worth keeping.
Fixed by doing the bump properly across README, COMPATIBILITY, openapi.yaml, llms.txt, site-config, get-started, installation, verification, standalone-mode, api-reference, observability, security-model, and the observability example. The contract's CHANGELOG date is now derived from a variable instead of a hardcoded I also added a catch-all, because the enumerated checks had holes: they verified the new version is present on twelve named surfaces, but never that the old one is gone. So
Enumerating surfaces only ever finds the surfaces someone remembered to enumerate. |
- 📦 deps(docker): bump the wolfi-base runtime digest to 003627d. The changelog already claimed this pin was current and it wasn't; d2ad9a7 was two rebuilds behind, so the runtime rootfs was missing the newest upstream Wolfi package fixes. - 📦 deps(ci): move the Homebrew cask gate from macos-15 to macos-26. The job only runs post-publish on GA tags and has passed on every release, so the image swap is the whole change.
biggest-littlest
left a comment
There was a problem hiding this comment.
Approving the v0.9.2 cut. Reviewed the two security fixes (X-Real-IP validation before it keys the limiter, os.Root containment on the compose env-file stat), the release-contract hardening, and the dependency refresh.
ALARGECOMPANY
left a comment
There was a problem hiding this comment.
Approving the v0.9.2 cut. Reviewed the two security fixes (X-Real-IP validation before it keys the limiter, os.Root containment on the compose env-file stat), the release-contract hardening, and the dependency refresh.
CI read 95.9% against a 96% floor. main was already sitting exactly on 96.0 with no margin, so the three uncovered error branches statRootedEnvFile added were enough to tip it red. - 🧪 test(docker): cover statRootedEnvFile's two reachable error paths — a stack dir escaping STACKS_DIR (rejected lexically, before any syscall) and a missing stacks dir (caught at os.OpenRoot). The filepath.Abs branch stays uncovered; it only fails if os.Getwd does. - 🔄 refactor(server): split the rate limiter's prune loop out of cleanup into sweepExpired(now). The rules were unreachable in tests only because the ticker period is hardcoded at five minutes. - 🧪 test(server): cover sweepExpired, including the two entries that must survive a sweep — in-flight ones, whose firstFail is not final and whose concurrency count would be lost, and zero-firstFail ones. - 🎨 style(docs): qlty fmt the two competitive-landscape files (MD012). - 📝 docs(ci): correct the coverage-gate comment. It claimed ~1.5% of slack below an achieved 97.5%; actual is 96.3% against a floor of 96, and linux CI reads ~0.1 under a darwin dev box.
4338246
biggest-littlest
left a comment
There was a problem hiding this comment.
Re-approving on 4338246. Adds the coverage the two new statRootedEnvFile error branches were missing, splits the rate limiter's prune loop into sweepExpired so its rules are testable without the five-minute ticker, and clears the markdownlint findings on the competitive-landscape files.
ALARGECOMPANY
left a comment
There was a problem hiding this comment.
Re-approving on 4338246. Adds the coverage the two new statRootedEnvFile error branches were missing, splits the rate limiter's prune loop into sweepExpired so its rules are testable without the five-minute ticker, and clears the markdownlint findings on the competitive-landscape files.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/package-release-config-test.sh`:
- Around line 73-76: Update the git grep invocation in the stale-version check
to scan all tracked files instead of restricting matches to the current
extension allowlist, while retaining only the necessary exclusions for
CHANGELOG.md and scripts/package-release-config-test.sh. Ensure files such as
Dockerfile, package.json, and TOML configuration are included.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: cf6547f9-2fb6-435e-9bd5-8108a23d8ddd
⛔ Files ignored due to path filters (2)
CHANGELOG.mdis excluded by!CHANGELOG.mdwebsite/public/llms.txtis excluded by!website/public/**
📒 Files selected for processing (22)
.github/workflows/ci.yml.github/workflows/release.ymlCOMPATIBILITY.mdCOMPETITIVE-LANDSCAPE.mdDockerfileREADME.mdapi/openapi.yamldocs/content/docs/api-reference.mdxdocs/content/docs/competitive-landscape.mdxdocs/content/docs/installation.mdxdocs/content/docs/observability.mdxdocs/content/docs/security-model.mdxdocs/content/docs/standalone-mode.mdxdocs/content/docs/verification.mdxexamples/observability/docker-compose.ymlinternal/docker/compose_helpers_test.gointernal/server/coverage2_test.gointernal/server/middleware.golefthook.ymlscripts/package-release-config-test.shwebsite/src/components/get-started.tsxwebsite/src/lib/site-config.ts
💤 Files with no reviewable changes (2)
- docs/content/docs/competitive-landscape.mdx
- COMPETITIVE-LANDSCAPE.md
🚧 Files skipped from review as they are similar to previous changes (5)
- Dockerfile
- internal/docker/compose_helpers_test.go
- README.md
- .github/workflows/ci.yml
- .github/workflows/release.yml
| if git grep -n -F -- "$previous_version" -- \ | ||
| '*.md' '*.mdx' '*.ts' '*.tsx' '*.yaml' '*.yml' '*.txt' \ | ||
| ':(exclude)CHANGELOG.md' \ | ||
| ':(exclude)scripts/package-release-config-test.sh'; then |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Scan all tracked release and configuration files.
The extension allowlist skips files such as Dockerfile, package.json, and TOML configuration. A stale 0.9.1 reference in those files passes this release gate. Search all tracked files and retain only the required exclusions.
Expand the stale-version check
if git grep -n -F -- "$previous_version" -- \
- '*.md' '*.mdx' '*.ts' '*.tsx' '*.yaml' '*.yml' '*.txt' \
':(exclude)CHANGELOG.md' \
':(exclude)scripts/package-release-config-test.sh'; then📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if git grep -n -F -- "$previous_version" -- \ | |
| '*.md' '*.mdx' '*.ts' '*.tsx' '*.yaml' '*.yml' '*.txt' \ | |
| ':(exclude)CHANGELOG.md' \ | |
| ':(exclude)scripts/package-release-config-test.sh'; then | |
| if git grep -n -F -- "$previous_version" -- \ | |
| ':(exclude)CHANGELOG.md' \ | |
| ':(exclude)scripts/package-release-config-test.sh'; then |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/package-release-config-test.sh` around lines 73 - 76, Update the git
grep invocation in the stale-version check to scan all tracked files instead of
restricting matches to the current extension allowlist, while retaining only the
necessary exclusions for CHANGELOG.md and
scripts/package-release-config-test.sh. Ensure files such as Dockerfile,
package.json, and TOML configuration are included.
Clears everything that was open on the tracker and cuts v0.9.2.
What was open
What's in here
Competitive landscape — the primary-source audit of Portainer Agent, Komodo Periphery, Arcane, Hawser, Docker-native access, and socket proxies. Corrects stale Komodo auth/edge claims, adds the Arcane comparison route, folds
comparison-rows.tsinto per-competitor route data, and records the pre-v1 review gate plus explicit security non-goals. This work was written against the pre-v0.9.0 tree, so the merge conflicts were resolved claim-by-claim: the audit wins on content, theportwing.codeswhat.comdomain andDrydock v1.6.0-rc.11+version strings from v0.9.x win where they overlap.Both code-scanning alerts closed, and one was a real bug.
buildCommandchecked for a stack's.env.drydockwith a plainos.Stat, which follows symlinks — a symlink planted at that path resolves outsideSTACKS_DIRand gets handed todocker compose --env-file. The stack-file writer already refused to create symlinks, so this needed a symlink planted by other means, but the check now goes throughos.Rootlike the writer does, and non-regular files are ignored. Covered by two new tests. The log-injection alert was the single unsanitizedslogcall intunnel.go— every sibling line already usedapplog.Sanitize.Dashboard cleared, including the majors. Every pinned action moved to current,
actions/checkoutv7 andactions/setup-gov7 included — both are ESM migrations, and checkout v7's fork-ref restriction doesn't apply since no workflow usespull_request_targetorworkflow_run. TypeScript 7 neededbaseUrldropped fromdocs/tsconfig.json(removed in TS 7; the website config was already on the paths-only form). npm 12 neededengines.nodeto state its actual requirement instead of a looser>=22.0.0. Thejs-yamloverride was dead — nothing in the tree resolves to it. The 4 "abandoned" packages are stable by design, not unmaintained, so renovate.json now says so.Branch hygiene — the 4 merged branches are deleted, along with 11 more stale local ones.
Verification
Local gate from RELEASING.md, all green: gofmt,
go vet,go test -race ./...(17 packages), golangci-lint (0 issues), govulncheck (0 reachable),goreleaser check+ snapshot (all archives, deb/rpm, cask, checksums). Website and docs typecheck and build,/compare/arcanerenders. actionlint and zizmor 1.29 clean on the rewritten workflows. Lefthook pre-push gate passed.Changelog
✨ Added
.env.drydockpaths and rate-limiter edge cases.🔧 Changed
-count=1.🐛 Fixed
.env.drydockpaths.execIDand error messages before logging.X-Real-IPbefore rate limiting.X-Real-IPfallback values.🗑️ Removed
ComparisonRowinterface andcomparisonRowsdataset.js-yamlnpm override.🔒 Security
.env.drydocksymlink escapes outsideSTACKS_DIR.X-Real-IPvalues from creating rate-limit buckets.Concerns
comparisonRowsexport.os.Rootsupport on every target platform.