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.
| Variable | Purpose |
|---|---|
S3_BUCKET_NAME | Bucket for creator images |
S3_REGION | Region; defaults to auto |
S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY | Credentials |
S3_ENDPOINT | S3-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)
Share links
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