File size: 4,991 Bytes
1b2323a
 
8bf0d31
 
 
 
 
 
 
 
1b2323a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# 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.