Skip to content

feat(social-ops): credential-free capability layer for 12 platforms - #32

Merged
oratis merged 1 commit into
mainfrom
feat/social-ops-capability-layer
Sep 8, 2026
Merged

oratis merged 1 commit into
mainfrom
feat/social-ops-capability-layer

Conversation

@oratis

@oratis oratis commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Why

Cuddler (private) and InfluenceX (public) are co-building social operations agent capabilities, with a hard split the owner set: Cuddler holds the connection secrets and executes; InfluenceX holds the capability.

The publish code we had lived inside server/publish/oauth.js next to env reads and DB rows, so a host that must never hand its tokens to another process could not reuse any of it.

What

packages/social-ops (@influencex/social-ops, zero dependencies, CJS) — the capability layer:

Module Contents
capabilities.js 12-platform matrix: X · Instagram · Discord · Reddit · YouTube · TikTok · 小红书 · 微信视频号 · 微信公众号 · B站 · 抖音 · 快手. Each carries publishMode (api_direct / api_draft / manual_package), auth kind, text + media limits, metric readability, daily caps, requiresPlatformAudit, endpointsVerified
connectors/ One contract per platform: validate / publish / fetchMetrics. Credentials are always arguments; platform refusals are returned as {success:false, error, retryable, kind}, never thrown
oauth.js Pure authorize-URL / code-exchange / refresh helpers for 8 providers. The consent page is always opened by the account holder
adapt.js Deterministic per-platform shaping: limits, X threads with nothing lost, hashtag caps, paste packages, 公众号 inline HTML
pipeline/ brief → plan → copy (per locale) → visual → adapt → vocabulary gate, with the LLM and image generator injected
edm/ Compliance floor (CAN-SPAM / GDPR / Gmail-Yahoo 2024), consent-only audience filter, suppression list, warm-up caps, complaint circuit breaker, resumable campaign runner with an injected send
community/ 7:1 contribution ledger, subreddit-rule assessment, disclosure templates, Discord slowmode
matrix/policy.js Owned-account matrix validation and stagger planner
refusals.js What this layer will not do, why, and the substitute it provides — exposed through manifest()

Invariants, each with a test:

  • The package never reads process.env — social-ops-capabilities.test.js walks every source file
  • It never drives a browser or a login form
  • Every connector satisfies the contract and maps 1:1 to the matrix

Server integration: server/publish/oauth.js now delegates X / Instagram / YouTube / TikTok / Reddit publishing to the package (legacy {success, platform_post_id, url} shape preserved, so publisher agent, scheduled-publish and /api/publish/direct/:platform are untouched). One implementation instead of two.

Dockerfile gains COPY packages/ packages/ before COPY server/ — without it the image fails the first publish with MODULE_NOT_FOUND, and local npm test would not catch that.

Deliberate boundaries

Four capabilities were requested that this layer refuses, each with a working substitute:

Refused Why Instead
Mass bot-account creation for posting / commenting / DMs Coordinated inauthentic behaviour: banned on all 12 targets, ban cascades reach the official accounts, illegal under FTC 16 CFR Part 465 and 网信办《网络信息内容生态治理规定》第二十四条 matrix/policy — a matrix of owned, disclosed accounts (brand / regional / topic / employee / creator partner), each authorised by its human holder
Bulk consumer-mailbox registration for EDM Provider ToS abuse; consumer domains cannot carry your SPF/DKIM/DMARC; burns the reputation of everything else you send edm/ on an owned domain through an ESP, consent-only lists
Cold DM automation Spam under every platform policy; the receiving side is the strongest prompt-injection surface an agent can face Community agent pulls inbound messages, drafts replies, a human sends
Headless-browser login for platforms with no API Needs plaintext credentials on a server, defeats 2FA, no audit trail manual_package mode — a limit-checked paste package for the operator

Tests

npm test — 733 passing, of which 54 are new across six files:

  • social-ops-capabilities — matrix invariants, mode membership, unverified-endpoint flags, connector contract, manifest serialisability, the no-process.env sweep
  • social-ops-adapt — X thread splitting loses nothing, 小红书 20-char title / 18 images, 公众号 64/120 caps + HTML escaping, YouTube video-only, IG 30-hashtag cap, B站 cover, Discord 2000
  • social-ops-connectors — all 12 fail fast on missing credentials with no network; per-platform request shaping against a scripted fetch; 429/403 classification; IG Reels container polling; YouTube scheduled upload forced private; TikTok SELF_ONLY draft; Reddit RATELIMIT retryable; 公众号 40164 IP-allowlist hint; B站 HMAC signature headers; OAuth URLs and code exchange
  • social-ops-pipeline — full chain, vocabulary gate blocking + one rewrite + residue reported (never silently dropped), image generation fill-in
  • social-ops-edm — compliance positives and negatives, unsubscribe headers, suppression event mapping, 11 audience exclusion reasons, warm-up + breaker, the send loop's rate limit / suppression / daily cap / budget / cursor
  • social-ops-community-matrix — 7:1 ledger + cooldown, rule assessment, idempotent disclosure, refusal before posting, bot-farm account shapes rejected, stagger planning

Known limits

bilibili / douyin / kuaishou connectors are implemented from published 开放平台 docs with request-shaping tests, but have not been exercised against a live approved application — the matrix marks them endpointsVerified: false. Verify with a test account before issuing credentials.

🤖 Generated with Claude Code

WHY: Cuddler (private) and InfluenceX (public) are co-building social
operations agent capabilities with a hard split: Cuddler holds the
connection secrets and executes, InfluenceX holds the capability. The
existing publish code lived inside server/publish/oauth.js next to env
reads and DB rows, so nothing could be reused by a host that must never
hand its tokens to another process.

WHAT:
- packages/social-ops (@influencex/social-ops, zero deps): 12-platform
  capability matrix (X, Instagram, Discord, Reddit, YouTube, TikTok,
  小红书, 微信视频号, 微信公众号, B站, 抖音, 快手) with publishMode
  api_direct / api_draft / manual_package, audit + endpointsVerified flags
- connectors with one contract (validate / publish / fetchMetrics);
  credentials are always arguments, refusals are results not throws
- pure OAuth helpers (authorize URL, code exchange, refresh) for 8 providers
- adapt.js (limits, X threads without loss, paste packages, 公众号 HTML)
- pipeline: brief → plan → copy → visual → adapt → vocabulary gate (LLM injected)
- edm: compliance floor, consent-only audience, suppression, warm-up caps,
  complaint breaker, resumable campaign runner (send injected)
- community: 7:1 contribution ledger, subreddit rule assessment,
  disclosure, Discord slowmode; matrix/policy rejects bot-farm shapes
- refusals.js exposed through manifest(): bot account farms, mass mailbox
  registration, cold DM automation, headless login, engagement automation
- server/publish/oauth.js delegates X/IG/YouTube/TikTok/Reddit to the
  package (legacy result shape preserved); Dockerfile copies packages/
- 54 tests in server/__tests__/social-ops-*.test.js; docs + memory + changelog

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@oratis
oratis merged commit 691f489 into main Sep 8, 2026
5 checks passed
@oratis
oratis deleted the feat/social-ops-capability-layer branch September 8, 2026 15:22
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