* feat(proto): generate unified worldmonitor.openapi.yaml bundle
Adds a third protoc-gen-openapiv3 invocation that merges every service
into a single docs/api/worldmonitor.openapi.yaml spanning all 68 RPCs,
using the new bundle support shipped in sebuf 0.11.0
(SebastienMelki/sebuf#158).
Per-service YAML/JSON files are untouched and continue to back the
Mintlify docs in docs/docs.json. The bundle runs with strategy: all and
bundle_only=true so only the aggregate file is emitted, avoiding
duplicate-output conflicts with the existing per-service generator.
Requires protoc-gen-openapiv3 >= v0.11.0 locally:
go install github.com/SebastienMelki/sebuf/cmd/protoc-gen-openapiv3@v0.11.0
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(proto): bump sebuf to v0.11.0 and document unified OpenAPI bundle
- Makefile: SEBUF_VERSION v0.7.0 → v0.11.0 (required for bundle support).
- proto/buf.gen.yaml: point bundle_server at https://api.worldmonitor.app.
- CONTRIBUTING.md: new "OpenAPI Output" section covering per-service specs
vs the unified worldmonitor.openapi.yaml bundle, plus a note that all
three sebuf plugins must be installed from the pinned version.
- AGENTS.md: clarify that `make generate` also produces the unified spec
and requires sebuf v0.11.0.
- CHANGELOG.md: Unreleased entry announcing the bundle and version bump.
Also regenerates the bundle with the updated server URL.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(codegen): regenerate TS client/server with sebuf v0.11.0
Mechanical output of the bumped protoc-gen-ts-client and
protoc-gen-ts-server. Two behavioral improvements roll in from sebuf:
- Proto enum fields now use the proper `*_UNSPECIFIED` sentinel in
default-value checks instead of the empty string, so generated
query-string serializers correctly omit enum params only when they
actually equal the proto default.
- `repeated string` query params now serialize via
`forEach(v => params.append(...))` instead of being coerced through
`String(req.field)`, matching the existing `parseStringArray()`
contract on the server side.
All files also drop the `// @ts-nocheck` header that earlier sebuf
versions emitted — 0.11.0 output type-checks cleanly under our tsconfig.
No hand edits. Reproduce with `make install-plugins && make generate`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(proto): bump sebuf v0.11.0 → v0.11.1, realign tests with repeated-param wire format
- Bump SEBUF_VERSION to v0.11.1, pulling in the OpenAPI fix for repeated
scalar query params (SebastienMelki/sebuf#161). `repeated string` fields
now emit `type: array` + `items.type: string` + `style: form` +
`explode: true` instead of `type: string`, so SDK generators consuming
the unified bundle produce correct array clients.
- Regenerate all 12 OpenAPI specs (unified bundle + Aviation, Economic,
Infrastructure, Market, Trade per-service). TS client/server codegen
is byte-identical to v0.11.0 — only the OpenAPI emitter was out of sync.
- Update three tests that asserted the pre-v0.11 comma-joined wire format
(`symbols=AAPL,MSFT`) to match the current repeated-param form
(`symbols=AAPL&symbols=MSFT`) produced by `params.append(...)`:
- tests/market-service-symbol-casing.test.mjs (2 cases: getAll)
- tests/stock-analysis-history.test.mts
- tests/stock-backtest.test.mts
Locally: test:data 6619/6619 pass, typecheck clean, lint exit 0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Apply suggestions from code review
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* feat(trade): UN Comtrade strategic commodity flows seeder + RPC (#2045)
* fix(trade): correct byYear overwrite bug and anomaliesOnly upstream flag
Two bugs in the Comtrade flows feature:
1. seed-trade-flows.mjs: byYear Map used year alone as key. With flowCode=X,M
the API returns both export and import records for the same year; the second
record silently overwrote the first, causing incorrect val/wt and YoY
calculations. Fix: key by `${flowCode}:${year}` so exports and imports are
tracked separately and YoY is computed per flow direction.
2. list-comtrade-flows.ts: `if (!flows.length)` set upstreamUnavailable=true
even when Redis data was present but all records were filtered out by
anomaliesOnly=true. Fix: track dataFound separately and only set
upstreamUnavailable when no Redis keys returned data.
* fix(comtrade-flows): gold standard TTL, maxStaleMin, exit code, batch Redis fetch
- health.js: maxStaleMin 1440→2880 (2× daily interval per gold standard)
- seed-trade-flows.mjs: CACHE_TTL 86400→259200 (72h = 3× daily interval)
- seed-trade-flows.mjs: process.exit(1)→0 to match seeder suite convention
- list-comtrade-flows.ts: replace 30 getCachedJson calls with single getCachedJsonBatch pipeline
* feat: effective tariff rate source
* fix(trade): extract parse helpers, fix tests, add health monitoring
- Extract htmlToPlainText/toIsoDate/parseBudgetLabEffectiveTariffHtml
to scripts/_trade-parse-utils.mjs so tests can import directly
- Fix toIsoDate to use month-name lookup instead of fragile
new Date(\`\${text} UTC\`) which is not spec-guaranteed
- Replace new Function() test reconstruction with direct ESM import
- Add test fixtures for parser patterns 2 and 3 (previously untested)
- Add tariffTrendsUs to health.js STANDALONE_KEYS + SEED_META
(key trade:tariffs:v1:840:all:10, maxStaleMin 900 = 2.5x the 6h TTL)
* fix(test): update sourceVersion assertion for budgetlab addition
---------
Co-authored-by: Elie Habib <elie.habib@gmail.com>
* feat(trade): add US Treasury customs revenue to Trade Policy panel
US customs duties revenue spiked 4-5x under Trump tariffs (from
$7B/month to $27-31B/month) but the WTO tariff data only goes to
2024. Adds Treasury MTS data showing monthly customs revenue.
- Add GetCustomsRevenue RPC (proto, handler, cache tier)
- Add Treasury fetch to seed-supply-chain-trade.mjs (free API, no key)
- Add Revenue tab to TradePolicyPanel with FYTD YoY comparison
- Fix WTO gate: per-tab gating so Revenue works without WTO key
- Wire bootstrap hydration, health, seed-health tracking
* test(trade): add customs revenue feature tests
22 structural tests covering:
- Handler: raw key mode, empty-cache behavior, correct Redis key
- Seed: Treasury API URL, classification filter, timeout, row
validation, amount conversion, sort order, seed-meta naming
- Panel: WTO gate fix (per-tab not panel-wide), revenue tab
defaults when WTO key missing, dynamic FYTD comparison
- Client: no WTO feature gate, bootstrap hydration, type exports
* fix(trade): align FYTD comparison by fiscal month count
Prior FY comparison was filtering by calendar month, which compared
5 months of FY2026 (Oct-Feb) against only 2 months of FY2025
(Jan-Feb), inflating the YoY percentage. Now takes the first N
months of the prior FY matching the current FY month count.
* fix(trade): register treasury_revenue DataSourceId and localize revenue tab
- Add treasury_revenue to DataSourceId union type so freshness
tracking actually works (was silently ignored)
- Register in data-freshness.ts source config + gap messages
- Add i18n keys: revenue tab label, empty state, unavailable banner
- Update infoTooltip to include Revenue tab description
* fix(trade): complete revenue tab localization
Use t() for all remaining hardcoded strings: footer source labels,
FYTD summary headline, prior-year comparison, and table column
headers. Wire the fytdLabel/vsPriorFy keys that were added but
not used.
* fix(test): update revenue source assertion for localized string
* feat: convert 52 API endpoints from POST to GET for edge caching
Convert all cacheable sebuf RPC endpoints to HTTP GET with query/path
parameters, enabling CDN edge caching to reduce costs. Flatten nested
request types (TimeRange, PaginationRequest, BoundingBox) into scalar
query params. Add path params for resource lookups (GetFredSeries,
GetHumanitarianSummary, GetCountryStockIndex, GetCountryIntelBrief,
GetAircraftDetails). Rewrite router with hybrid static/dynamic matching
for path param support.
Kept as POST: SummarizeArticle, ClassifyEvent, RecordBaselineSnapshot,
GetAircraftDetailsBatch, RegisterInterest.
Generated with sebuf v0.9.0 (protoc-gen-ts-client, protoc-gen-ts-server).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add rate_limited field to market response protos
The rateLimited field was hand-patched into generated files on main but
never declared in the proto definitions. Regenerating wiped it out,
breaking the build. Now properly defined in both ListEtfFlowsResponse
and ListMarketQuotesResponse protos.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: remove accidentally committed .planning files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>