|

Social integrations and boundaries

S3 image storage, SMTP password reset, RSS and sitemap, share links, external destination records, and the AI completion route in current source.

Social has no payment, shipping, or messaging provider. Its integrations are image storage, password-reset email, public feeds, share links, and a local consent model for external destinations.

Image storage (S3)

Keystone storage my_images is an S3 adapter configured in features/keystone/index.ts.

VariablePurpose
S3_BUCKET_NAMEBucket for creator images
S3_REGIONRegion; defaults to auto
S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEYCredentials
S3_ENDPOINTS3-compatible endpoint (for example Railway buckets or MinIO)

Reads are signed with a 5000-second expiry. s3ForcePathStyle() uses virtual-hosted addressing for storageapi.dev (Railway) endpoints and path-style for everything else. Profile images, item covers, and images inside item bodies are stored as MediaAsset records owned by the site. Markdown stores the stable /media/[id] path, and that route redirects to a fresh presigned URL. Uploads require canUseStudio and an owned site (features/keystone/mutations/creator-media.ts).

Password-reset email (SMTP)

Keystone auth sends password-reset tokens through nodemailer in features/keystone/lib/mail.ts, using SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASSWORD, and SMTP_FROM. The reset link base is SMTP_STORE_LINK or NEXT_PUBLIC_APP_URL. No other email is sent.

Public origin, RSS, and sitemap

publicSiteOrigin() reads NEXT_PUBLIC_APP_URL, or https:// plus RAILWAY_PUBLIC_DOMAIN. It must be an origin with no path, query, or credentials, and HTTPS in production. It is used by:

  • /feeds/[handle] (RSS 2.0 for public collections; renamed handles return a permanent redirect)
  • /sitemap.xml (publicSitemap)
  • /robots.txt (disallows /dashboard, /api, /account)

The item editor offers "Share to X" and "Share to Threads" links that open those networks' public post-intent pages, plus copy link. No credentials are stored and nothing is posted on the creator's behalf.

External destinations

ConnectedAccount records a label for an X, Instagram, or Threads account. Its status starts as unconfigured. A consent request (requestExternal) creates a Publication with status not_configured and one failed PublishJob with zero attempts.

There is no OAuth connection, provider adapter, token storage, worker, or dispatcher. connected, queued, processing, and succeeded exist as status values in the schema but no current code path reaches them for an external destination. Do not treat a destination or publication record as proof that anything was published elsewhere.

To add a real provider you would need a connection flow with credential storage outside GraphQL reads, a worker that claims queued jobs, retry and idempotency handling that respects the existing consent binding and publication fences, and status reporting back to Publication and PublishJob.

AI completion and MCP

/api/completion uses the OpenRouter provider (OPENROUTER_API_KEY, OPENROUTER_MODEL, OPENROUTER_MAX_TOKENS, or browser-supplied local keys) and requires a dashboard session. It connects to /api/mcp-transport/[transport] for tools. That MCP route currently returns 404 with a message that it is disabled until request isolation and tool authorization are rebuilt, so no MCP tools are exposed.

Webhooks

The source registers no inbound or outbound webhooks.

Out of scope

  • Payments, subscriptions, tips, or paid content
  • Comments, likes, follows, direct messages, or a social graph between creators
  • Delivery to any external network
  • Analytics or tracking integrations

On this page