You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Everything on this list lives inside kun — environment variables, workflows, and one code change. None of it depends on Meta, Business Verification, or the ownership work in #141, and none of it depends on Hermes.
Companion issues: #141 (Meta ownership, team access, per-brand email) and #143 (the Hermes relay lane — draft source, pull-vs-push, Slack).
This issue absorbs #138 ("configure the 8 unplugged channels — Telegram first"), which is closed as merged here.
TL;DR
The code is in good shape; the configuration is not. One path works today — compose in /social, publish to Facebook for hogwarts, mkan, databayt. The daily cron has been a no-op since it shipped, and Telegram is switched off for want of two environment variables despite being free, ungated, and ready since 2026-07-10.
Live: 1 of 8 distribution channels, for 3 of 5 brands.
1. Loop B (the daily cron) is dead — three independent blockers
/api/social/cron fires daily at 06:00 UTC and returns drafted: 0. It returns 401 to an unauthenticated request, which confirms it is deployed and CRON_SECRET is set. Nothing is wrong with the code path; three pieces of config are missing and each one alone is fatal.
#
Blocker
Fix
1
SOCIAL_AUTOPOST_PRODUCTS is unset, so the cron opts nobody in and exits
Set it to the brands that should auto-draft
2
SOCIAL_DRAFT_SOURCE defaults to hermes, which Vercel cannot reach
See the Hermes issue — Vercel can never call into Hermes
3
No review destination is configured, so sendReview fails even if a draft existed
Configure the review destination
Three environment variables revive an entire loop. No code.
Set SOCIAL_AUTOPOST_PRODUCTS
Set SOCIAL_DRAFT_SOURCE to a source Vercel can actually reach
Configure the review destination so sendReview succeeds
Boundaries. Do not set SOCIAL_DRAFT_SOURCE=anthropic — that needs a /decide first. Do not rotate CRON_SECRET — it now signs live approval links and authenticates the Hermes queue, so rotating it breaks both.
2. Turn Telegram on — highest value ÷ cost on the whole board
Free, no platform gate, no review, no verification. The bot @nmbdsd_bot already exists and answers getMe. The transport has been wired since 2026-07-10 and is doing nothing.
Create the public brand channel
Add @nmbdsd_bot to it as an admin with Post Messages — admin, not member
Create a separate private review chat
Push TELEGRAM_BOT_TOKEN to Vercel production (it is in the local .env, never pushed)
Set TELEGRAM_CHANNEL_ID — it does not exist anywhere today
Set TELEGRAM_REVIEW_CHAT_ID
Verify: the Hub status shows Telegram green with the resolved @username
Verify: vercel crons run /api/social/cron produces a review message with a working link
The review chat is never the brand channel. Review messages carry one-click publish links — putting them in the public channel hands publishing to the audience.
That doubles the live distribution-channel count in about ten minutes. Setup steps: Telegram guide.
3. Instagram env var for the one brand that is linked
@mkan.sd is claimed and linked to the Mkan Page — the only brand that has cleared gates 1–4. It still needs its id in Vercel:
INSTAGRAM_ACCOUNT_ID_MKAN
Publishing will still fail until Advanced Access lands (#141), but the wiring should not be the thing that is missing when it does. Hogwarts' id is known and goes in the same way once its link succeeds.
There is no separate Instagram token — Instagram authenticates with the linked Page's Facebook token, which also means a crossed Facebook token silently posts to the wrong brand's Instagram. Details: Instagram guide.
4. Metrics — verified on one token, scheduled on none
read_insights and pages_read_user_content were granted 2026-07-27 and verified returning real numbers against a live Hogwarts post. /api/social/metrics writes SocialMetric on a six-hourly schedule, but the workflow ships with its schedule commented out, because the scopes are confirmed on the hogwarts token only.
Dispatch /api/social/metrics once by hand for mkan
Dispatch it once by hand for databayt
If both return numbers, uncomment the schedule
Two things worth keeping written down so they are not rediscovered the hard way:
A permission must be added to the app's Use Case (Dashboard → Use cases → Customize → Permissions and features) before it appears anywhere else in the console. Skip that and the Graph API Explorer answers "Found 0 results", which reads exactly like Meta having withdrawn the permission.
Meta retired the whole post_impressions* family during 2025. A correctly-scoped token still gets (#100) from the old names — that is a metric error, not a permissions one. The live names are post_media_view and post_total_media_view_unique. classifyGraphError exists so this mistake is not repeatable.
/api/social/metrics degrades per product rather than globally, and gives up permanently on a permission failure rather than retrying it forever.
5. Pin the Graph API version deliberately
src/lib/facebook.ts carries GRAPH_VERSION = "v21.0" while the console work has been on v25.0.
Decide: pin, bump, or make it configurable — and write down which
A silent version drift breaks on Meta's schedule rather than ours.
6. The last structural gap — teach the cron to draft per channel
The cron drafts one text and fans it to every channel. That contradicts the one core piece → N platform-native variants multiplier the strategy depends on. The draft skill already owns the correct shape; teaching the cron to use it is a separate change with its own drafting-cost implications.
This is the only item here that is real engineering rather than configuration.
7. Facebook — the two brands that still have no Page
Console work, but channel provisioning rather than ownership, so it lives here rather than in #141.
Sijillee — Page, Business app, permanent Page token
Moallimee — check with @abdout first. It is pre-launch, and the brand page says not to open accounts until positioning is confirmed
Confirm expires_at: 0 via debug_token for every brand token, old and new
A 60-day token looks perfectly healthy today and breaks in two months. expires_at: 0 is the only proof a token is permanent.
8. Promote the channel guides from Researched to Verified
The guides were written from research; some have since been walked through a real console.
Correct each guide against what the console actually shows, and flip its status line
Facebook and Instagram are done. Telegram and LinkedIn are not.
Hard boundaries
⛔ Do not set SOCIAL_DRAFT_SOURCE=anthropic — per-draft API spend against a subscription-only posture. Needs a /decide and @abdout
⛔ Do not wire X/Twitter — pay-per-post since Feb 2026. Same gate
⛔ Do not rotate CRON_SECRET — it invalidates every outstanding approval link and breaks the Hermes relay
⛔ Never a NEXT_PUBLIC_* token
⏸ Stop and report on anything needing @abdout personally: 2FA, legal-entity verification, payment
Already done — do not redo
Egress with per-channel results, three transports in parallel, media carried through the whole chain
Per-product Facebook: its own Page and permanent token per brand, with the resolved Page name shown before publish — which is how a crossed token gets caught
Registry: 5 products × 8 distribution channels, AND-gated so a channel is publishable only when the transport and that brand's destination are both wired
Taxonomy: kind separates what a channel is for from how its bytes move, with a test asserting every channel lands in exactly one delivery lane (drain · hermes · manual)
Approval: signed HMAC links, 12h TTL, single-use, contributor re-checked inside every mutating action
Persistence: SocialPiece / SocialVariant / SocialMetric on Neon (2026-07-26)
Scheduling: /api/social/drain publishes due variants every ~15 minutes from GitHub Actions — Vercel cron granularity is a plan-tier limit and kun already uses its slot, so this also keeps a Pro upgrade off the critical path
UTM tagging at delivery on every outbound link (utm_source / utm_medium / utm_campaign), leaving already-tagged links alone
Analytics destination — no PostHog dependency or key exists, so nothing consumes the UTMs yet. The tags are still worth having; they are recorded in the platform link and readable by anything added later
Order of play
Telegram (channel + review chat + three env vars — free, ungated)
The three cron env vars
INSTAGRAM_ACCOUNT_ID_MKAN
Two manual metrics dispatches, then uncomment the schedule
Everything on this list lives inside kun — environment variables, workflows, and one code change. None of it depends on Meta, Business Verification, or the ownership work in #141, and none of it depends on Hermes.
Companion issues: #141 (Meta ownership, team access, per-brand email) and #143 (the Hermes relay lane — draft source, pull-vs-push, Slack).
This issue absorbs #138 ("configure the 8 unplugged channels — Telegram first"), which is closed as merged here.
TL;DR
The code is in good shape; the configuration is not. One path works today — compose in
/social, publish to Facebook for hogwarts, mkan, databayt. The daily cron has been a no-op since it shipped, and Telegram is switched off for want of two environment variables despite being free, ungated, and ready since 2026-07-10.Live: 1 of 8 distribution channels, for 3 of 5 brands.
1. Loop B (the daily cron) is dead — three independent blockers
/api/social/cronfires daily at 06:00 UTC and returnsdrafted: 0. It returns 401 to an unauthenticated request, which confirms it is deployed andCRON_SECRETis set. Nothing is wrong with the code path; three pieces of config are missing and each one alone is fatal.SOCIAL_AUTOPOST_PRODUCTSis unset, so the cron opts nobody in and exitsSOCIAL_DRAFT_SOURCEdefaults tohermes, which Vercel cannot reachsendReviewfails even if a draft existedThree environment variables revive an entire loop. No code.
SOCIAL_AUTOPOST_PRODUCTSSOCIAL_DRAFT_SOURCEto a source Vercel can actually reachsendReviewsucceedsBoundaries. Do not set
SOCIAL_DRAFT_SOURCE=anthropic— that needs a/decidefirst. Do not rotateCRON_SECRET— it now signs live approval links and authenticates the Hermes queue, so rotating it breaks both.2. Turn Telegram on — highest value ÷ cost on the whole board
Free, no platform gate, no review, no verification. The bot
@nmbdsd_botalready exists and answersgetMe. The transport has been wired since 2026-07-10 and is doing nothing.@nmbdsd_botto it as an admin with Post Messages — admin, not memberTELEGRAM_BOT_TOKENto Vercel production (it is in the local.env, never pushed)TELEGRAM_CHANNEL_ID— it does not exist anywhere todayTELEGRAM_REVIEW_CHAT_ID@usernamevercel crons run /api/social/cronproduces a review message with a working linkThe review chat is never the brand channel. Review messages carry one-click publish links — putting them in the public channel hands publishing to the audience.
That doubles the live distribution-channel count in about ten minutes. Setup steps: Telegram guide.
3. Instagram env var for the one brand that is linked
@mkan.sdis claimed and linked to the Mkan Page — the only brand that has cleared gates 1–4. It still needs its id in Vercel:INSTAGRAM_ACCOUNT_ID_MKANPublishing will still fail until Advanced Access lands (#141), but the wiring should not be the thing that is missing when it does. Hogwarts' id is known and goes in the same way once its link succeeds.
There is no separate Instagram token — Instagram authenticates with the linked Page's Facebook token, which also means a crossed Facebook token silently posts to the wrong brand's Instagram. Details: Instagram guide.
4. Metrics — verified on one token, scheduled on none
read_insightsandpages_read_user_contentwere granted 2026-07-27 and verified returning real numbers against a live Hogwarts post./api/social/metricswritesSocialMetricon a six-hourly schedule, but the workflow ships with its schedule commented out, because the scopes are confirmed on the hogwarts token only./api/social/metricsonce by hand for mkanTwo things worth keeping written down so they are not rediscovered the hard way:
post_impressions*family during 2025. A correctly-scoped token still gets(#100)from the old names — that is a metric error, not a permissions one. The live names arepost_media_viewandpost_total_media_view_unique.classifyGraphErrorexists so this mistake is not repeatable./api/social/metricsdegrades per product rather than globally, and gives up permanently on a permission failure rather than retrying it forever.5. Pin the Graph API version deliberately
src/lib/facebook.tscarriesGRAPH_VERSION = "v21.0"while the console work has been on v25.0.A silent version drift breaks on Meta's schedule rather than ours.
6. The last structural gap — teach the cron to draft per channel
The cron drafts one text and fans it to every channel. That contradicts the one core piece → N platform-native variants multiplier the strategy depends on. The
draftskill already owns the correct shape; teaching the cron to use it is a separate change with its own drafting-cost implications.This is the only item here that is real engineering rather than configuration.
7. Facebook — the two brands that still have no Page
Console work, but channel provisioning rather than ownership, so it lives here rather than in #141.
expires_at: 0viadebug_tokenfor every brand token, old and newA 60-day token looks perfectly healthy today and breaks in two months.
expires_at: 0is the only proof a token is permanent.8. Promote the channel guides from Researched to Verified
The guides were written from research; some have since been walked through a real console.
Facebook and Instagram are done. Telegram and LinkedIn are not.
Hard boundaries
SOCIAL_DRAFT_SOURCE=anthropic— per-draft API spend against a subscription-only posture. Needs a/decideand @abdoutCRON_SECRET— it invalidates every outstanding approval link and breaks the Hermes relayNEXT_PUBLIC_*tokenAlready done — do not redo
kindseparates what a channel is for from how its bytes move, with a test asserting every channel lands in exactly one delivery lane (drain · hermes · manual)SocialPiece/SocialVariant/SocialMetricon Neon (2026-07-26)/api/social/drainpublishes due variants every ~15 minutes from GitHub Actions — Vercel cron granularity is a plan-tier limit and kun already uses its slot, so this also keeps a Pro upgrade off the critical pathutm_source/utm_medium/utm_campaign), leaving already-tagged links aloneOut of scope for this issue
/decideOrder of play
INSTAGRAM_ACCOUNT_ID_MKANGRAPH_VERSIONdecisionDocs
content/docs/social/status.mdxcontent/docs/social/architecture.mdxcontent/docs/social/channels/facebook.mdxcontent/docs/social/channels/instagram.mdxRunbook: the per-channel guides at https://kun.databayt.org/docs/social/channels
Refs #138 (merged here), #140, #141, #143.