Spaces:
Running
Running
| # Publishing Operations β Phase 9 | |
| ## Status | |
| Publishing operations are implemented in the current working tree with durable | |
| unified jobs, calendar/queue/draft flows, retries, idempotency, and SDK/MCP/n8n | |
| transport coverage. PostgreSQL/RLS runtime verification, Docker, FFmpeg, | |
| Hugging Face startup, live provider certification, and final production | |
| certification remain deferred until all planned product phases are complete. | |
| ## Audit | |
| The Phase 8 audit found one authoritative publishing domain under | |
| `app/social/`. `SocialPost` is already the canonical draft/post record, a | |
| post owns multiple `SocialPostTarget` rows, `SocialSchedule` stores UTC | |
| timestamps plus the requested IANA timezone, and `SocialJob` is the durable | |
| per-target queue consumed by the existing scheduler and publisher workers. | |
| Provider adapters, OAuth/TokenService, capability discovery, asset ownership, | |
| RLS, retries, cancellation requests, reconciliation, partial success, SDK, | |
| MCP, n8n, Copilot, project provenance, and Content Studio integration are | |
| reused. No duplicate post, account, asset, or job tables were introduced. | |
| Phase 9 adds revision-safe draft mutation and rescheduling, queue/calendar | |
| read models, and durable bounded bulk orchestration. `revision` on posts and | |
| schedules is additive and is checked server-side for updates, duplication, and | |
| rescheduling. `social_publishing_batches` and | |
| `social_publishing_batch_items` are additive, workspace-isolated orchestration | |
| records; individual posts/jobs retain their own state and idempotency. | |
| ## State and APIs | |
| Existing `/v1/social/posts`, `/publish`, `/schedule`, `/cancel`, validation, | |
| jobs, accounts, and provider routes remain canonical. Phase 9 adds: | |
| - `GET /v1/social/drafts` | |
| - `PATCH/DELETE /v1/social/drafts/{post_id}` | |
| - `PATCH /v1/social/posts/{post_id}` | |
| - `POST /v1/social/posts/{post_id}/duplicate` | |
| - `POST /v1/social/posts/{post_id}/reschedule` | |
| - `GET /v1/social/publishing-context` | |
| - `GET /v1/social/calendar` | |
| - `GET /v1/social/queue` | |
| - `POST /v1/social/bulk` | |
| The batch operation is `schedule`, `reschedule`, `cancel`, `duplicate`, or | |
| `delete`. Batch items are claimed with `FOR UPDATE SKIP LOCKED` by the existing | |
| Social scheduler boundary and report independent completion/failure. | |
| Drafts remain `draft` until server validation. `validating` and `ready` are | |
| reserved state vocabulary for future asynchronous validation materialization; | |
| provider execution continues to use the existing `queued` β `preparing` β | |
| `processing` β `uploading` β `publishing` β terminal transitions. No frontend | |
| can arbitrarily mutate execution state. | |
| ## Calendar and timezone model | |
| The calendar accepts an aware UTC range and returns scheduled posts with the | |
| stored schedule timezone and schedule revision. Workspace timezone is read | |
| from authoritative workspace metadata, defaulting to UTC only when no | |
| workspace timezone has been configured. UI date-time inputs are explicitly | |
| labelled with that timezone and converted to an instant before mutation. | |
| Invalid, past, unordered, or excessively broad ranges are rejected. | |
| ## Queue and bulk behavior | |
| Queue filtering supports provider, account, project, status, search, bounded | |
| pagination, and live polling through TanStack Query. Bulk requests are | |
| bounded to 100 posts, idempotent at batch level, and never clone provider job | |
| IDs or provider references. Batch processing runs through the existing worker | |
| loop; partial item failure produces `partial_success` at the batch level. | |
| ## Security, permissions, RLS, and audit | |
| Existing Social scopes are reused: `social:posts:read/write/publish`, | |
| `social:schedules:read/write`, and account scopes. The BFF continues to enforce | |
| same-origin and session permission checks before forwarding authenticated | |
| requests. Migration `0009_publishing_operations.sql` enables and forces RLS | |
| for batch tables, adds workspace checks, foreign keys, indexes, and revision | |
| columns without destructive changes. Audit events use bounded | |
| `publishing.*` names alongside legacy Social event names; credentials, signed | |
| URLs, provider payloads, and binary media are never recorded. | |
| ## Integrations | |
| The Composer, Calendar, Queue, and Drafts routes use the existing Workspace | |
| shell, design system, Social hooks, canonical project assets, and provider | |
| capabilities. TypeScript and Python SDK Social resources expose draft, | |
| duplicate, reschedule, calendar, queue, and bulk methods. MCP exposes narrowly | |
| scoped queue/calendar/reschedule/duplicate/bulk tools through the shared | |
| service. The official n8n Social node exposes deterministic queue/calendar, | |
| duplicate, reschedule, and bulk operations through the SDK credential. | |
| ## Runtime limitations | |
| Local validation is limited by the available Termux environment. PostgreSQL | |
| RLS runtime checks, Docker, FFmpeg, Hugging Face startup, live provider | |
| credentials, provider certification, production OpenAPI verification, and | |
| final production hardening remain intentionally deferred until all MediaRouter | |
| product phases are complete. | |