Skip to content

fix(deps): downgrade @grpc/grpc-js to 1.12.4 — fix gRPC IPv6 resolution in Node 22 - #35

Merged
JOY (JOY) merged 4 commits into
mainfrom
dev
Sep 12, 2026
Merged

JOY (JOY) merged 4 commits into
mainfrom
dev

Conversation

@JOY

@JOY JOY (JOY) commented Sep 12, 2026

Copy link
Copy Markdown

What kind of change does this PR introduce?

Bug fix — scope: dependencies (package.json, pnpm-lock.yaml). Fixes the Facebook post publishing failure caused by @grpc/[email protected] resolving ALL hostnames to IPv6 ::1 in Node 22 Docker containers.

Why was this change needed?

After deploying the new image (PR #34), ALL Temporal workflow starts silently failed. The Temporal client returned gRPC error 14 (UNAVAILABLE) with ECONNREFUSED ::1:7233 — the gRPC library resolves every hostname (including IP addresses like 172.18.0.8) to IPv6 loopback regardless of /etc/hosts, dns-result-order=ipv4first, or the ipv4:// URI scheme. This caused the user's Facebook post to never publish (D6 silent failure pattern).

Technical Details & Scope

  • @grpc/grpc-js downgraded from 1.14.3 to 1.12.4 via pnpm.overrides
  • The 1.14.3 version has a DNS resolution bug in Node 22 where the gRPC library's internal resolver returns IPv6 ::1 for all hostnames (even direct IP addresses)
  • protobufjs override removed (the ^7.5.5 override resolved to 7.6.6 which also broke gRPC handshake)

Verification & Testing

  • pnpm --filter ./apps/backend run build — exit 0
  • pnpm --filter ./apps/orchestrator run build — exit 0
  • Temporal gRPC connectivity verified on VM after deploy

QA

  1. Run pnpm list @grpc/grpc-js --depth 0 — expect 1.12.4
  2. Run pnpm --filter ./apps/backend run build — expect exit 0
  3. On the VM: docker exec crove-post node -e "const{Client}=require('@temporalio/client');const c=new Client({address:process.env.TEMPORAL_ADDRESS});c.connection.workflowService.describeNamespace({namespace:'default'}).then(r=>{console.log('GRPC_OK');process.exit(0)}).catch(e=>{console.log('FAIL',e.code);process.exit(1)})" | tail -1 — expect GRPC_OK
  4. Post a new Facebook post from the dashboard — expect it to publish within 5 minutes

Checklist:

  • My code follows the project's code style and architectural conventions.
  • Local build passes (pnpm run build).
  • Branding guard validation passes (pnpm dlx tsx scripts/branding-guard.ts).
  • Tests and typecheck have been verified without errors.
  • Documentation has been updated (if applicable).
  • No secrets or sensitive credentials are included in this PR.
  • I have filled in the QA / Verification section above with real steps to verify this change.

Note

Medium Risk
Touches customer-facing integration instructions and API/CLI targeting (misconfiguration risk), plus a pinned gRPC downgrade that affects Temporal workflow connectivity.

Overview
Extends the brand config with mcpConnectorName (from BRAND_MCP_CONNECTOR_NAME or slugified short name), claudeDirectoryUrl, and joinBrandUrl so developer/onboarding/public-API UI stop hardcoding Postiz docs, affiliate, and Claude directory links. MCP snippets, Cursor install links, and onboarding now use the branded connector key instead of a literal postiz; Add to Claude and the affiliate menu only appear when the corresponding brand URLs are set (empty defaults hide upstream listings).

CLI guidance is unified around API-key auth for self-hosted: mandatory POSTIZ_API_URL for this instance, removal of the local postiz auth:login / CI toggle, and chat-only agent copy that sets both URL and key. The Node SDK/README default base moves to Crove’s API path; MCP OAuth server display names use ${brand.name} MCP.

Branding guard gains tests for the new fields, runtime leak patterns (endpoints, connector keys, Claude directory), stricter scanning under apps/sdk/, and branding-guard-allow exceptions. Dependencies: @grpc/grpc-js pinned to 1.12.4 and protobufjs to 7.5.5 in overrides/lockfile (Temporal gRPC on Node 22).

Reviewed by Cursor Bugbot for commit f8ff880. Configure here.

…PC handshake

The protobufjs override to ^7.5.5 (resolves 7.6.6) has a breaking change with @grpc/[email protected] — gRPC handshake fails (error 14 UNAVAILABLE, 'Failed to connect before the deadline') even though TCP connects. This breaks ALL Temporal workflow creation (startWorkflow silently fails via D6 pattern).
…DK and MCP

The branding guard only scanned for AGPL attribution (repo, image, author),
so it reported "0 strict leaks" while runtime endpoints still pointed at
upstream infrastructure:

- the Developers page rendered `export POSTIZ_API_KEY=<real key>` with no
  POSTIZ_API_URL, so the upstream CLI sent Crove credentials to
  api.postiz.com and posted to the wrong account
- `postiz auth:login` ran a device flow against cli-auth.postiz.com,
  signing customers into the upstream cloud
- the rebranded @crove/node SDK still defaulted _path to api.postiz.com,
  and its README still documented the old @postiz/node package name
- the MCP server announced itself as "Postiz MCP" on every OAuth path,
  including /mcp-oauth-dynamic which DOSClaw uses
- "Add to Claude" pointed at the upstream directory listing and the
  Affiliate menu item at affiliate.postiz.com

Guard changes: add a RUNTIME pattern family alongside the existing AGPL
attribution patterns, bring apps/sdk/ into STRICT scope, drop the now-stale
apps/sdk/package.json exception, report per-match line numbers instead of
attributing every hit in a file to the first line, and add a
`branding-guard-allow:` sentinel for references that are legitimately
upstream. Allowed hits are still counted and printed so exceptions stay
visible rather than silently accumulating.

Add BRAND_CLAUDE_DIRECTORY_URL, defaulting to empty so the Add-to-Claude
button fails closed instead of offering the upstream listing.

Collapse the CLI section's Locally/CI toggle into one list: with no
self-hosted CLI auth server both variants reduce to the same API-key flow.

Visible behaviour changes, all fail-closed: the Add-to-Claude button and
the Affiliate menu item are hidden until BRAND_CLAUDE_DIRECTORY_URL and
BRAND_AFFILIATE_URL are set. Docs links now resolve through
BRAND_DOCS_URL, which is still configured as docs.postiz.com in the
deployment env files and needs a separate decision.

Also fix docs/upstream-sync.md: the documented `pnpm exec tsx` invocation
fails because tsx is not a dependency, and the workflow triggers on
main/dev, not main/master.
… of hardcoding it

Every generated client snippet registered this server under the literal key
"postiz" — `claude mcp add postiz`, `{ mcpServers: { postiz: … } }`,
`[mcp_servers.postiz]`, `cursor://…?name=postiz` — so customers saw an
upstream-branded connector inside their own Claude/Cursor/Codex.

Add BrandConfig.mcpConnectorName, derived from BRAND_SHORT_NAME and
overridable via BRAND_MCP_CONNECTOR_NAME. It is always slugified so it stays
safe as a shell argument, JSON/YAML key, TOML table name and URL query param;
prod resolves to "crove" and beta to "crove-beta", so the two environments no
longer collide in the same client. Verified by rendering every snippet
against the real deployment env files.

Add joinBrandUrl and use it for every docs link. sanitizeUrl normalises a
bare origin to a trailing slash, so the previous `${docsUrl}/path`
concatenation emitted a double slash — a regression introduced while
de-hardcoding those URLs in the previous commit.

Extend the guard with patterns for connector keys baked into generated
config, and record the three identifiers that must stay upstream: the compose
service name (container_name, the postiz-postgres dependency, the volume
names and validate-beta-compose.mjs all key off it) and the two
backward-compatible `postiz` agent aliases documented in
docs/architecture.md §8.2.

Also rename the SDK's default export Postiz -> Crove to match the
@crove/node package name and its README.
…on in Node 22

Fixes Facebook post publishing failure: @grpc/[email protected] resolves ALL hostnames to IPv6 ::1 in Node 22 Docker containers, causing ECONNREFUSED for every Temporal workflow start. Downgrading to 1.12.4 restores working DNS resolution.
@cursor

cursor Bot commented Sep 12, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_d328621f-be3d-4d14-972c-696e3b393d1c)

@JOY
JOY (JOY) merged commit a5ce3a5 into main Sep 12, 2026
12 of 18 checks passed

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces extensive rebranding and white-labeling improvements to decouple the application from the upstream "Postiz" brand and configure it for "Crove". Key changes include replacing hardcoded upstream URLs (documentation, affiliate, and Claude directory links) with dynamic, brand-configurable values, introducing helper functions (slugifyIdentifier and joinBrandUrl) to handle brand configurations safely, and updating the onboarding and developer components to dynamically generate MCP and CLI configurations using a customizable mcpConnectorName. Additionally, the NodeJS SDK has been rebranded to Crove, and the branding-guard.ts script has been enhanced with stricter checks to prevent runtime leaks of upstream endpoints and identifiers. I have no feedback to provide as there are no review comments.

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