Elie Habib a04c53fe26 fix(build): pin sebuf plugin via PATH in make generate (#3371)
* fix(build): pin sebuf plugin via PATH in `make generate`

Without this, developers who have an older sebuf protoc-gen-openapiv3
binary installed via a package manager (Homebrew ships v0.7.0 at
/opt/homebrew/bin) hit this failure on a fresh `make generate`:

    Failure: file ".../AviationService.openapi.yaml" was generated
    multiple times: once by plugin "protoc-gen-openapiv3" and again
    by plugin "protoc-gen-openapiv3"

Root cause: `buf.gen.yaml` declares three `protoc-gen-openapiv3`
invocations — the default yaml, a `format=json` variant, and a
`bundle_only=true, strategy: all` unified bundle. Sebuf v0.11.x
honors both `format=json` (emits .json extension) and `bundle_only=true`
(skips per-service emission), so the three invocations write distinct
files. Sebuf v0.7.x does NOT honor either option — it silently emits
the same per-service .yaml filenames from all three plugins and buf
rejects the collision.

`Makefile: install-plugins` installs v0.11.1 (SEBUF_VERSION) to
$HOME/go/bin. But the `generate` target doesn't prepend that to PATH,
so `which protoc-gen-openapiv3` resolves to the stale Homebrew binary
for anyone with both installed.

Verified by `go version -m`:
    /opt/homebrew/bin/protoc-gen-openapiv3 — mod sebuf v0.7.0
    /Users/eliehabib/go/bin/protoc-gen-openapiv3 — mod sebuf v0.11.1

Fix: prepend $$HOME/go/bin to PATH in the `generate` recipe. Matches
what .husky/pre-push:151-153 already does before invoking this target,
so CI and local behavior converge. No sebuf upstream bug.

* fix(build): follow GOBIN-then-GOPATH/bin for plugin PATH prefix

Reviewer (Codex) on PR #3371: the previous patch hardcoded
\$HOME/go/bin, which is only the default fallback when GOBIN is unset
AND GOPATH defaults to \$HOME/go. On machines with a custom GOBIN or
a non-default GOPATH, `go install` targets a different directory — so
hardcoding \$HOME/go/bin can force a stale binary from there to win
over the freshly-installed SEBUF_VERSION sitting at the actual install
location.

Fix: resolve the install dir the same way `go install` does:
  GOBIN first, then GOPATH/bin.

Shell expression: `go env GOBIN` returns an empty string (exit 0) when
unset, so `||` alone doesn't cascade. Using explicit `[ -n "$gobin" ]`
instead.

Also dropped the misleading comment that claimed the pre-push hook
used the same rule — it still hardcodes \$HOME/go/bin. Called that out
in a note, but left the hook alone because its PATH prepend is
belt-and-suspenders (only matters for locating `buf` itself; the
Makefile's own recipe-level prepend decides plugin resolution).

Verified on a machine with empty GOBIN:
    resolved → /Users/eliehabib/go/bin
And \`make generate\` succeeds without manual PATH overrides.

* fix(build): use first GOPATH entry for plugin PATH prefix

Reviewer (Codex) on commit 6db0b53c2: the GOBIN-empty fallback used
`$(go env GOPATH)/bin`, which silently breaks on setups where GOPATH
is a colon-separated list. Example:

    GOPATH=/p1:/p2
    previous code → "/p1:/p2/bin"
       ^ two PATH entries; neither is the actual install target /p1/bin

`go install` writes binaries only into the first GOPATH entry's bin,
so the stale-plugin case this PR is trying to fix can still bite.

Fix: extract the first entry via `cut -d: -f1`. Matches Go's own
behavior in cmd/go/internal/modload/init.go:gobin(), which uses
filepath.SplitList + [0].

Verified:
- Single-entry GOPATH (this machine) → /Users/eliehabib/go/bin ✓
- Simulated GOPATH=/fake/path1:/fake/path2 → /fake/path1/bin ✓
- make generate succeeds in both cases.

* fix(build): resolve buf via caller PATH; prepend plugin dir only (review P1/P3)

Codex P1: the previous recipe prepended the Go install dir to PATH
before invoking `buf generate`, which also changed which `buf` binary
ran. On a machine with a stale buf in GOBIN/$HOME/go/bin, the recipe
would silently downgrade buf itself and reintroduce version-skew
failures — the exact class of bug this PR was trying to fix.

Fix: two-stage resolution.

  1. `BUF_BIN=$(command -v buf)` resolves buf using the CALLER's PATH
     (Homebrew, Go install, distro package — whichever the developer
     actually runs day-to-day).
  2. Invoke the resolved buf via absolute path ("$BUF_BIN"), with a
     PATH whose first entry is the Go install dir. That affects ONLY
     plugin lookup inside `buf generate` (protoc-gen-ts-*,
     protoc-gen-openapiv3) — not buf itself, which was already resolved.

Adds a loud failure when `buf` is not on PATH:
    buf not found on PATH — run: make install-buf
Previously a missing buf would cascade into a confusing error deeper
in the pipeline.

Codex P3: added tests/makefile-generate-plugin-path.test.mjs — scrapes
the generate recipe text and asserts:
  - `command -v buf` captures buf before the PATH override
  - Missing-buf case fails loudly
  - buf is invoked via "$BUF_BIN" (absolute path)
  - GOBIN + GOPATH/bin resolution is present
  - Install-dir prepend precedes $$PATH (order matters)
  - The subshell expression resolves on the current machine

Codex P2 (Windows GOPATH semicolon delimiter) is acknowledged but
not fixed here — this repo does not support Windows dev per CLAUDE.md,
the pre-push hook and CI are Unix-only, and a cross-platform
implementation would require a separate Make detection or a
platform-selected helper script. Documented inline as a known
Unix assumption.

Verified:
- `make generate` clean
- `command -v buf` → /opt/homebrew/bin/buf
- protoc-gen-openapiv3 via plugin-PATH → ~/go/bin/protoc-gen-openapiv3
- New test suite 6/6 pass
- npm run typecheck clean

* fix(build): silence recipe comments with @# (review P2)

Codex P2: recipe lines starting with `#` are passed to the shell
(which ignores them) but Make still echoes them to stdout before
execution. Running `make generate` printed all 34 comment lines
verbatim. Noise for developers, and dilutes the signal when the
actual error output matters.

Fix: prefix every in-recipe `#` comment with `@` so Make suppresses
the echo. No semantic change — all comments still read identically
in the source.

Verified: `make generate` now prints only "Clean complete!", the
buf invocation line (silenced with @... would hide the invocation
which helps debugging, so leaving that audible), and "Code
generation complete!".

* fix(build): fail closed when go missing; verify plugin is present (review High)

Codex High: previous recipe computed PLUGIN_DIR from `go env GOBIN` /
`go env GOPATH` without checking that `go` itself was on PATH. When
go is missing:
  - `go env GOBIN`  fails silently, gobin=""
  - `go env GOPATH` fails silently, cut returns ""
  - printf '%s/bin' "" yields "/bin"
  - PATH becomes "/bin:$PATH" — doesn't override anything
  - `buf generate` falls back to whatever stale sebuf plugin is on
    PATH, reintroducing the exact duplicate-output failure this PR
    was supposed to fix.

Fix (chained in a single shell line so any guard failure aborts):
  1. `command -v go`  — fail with clear "install Go" message.
  2. `command -v buf` — fail with clear "run: make install-buf".
  3. Resolve PLUGIN_DIR via GOBIN / GOPATH[0]/bin.
  4. `[ -n "$$PLUGIN_DIR" ]` — fail if resolution returned empty
     (shouldn't happen after the go-guard, but belt-and-suspenders
     against future shell weirdness).
  5. `[ -x "$$PLUGIN_DIR/protoc-gen-ts-client" ]` — fail if the
     plugin isn't installed, telling the user to run
     `make install-plugins`. Catches the case where `go` exists but
     the user has never installed sebuf locally.
  6. `PATH="$$PLUGIN_DIR:$$PATH" "$$BUF_BIN" generate`.

Verified failure modes:
  - go missing        → "go not found on PATH — run: ... install-plugins"
  - buf missing       → "buf not found on PATH — run: make install-buf"
  - happy path        → clean `Code generation complete!`

Extended tests/makefile-generate-plugin-path.test.mjs with:
  - `fails loudly when go is not on PATH`
  - `verifies the sebuf plugin binary is actually present before invoking buf`
  - Rewrote `PATH override order` to target the new PLUGIN_DIR form.

All 8 tests pass. Typecheck clean.

* fix(makefile): guard all sebuf plugin binaries, not just ts-client

proto/buf.gen.yaml invokes THREE sebuf binaries:

- protoc-gen-ts-client
- protoc-gen-ts-server
- protoc-gen-openapiv3 (× 3 plugin entries)

The previous guard only verified protoc-gen-ts-client was present in
the pinned Go install dir. If the other two were missing from that
dir (or only partially installed by a prior failed `make install-plugins`),
`PATH="$PLUGIN_DIR:$PATH" buf generate` would fall through to whatever
stale copy happened to be earlier on the caller's normal PATH —
exactly the mixed-sebuf-version failure this PR is meant to eliminate.

Fix: iterate every plugin name in a shell `for` loop. Any missing
binary aborts with the same `Run: make install-plugins` remediation
the previous guard showed.

Tests:
- Update the existing plugin-presence assertion to require all three
  binaries by name AND the `[ -x "$PLUGIN_DIR/$p" ]` loop pattern.
- Add a cross-reference test that parses proto/buf.gen.yaml, extracts
  every `local:` plugin, and fails if any declared plugin is missing
  from the Makefile guard list. This catches future drift without
  relying on a human to remember the dependency.

Closes the PR #3371 High finding that a `ts-server` or `openapiv3`
missing from $PLUGIN_DIR would silently re-enable the stale-plugin bug.

* fix(pre-push): don't shadow caller's buf with stale ~/go/bin/buf

The proto-freshness hook's unconditional
`export PATH="$HOME/go/bin:$PATH"` defeated the Makefile-side
caller-PATH-first invariant: on machines with both a preferred buf
(Homebrew, /usr/local, etc.) AND an older `go install buf@<old>`
leftover at `~/go/bin/buf`, the prepend placed the stale copy first.
`make generate` then resolved buf via `command -v buf` and picked up
the shadowed stale binary — recreating the mixed-version failure
this PR is meant to eliminate.

Fix:

1. Only prepend `$HOME/go/bin` when buf is NOT already on the caller's
   PATH. Now buf's Homebrew/system copy always wins; `~/go/bin/buf` is
   a pure fallback.

2. Widen the plugin-presence check to accept either a PATH-resolvable
   `protoc-gen-ts-client` OR the default go-install location
   `$HOME/go/bin/protoc-gen-ts-client`. `make generate` now resolves
   plugins via its own PLUGIN_DIR (GOBIN, then first-entry GOPATH/bin),
   so requiring them on PATH is too strict.

3. Drop the redundant plugin-only PATH prepend — the Makefile's own
   plugin-path resolution handles it authoritatively.

Tests: add a regression guard that reads the hook, verifies the
prepend is gated on `! command -v buf`, and explicitly asserts the
OLD buggy pattern is not present.

Closes the PR #3371 High finding about the hook's unconditional
prepend defeating the Makefile-side caller-PATH-first invariant.
2026-04-24 19:01:47 +04:00

World Monitor

Real-time global intelligence dashboard — AI-powered news aggregation, geopolitical monitoring, and infrastructure tracking in a unified situational awareness interface.

GitHub stars GitHub forks Discord License: AGPL v3 TypeScript Last commit Latest release

Web App  Tech Variant  Finance Variant  Commodity Variant  Happy Variant

Download Windows  Download macOS ARM  Download macOS Intel  Download Linux

Documentation  ·  Releases  ·  Contributing

World Monitor Dashboard


What It Does

  • 500+ curated news feeds across 15 categories, AI-synthesized into briefs
  • Dual map engine — 3D globe (globe.gl) and WebGL flat map (deck.gl) with 45 data layers
  • Cross-stream correlation — military, economic, disaster, and escalation signal convergence
  • Country Intelligence Index — composite risk scoring across 12 signal categories
  • Finance radar — 92 stock exchanges, commodities, crypto, and 7-signal market composite
  • Local AI — run everything with Ollama, no API keys required
  • 5 site variants from a single codebase (world, tech, finance, commodity, happy)
  • Native desktop app (Tauri 2) for macOS, Windows, and Linux
  • 21 languages with native-language feeds and RTL support

For the full feature list, architecture, data sources, and algorithms, see the documentation.


Quick Start

git clone https://github.com/koala73/worldmonitor.git
cd worldmonitor
npm install
npm run dev

Open localhost:5173. No environment variables required for basic operation.

For variant-specific development:

npm run dev:tech       # tech.worldmonitor.app
npm run dev:finance    # finance.worldmonitor.app
npm run dev:commodity  # commodity.worldmonitor.app
npm run dev:happy      # happy.worldmonitor.app

See the self-hosting guide for deployment options (Vercel, Docker, static).


Tech Stack

Category Technologies
Frontend Vanilla TypeScript, Vite, globe.gl + Three.js, deck.gl + MapLibre GL
Desktop Tauri 2 (Rust) with Node.js sidecar
AI/ML Ollama / Groq / OpenRouter, Transformers.js (browser-side)
API Contracts Protocol Buffers (92 protos, 22 services), sebuf HTTP annotations
Deployment Vercel Edge Functions (60+), Railway relay, Tauri, PWA
Caching Redis (Upstash), 3-tier cache, CDN, service worker

Full stack details in the architecture docs.


Flight Data

Flight data provided gracefully by Wingbits, the most advanced ADS-B flight data solution.


Data Sources

WorldMonitor aggregates 65+ external data sources across geopolitics, finance, energy, climate, aviation, cyber, military, infrastructure, and news intelligence. See the full data sources catalog for providers, feed tiers, and collection methods.


Contributing

Contributions welcome! See CONTRIBUTING.md for guidelines.

npm run typecheck        # Type checking
npm run build:full       # Production build

License

AGPL-3.0 for non-commercial use. Commercial license required for any commercial use.

Use Case Allowed?
Personal / research / educational Yes
Self-hosted (non-commercial) Yes, with attribution
Fork and modify (non-commercial) Yes, share source under AGPL-3.0
Commercial use / SaaS / rebranding Requires commercial license

See LICENSE for full terms. For commercial licensing, contact the maintainer.

Copyright (C) 2024-2026 Elie Habib. All rights reserved.


Author

Elie HabibGitHub

Contributors

Security Acknowledgments

We thank the following researchers for responsibly disclosing security issues:

  • Cody Richard — Disclosed three security findings covering IPC command exposure, renderer-to-sidecar trust boundary analysis, and fetch patch credential injection architecture (2026)

See our Security Policy for responsible disclosure guidelines.


worldmonitor.app  ·  docs.worldmonitor.app  ·  finance.worldmonitor.app  ·  commodity.worldmonitor.app

Star History

Star History Chart
Description
Mirrored from GitHub
Readme AGPL-3.0 382 MiB
Languages
TypeScript 49.1%
JavaScript 47%
CSS 2.9%
HTML 0.4%
Rust 0.3%
Other 0.1%