Skip to content

fix(ci,hasura,docs): FIFO and symlink races in ci config, path-selection note, junk hasura files, nself-image Go spec (D-1173, D-1174, D-1175, D-0628, D-0296) - #484

Merged
acamarata merged 7 commits into
mainfrom
dw2-plugins-5
Oct 26, 2026
Merged

acamarata merged 7 commits into
mainfrom
dw2-plugins-5

Conversation

@acamarata

@acamarata acamarata commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Four rows fixed, one fix per concern. Nothing merged, no version bump.

D-1173 readRegular TOCTOU. The file is now opened with O_NONBLOCK|O_NOCTTY (unix; plain open elsewhere) and its type is checked again with fstat on the descriptor. The path check stays as an early exit. Test TestReadRegularFIFOSwappedAfterCheck swaps a regular file for a FIFO between the check and the open (test hook); it blocks and fails with a plain os.Open, passes with the fix.

D-1174 migrate --write parent swap. After checkDestination, Write now creates .nself and ci.yaml through os.OpenRoot(root), so a symlink swapped in afterwards cannot leave the repo. Test TestWriteRefusesSymlinkSwappedAfterCheck swaps .nself for a symlink to an outside dir after the check; with the old MkdirAll/OpenFile-by-path code it wrote outside (verified failing), now it errors and the outside dir stays empty.

D-1175 path-based job selection. Verified legacy internal/legacy/pipeline.go has no path logic. Migrate now adds a Note per manifest below the root saying the jobs get when.paths <dir>/** and the legacy runner ran every stage every time. Test TestMigrateNotesPathSelection. Rendered YAML and goldens are unchanged.

D-0628 newline-named hasura files. Deleted the two junk files (the name was a shell list that got joined into one name; tables.yaml pointed at it). Created per-table files with the same permission template for the tables the migrations actually create (media-processing 5, podcast 5) and fixed both tables.yaml. Not added: four media-processing tables named in the junk name and in plugin.json (trickplay, webhook_events, watcher_events, uploads) have no migration, so hasura metadata for them would fail to apply; and np_podcast_plays (migration 002) was never in the junk name. Both need an owner call. docker-socket.sh now reads find -print0 | sort -zu like port-bind.sh; fixture sock-in-newline-filename added. Run by hand: the old rule passes a socket mount in a newline-named file (fail open), the new one fails it.

D-0296 nself-image SPEC.md. Rewritten for Go: removed the phantom "Plugin Language Policy", the SIMD claim and the libnclaw precedent; Rust/crate/cargo sections replaced (CI matrix is now GOOS/GOARCH); perf figures marked as unmeasured targets; encoder choice (no Go WebP/AVIF encoder in x/image) left as an open item; Rust needs a benchmark plus an ADR 0031 exception. plugin.json and README.md now say Go (language: go), and the rust and simd tags are removed from plugin.json. registry.json is regenerated with scripts/plugin-counts.sh, never hand-edited; scripts/plugin-counts.sh --check --free-only passes.

Checks run

  • cd free/ci && GOFLAGS=-mod=vendor go vet ./... clean; go test ./internal/config/ all pass (new tests included); gofmt -l clean.
  • go test ./... in free/ci: one failure, cmd/agent TestServeStdioExitsNonZeroWithE663OnAProdStackMarker, identical on a clean origin/main worktree (pre-existing).
  • GOOS=windows go build ./internal/config/ fails in internal/exec/process.go:141 (tracker.reap undefined), identical on clean origin/main (pre-existing, not in my files).
  • scripts/conformance/rules/docker-socket.sh run on media-processing, podcast, nself-image: pass. check.sh --fixtures cannot run on this worker (no docker, schemacheck/portbind will not build), so the new fixture was exercised by hand as above.

@acamarata

Copy link
Copy Markdown
Contributor Author

Review fix: the pre-ship checklist in free/nself-image/SPEC.md now says linux/amd64 and linux/arm64 (matching the §14 matrix) instead of the leftover Rust target triples. Check: grep -rn unknown-linux-gnu free/nself-image matched on the base and is now empty. Docs-only change, no code touched.

…the legacy every-run claim in the migrate note (D-0296)
@acamarata

Copy link
Copy Markdown
Contributor Author

Review fixes in a54a3e6:

  1. nself-image: plugin.json, README.md and the registry.json entry now say go, matching SPEC.md. registry.json is marked generated, but tools/catalog is not in this repo, so I made the one-word edit by hand. The next regeneration reads plugin.json and will agree.
  2. Migrate note: confirmed against internal/legacy/pipeline.go. DiscoverAndRunPipeline runs every declared stage of every manifest it finds, with the manifest's directory as the working dir, and has no change filter. Only skip_if_env_missing skips a stage. Added TestLegacyRunnerRanEveryStageEveryRun, which runs the real legacy runner twice over an unchanged tree and checks both stages ran each time in free/other, then checks Migrate still emits the note. With a break injected after the first stage in the legacy loop the test fails; on the real runner it passes. go test -mod=vendor ./... in free/ci passes, as do the free-manifest validator and the registry python test.

@acamarata

Copy link
Copy Markdown
Contributor Author

Review fixes in 2acdece: removed the rust and simd tags from free/nself-image/plugin.json and regenerated registry.json with scripts/plugin-counts.sh (the earlier hand edit of language is now generator output; --check --free-only failed on the stale tags before and passes now). catalog.json and counts.json did not change. PR body corrected: plugin.json, README and registry were changed to Go in a54a3e6.

@acamarata
acamarata merged commit a761c32 into main Oct 26, 2026
38 of 40 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant