Core System Architecture Part 88 — Anonymous Network Content Publishing, Posts, Articles, Media, Drafts, Revisions, Distribution & Creator-State Architecture
SIAR — Secure, Local-First, Multi-Transport Communication Platform
Series: Core System Architecture
Part: 88
Status: Architecture specification
Primary language: Rust
Builds on: Core System Architecture Parts 32, 40, 43, 56, 58–59, 67–69, 74–87
Primary purpose: define SIAR's complete content-publishing architecture for posts, articles, media, drafts, revisions, scheduled publication, retraction, creator pseudonyms, local/offline authoring, multi-device synchronization, content signing, provenance, feed/channel/federation distribution, media processing, moderation, retention, analytics boundaries, and creator-state lifecycle.
1. Purpose
Publishing content appears simple:
write
→ publish
In a real privacy-preserving distributed system, publishing includes:
drafts
autosave
multi-device sync
media
revision history
scheduled publication
visibility changes
retraction
federation
moderation
signing
deletion
The governing principle is:
SIAR publishing must be local-first, revision-safe, cryptographically attributable where desired, privacy-scoped, resilient to offline operation, and incapable of silently exposing creator identity or draft history.
2. Architectural Position
Authoring
│
▼
Draft State
│
▼
Validation / Signing / Media Finalization
│
▼
Publication Record
│
├── Feed
├── Channel
├── Community
├── Public Discovery
└── Federation
3. Core Separation
Keep distinct:
draft
published revision
creator identity
publisher pseudonym
media blob
distribution state
moderation state
analytics
4. Non-Goals
Part 88 does not create:
one global author identity
server-owned plaintext drafts by default
immutable public content forever
automatic exposure of edit history
centralized behavioral profiling of creators
5. Content Types
#![allow(unused)] fn main() { pub enum PublishedContentType { Post, Article, Announcement, ImagePost, VideoPost, AudioPost, LinkPost, DocumentPost, } }
6. Post
Short-form.
7. Article
Long-form.
8. Announcement
Publisher/channel notice.
9. Media Post
Primary media attachment.
10. Document Post
Document/file publication.
11. Content Identity
#![allow(unused)] fn main() { pub struct ContentId(pub [u8; 32]); }
12. Revision Identity
#![allow(unused)] fn main() { pub struct ContentRevisionId(pub [u8; 32]); }
13. Draft Identity
#![allow(unused)] fn main() { pub struct DraftId(pub [u8; 32]); }
14. Hard Rule
DraftId, ContentId, and ContentRevisionId remain distinct.
15. Why
Draft metadata should not leak into published identifiers.
16. Creator Identity Modes
#![allow(unused)] fn main() { pub enum CreatorIdentityMode { RelationshipScoped, SpaceScopedPseudonym, PublicPseudonym, ManagedIdentity, AnonymousPublisherCapability, } }
17. RelationshipScoped
For private contact-sharing.
18. SpaceScopedPseudonym
Group/community identity.
19. PublicPseudonym
Public creator identity by choice.
20. ManagedIdentity
Organization identity.
21. AnonymousPublisherCapability
Limited publishing without stable public identity where supported.
22. Hard Rule
Publishing never requires exposing login AccountId.
23. Creator Reference
#![allow(unused)] fn main() { pub struct CreatorRef { pub mode: CreatorIdentityMode, pub pseudonym: Option<PublisherPseudonym>, } }
24. No Email/Phone In Creator Record
Hard rule.
25. Creator Profile
Part 84 projection.
26. Public publisher profile
Separate from private account profile.
27. Draft State
#![allow(unused)] fn main() { pub enum DraftState { Editing, Ready, Scheduled, Publishing, Published, Abandoned, } }
28. Editing
Normal local authoring.
29. Ready
Passed validation.
30. Scheduled
Waiting for publish time.
31. Publishing
Durable workflow in progress.
32. Published
Content exists.
33. Abandoned
Local draft no longer active.
34. Hard Rule
Draft is never considered published until publication commit succeeds.
35. Draft Record
#![allow(unused)] fn main() { pub struct DraftRecord { pub draft_id: DraftId, pub content_type: PublishedContentType, pub creator: CreatorRef, pub target: PublicationTarget, pub body: DraftBody, pub attachments: Vec<DraftAttachmentRef>, pub state: DraftState, pub version: DraftVersion, } }
36. Draft Version
#![allow(unused)] fn main() { pub struct DraftVersion(pub u64); }
37. Local-First Draft
Primary authoring state stored locally.
38. Hard Rule
Network availability is not required to create/edit a draft.
39. Autosave
Transactional local save.
40. No Remote Autosave Requirement
Hard rule.
41. Autosave Frequency
Bounded/debounced.
42. Crash Recovery
Last committed local version.
43. No Unbounded In-Memory Draft
Hard rule.
44. Draft Storage
Encrypted local DB.
45. Draft Media
Encrypted local blob store.
46. Draft Encryption
At rest.
47. Server Draft Sync
Optional.
48. Default
Encrypted account sync only if enabled.
49. No Plaintext Cloud Draft Requirement
Hard rule.
50. Draft Sync Classification
#![allow(unused)] fn main() { pub enum DraftSyncMode { LocalOnly, EncryptedAccountSync, ManagedWorkspaceSync, } }
51. LocalOnly
Strong privacy.
52. EncryptedAccountSync
Own devices only.
53. ManagedWorkspaceSync
Managed workspace policy.
54. Hard Rule
Draft sync mode is explicit per draft/workspace.
55. Draft Sync Envelope
#![allow(unused)] fn main() { pub struct DraftSyncEnvelope { pub draft: DraftId, pub version: DraftVersion, pub encrypted_payload: EncryptedDraftPayload, } }
56. No plaintext body server-side where E2EE draft sync enabled.
57. Multi-Device Draft Editing
Potential conflicts.
58. Conflict Modes
#![allow(unused)] fn main() { pub enum DraftConflictPolicy { ManualMerge, StructuredMerge, LastWriterWinsAllowed, } }
59. Default Long-Form
Manual/structured merge.
60. Short low-risk metadata
LWW allowed.
61. Hard Rule
Never silently lose article body through naive LWW.
62. Structured Text Model
Possible:
block-based document
operation log
CRDT
63. Initial Recommendation
Versioned block/document model with explicit merge.
64. CRDT
Optional later.
65. No custom complex CRDT until needed.
66. Draft Collaboration
Not baseline.
67. If added
Separate architecture.
68. Publication Target
#![allow(unused)] fn main() { pub enum PublicationTarget { DirectRelationship(RelationshipId), SocialSpace(SocialSpaceId), Channel(ChannelId), PublicPublisher(PublisherPseudonym), ManagedWorkspace(OrganizationId), FederationTarget(FederatedPublicationTarget), } }
69. Target determines visibility/authority.
70. No Publish Without Target Capability
Hard rule.
71. Visibility
#![allow(unused)] fn main() { pub enum ContentVisibility { PrivateRelationship, MembersOnly, Subscribers, Public, Managed, } }
72. Visibility Derived From Target/Policy
73. User may request stricter visibility.
74. Cannot widen beyond target policy without authorization.
75. Hard Rule
Publishing preference cannot override authorization/privacy floor.
76. Publication Validation
Before publish:
target authorization
creator capability
body bounds
media availability
visibility policy
moderation preconditions
77. Validator Trait
#![allow(unused)] fn main() { pub trait PublicationValidator { fn validate( &self, draft: &DraftRecord, ) -> Result<ValidatedPublication, PublishError>; } }
78. No Network Calls Inside Final State Commit
Hard rule.
79. Media Finalization
Attachments finalized before publication commit or referenced via durable upload workflow.
80. Media Attachment
#![allow(unused)] fn main() { pub struct PublicationAttachment { pub blob: BlobId, pub media_type: MediaType, pub digest: ContentDigest, pub dimensions: Option<MediaDimensions>, } }
81. Media Blob
Content-addressed/encrypted where private.
82. Public Media
Can be plaintext/public CDN object by policy.
83. Private Media
Encrypt-before-upload.
84. Hard Rule
Private publication media never relies solely on transport TLS for confidentiality.
85. Media Metadata
Strip:
EXIF
GPS
device model
camera serial
unless user explicitly preserves.
86. Hard Rule
Sensitive metadata stripped by default.
87. Media Processing
Resize/transcode/thumbnail.
88. Local-first where feasible.
89. Server processing
Only on content server is allowed to inspect.
90. Private E2EE media
Processing before encryption or on-device.
91. Hard Rule
Server cannot decrypt private media merely to generate thumbnails.
92. Thumbnail
Generate before encryption.
93. Public Media Pipeline
Can use server processing.
94. Separate trust path.
95. Article Body Model
#![allow(unused)] fn main() { pub struct ArticleDocument { pub title: ArticleTitle, pub blocks: Vec<ArticleBlock>, } }
96. Blocks
#![allow(unused)] fn main() { pub enum ArticleBlock { Paragraph(TextBlock), Heading(HeadingBlock), Quote(TextBlock), Code(CodeBlock), Image(MediaRef), Video(MediaRef), Link(LinkBlock), } }
97. Block Count Bounded.
98. No Arbitrary Active HTML
Hard rule.
99. Sanitized Markdown
Optional source.
100. Render to safe internal block model.
101. Scripts
Forbidden.
102. Iframes
Forbidden by default.
103. External Embed
Explicit safe embed/proxy policy.
104. No Remote Tracking Pixel
Hard rule.
105. Link Metadata
Fetched according to privacy setting.
106. Max-anonymity
No direct external preview fetch.
107. Post Body
#![allow(unused)] fn main() { pub struct PostBody { pub text: BoundedText, pub links: Vec<SafeLinkRef>, } }
108. Text Length Bounded.
109. Mentions
Scoped.
110. Mention Reference
#![allow(unused)] fn main() { pub enum MentionRef { Relationship(RelationshipId), Membership(MembershipPseudonym), PublicPublisher(PublisherPseudonym), } }
111. No Raw AccountId Mention
Hard rule.
112. Mention Notification
Capability/visibility checked.
113. No Mention Enumeration Oracle
Hard rule.
114. Hashtags/Topics
Optional public metadata.
115. Topic Tags
#![allow(unused)] fn main() { pub struct TopicTag(pub String); }
116. Normalize.
117. Bounded count.
118. Private content
Do not send topic tags to public index.
119. Hard rule.
120. Content Signing
Useful for provenance.
121. Publication Signature
#![allow(unused)] fn main() { pub struct PublicationSignature { pub signer: PublisherSigningKeyId, pub content_digest: ContentDigest, pub signature: SignatureBytes, } }
122. Signer Identity
Publisher pseudonym/space identity.
123. Not login identity.
124. Hard rule.
125. Public Posts
Can be signed.
126. Private Group Messages
Use group/message crypto instead.
127. Signature Scope
Content revision.
128. Revision changes require new signature.
129. No Signature Reuse Across Revisions
Hard rule.
130. Provenance
#![allow(unused)] fn main() { pub struct ContentProvenance { pub content: ContentId, pub revision: ContentRevisionId, pub parent_revision: Option<ContentRevisionId>, pub signature: Option<PublicationSignature>, } }
131. No creator login identity embedded.
132. Revision Lifecycle
#![allow(unused)] fn main() { pub enum RevisionState { Draft, Published, Superseded, Retracted, Deleted, } }
133. First Publication
Revision 1.
134. Edit
Creates new revision.
135. Old revision
Superseded.
136. Public Revision History
Policy-controlled.
137. Private Revision History
Local/creator only by default.
138. Hard Rule
Editing content does not automatically expose all prior versions publicly.
139. Revision Visibility Policy
#![allow(unused)] fn main() { pub enum RevisionHistoryPolicy { Hidden, CurrentOnly, PublicHistory, ModeratorVisible, } }
140. PublicHistory
Explicit.
141. CurrentOnly
Most common.
142. ModeratorVisible
Space moderation.
143. Hidden
Private relationship content.
144. Revision Update
Atomic.
145. New revision published before current pointer changes.
146. No Partial Published Revision
Hard rule.
147. Content Head
#![allow(unused)] fn main() { pub struct ContentHead { pub content: ContentId, pub current_revision: ContentRevisionId, pub version: u64, } }
148. CAS Update
Prevent edit races.
149. Concurrent Edit
Conflict.
150. No Last-Writer Silently Deletes Published Revision
Hard rule.
151. Scheduled Publishing
Durable.
152. Schedule Record
#![allow(unused)] fn main() { pub struct ScheduledPublication { pub draft: DraftId, pub schedule: PublishSchedule, pub state: ScheduleState, } }
153. Schedule State
#![allow(unused)] fn main() { pub enum ScheduleState { Pending, Due, Publishing, Completed, Cancelled, Failed, } }
154. Time Semantics
Part 60.
155. User-specified wall-clock schedule.
156. Store timezone intent if needed locally.
157. Server schedule normalized.
158. Hard Rule
Critical publish timing does not depend on device being online if server scheduling enabled.
159. Local-Only Schedule
May publish when device reconnects.
160. UI must distinguish.
161. No false exact-time guarantee offline.
162. Hard truth.
163. Scheduled Draft Encryption
Server may store encrypted draft until due.
164. To publish public plaintext, server needs publishable payload/key.
165. Options:
pre-encrypted public payload
trusted managed publisher
device-online execution
166. Private E2EE scheduled content
requires careful key availability.
167. No server escrow of universal private keys.
168. Hard rule.
169. Publication Workflow
validate
→ finalize media
→ construct revision
→ sign
→ persist revision + head
→ create distribution outbox
→ commit
→ distribute asynchronously
170. Persist Before Distribution
Hard rule.
171. Distribution Outbox
Part 75.
172. Distribution Targets
feed index
channel fanout
subscriber delivery
public search
federation
notification hints
173. No direct synchronous fanout in publish transaction.
174. Hard rule.
175. Publication State
#![allow(unused)] fn main() { pub enum PublicationState { Pending, Committed, Distributing, Distributed, PartiallyDistributed, FailedDistribution, } }
176. Publication Commit Success
Does not require all downstream delivery complete.
177. UI
Shows "published, distributing" if needed.
178. No false atomic-global-publication claim.
179. Hard truth.
180. Distribution Idempotency
Required.
181. Same revision distributed twice
No duplicate feed item.
182. Stable distribution event ID.
183. Feed Integration
Part 87.
184. Feed receives publication projection.
185. Ranking separate.
186. Publisher cannot force ranked placement except explicit pin/admin policy.
187. Hard rule.
188. Social Space Integration
Part 86.
189. Channel/group publication requires membership/capability.
190. Moderator/publication roles.
191. Announcement channel
publisher capability required.
192. No Role Name Shortcut.
193. Contact Integration
Direct publication to relationship.
194. Uses relationship capability.
195. Not global feed.
196. Federation Distribution
Cross-domain publication.
197. Federation gateway sends signed publication projection.
198. No raw internal draft/revision state.
199. Hard rule.
200. Public Federation
Can cache public content.
201. Private federation
Capability-controlled encrypted content.
202. No gateway plaintext if E2EE.
203. Creator Identity Across Federation
Domain scoped.
204. No global AccountId merge.
205. Hard rule.
206. Retraction
Author withdraws published content.
207. Retraction State
#![allow(unused)] fn main() { pub enum RetractionReason { AuthorChoice, Error, SecurityIssue, PolicyViolation, LegalRequirement, } }
208. Retraction Flow
authorize
→ create retraction marker
→ update content head/state
→ distribute retraction
→ remove from discovery/feed
209. No Hard Delete Required Immediately.
210. Retraction vs Deletion
Separate.
211. Hard Rule
UI/API distinguish retracted from deleted.
212. Retraction Propagation
Asynchronous.
213. Cached copies may remain temporarily.
214. Public archives may preserve according to policy.
215. No universal erasure claim.
216. Hard truth.
217. Deletion
Stronger lifecycle action.
218. Deletion Policy Depends On
public/private
retention
legal
ownership
219. Private content
Cryptographic erasure possible.
220. Public content
Copies may exist externally.
221. No claim external copies erased.
222. Hard rule.
223. Deletion Tombstone
Prevent stale federation/cache resurrection.
224. Content Deletion Epoch
#![allow(unused)] fn main() { pub struct ContentDeletionEpoch(pub u64); }
225. Monotonic.
226. Stale revision older than epoch rejected.
227. Hard rule.
228. Restore/Backup
Part 33/67.
229. Draft backup
Logical encrypted.
230. Published creator state
Logical.
231. Live distribution jobs
Reconstructed/idempotent.
232. Deleted/retracted state
Must survive restore.
233. Hard rule.
234. Media Deletion
Blob refs.
235. GC after references removed/retention satisfied.
236. No cross-user dedup strict mode.
237. Shared Public Blob
If public dedup enabled, deletion semantics reference-counted.
238. Private content
Per-publication key.
239. Cryptographic erasure via key deletion.
240. Creator State
Need explicit lifecycle.
241. Creator Workspace
#![allow(unused)] fn main() { pub struct CreatorState { pub drafts: Vec<DraftId>, pub scheduled: Vec<DraftId>, pub publications: Vec<ContentId>, pub publisher_profiles: Vec<PublisherPseudonym>, } }
242. Stored locally/account encrypted.
243. No global creator dashboard requirement.
244. Creator State Sync
Encrypted.
245. No server behavioral profile.
246. Hard rule.
247. Publisher Pseudonym Lifecycle
#![allow(unused)] fn main() { pub enum PublisherState { Active, Paused, Rotating, Retired, } }
248. Rotation
Possible.
249. Public continuity proof optional.
250. No forced link to old pseudonym.
251. Hard rule.
252. Creator Profile
Separate from account profile.
253. Multiple public pseudonyms allowed.
254. No requirement to link them.
255. Hard rule.
256. Publisher Signing Key
Separate per pseudonym/domain.
257. No one signing key across all public identities.
258. Hard rule.
259. Publisher Key Rotation
Signed continuity statement if desired.
260. No silent substitution.
261. Identity change warning if verification used.
262. Content Ownership
#![allow(unused)] fn main() { pub enum ContentOwnership { Personal, SocialSpace, ManagedOrganization, SharedCollaborative, } }
263. Personal
Creator controls.
264. SocialSpace
Space policy.
265. ManagedOrganization
Org policy.
266. SharedCollaborative
Future collaboration.
267. Ownership Determines Delete/Edit Authority
Hard rule.
268. No Account Row Ownership Shortcut
Hard rule.
269. Moderation
Separate from creator authority.
270. Moderator may hide/remove within space.
271. Moderator does not become creator.
272. Hard rule.
273. Moderated Content State
#![allow(unused)] fn main() { pub enum ModerationVisibility { Visible, Limited, Hidden, Removed, } }
274. Content Revision Remains Creator State
Depending retention.
275. No silent content rewrite by moderator.
276. Hard rule.
277. Moderator Action
Can:
hide
remove from space
label
lock replies
278. Cannot alter author's signed body.
279. Hard rule.
280. If correction needed
new author revision.
281. Managed Announcement
Org publisher may update according to policy.
282. Distinguish creator vs org authority.
283. Publication Capability
#![allow(unused)] fn main() { pub struct PublicationCapability { pub target: PublicationTarget, pub actions: BTreeSet<PublicationAction>, pub expires_at: Option<Timestamp>, } }
284. Publication Actions
#![allow(unused)] fn main() { pub enum PublicationAction { Create, Revise, Retract, Delete, Schedule, Pin, } }
285. Pin
Separate elevated capability.
286. No ordinary creator automatic pin.
287. Hard rule.
288. Content Validation
Security.
289. Text bounds.
290. Media size bounds.
291. MIME sniffing.
292. No trust in file extension.
293. Hard rule.
294. Malware Risk
Attachments may contain malicious files.
295. For public downloads:
safe metadata
content-disposition
sandbox viewer
296. No auto-execution.
297. Hard rule.
298. Archive Files
Restricted preview.
299. Document Rendering
Sandboxed.
300. PDF/media pipeline Part 40/other components.
301. Image Decoder
Memory limits.
302. Video
Codec limits.
303. Zip bomb
Detect bounds.
304. Hard rule.
305. Content Hash
Integrity.
306. Digest algorithm registry Part 66.
307. No MD5/SHA1 for security integrity.
308. Content Addressing
Use modern digest.
309. Public Provenance
Can expose digest/signature.
310. Private content
Digest not globally published.
311. Hard rule.
312. Scheduled Revision
Can schedule update.
313. Current content remains until commit.
314. No half-updated state.
315. Publication Lock
Optimistic version.
316. Concurrent Creator Devices
CAS.
317. Conflict notification.
318. No silent overwrite.
319. Hard rule.
320. Draft Collaboration Future
Would require:
collaborator capability
operation sync
authorship attribution
321. Not baseline.
322. Comments/Replies
Could be social interactions.
323. Reply Target
Content revision/content ID.
324. Visibility inherited/scoped.
325. No reply to content user cannot access.
326. Hard rule.
327. Threading
Local/server metadata.
328. No global reply graph across private spaces.
329. Hard rule.
330. Mention Notifications
Opaque push hint.
331. No full content in push.
332. Hard rule.
333. Public Search
Published public content only.
334. Drafts never indexed.
335. Private content never indexed centrally.
336. Hard rule.
337. Search Index Update
After publication commit via outbox.
338. Retraction removes index entry.
339. Deletion removes/tombstones.
340. No search-before-commit.
341. Hard rule.
342. Feed Distribution
Part 87.
343. Feed candidate after commit.
344. No direct creator access to ranking score.
345. Creator may see aggregate distribution status.
346. No algorithm gaming API.
347. Hard rule.
348. Creator Analytics
Privacy-safe only.
349. Allowed:
aggregate public views
reaction buckets
subscriber-count bucket
distribution success
350. Forbidden by default:
viewer identities
exact read timestamps
viewer contact graph
precise locations
per-viewer dwell time
351. Hard rule.
352. Small Audience
Suppress analytics below threshold.
353. Prevent deanonymization.
354. Creator Analytics Threshold
#![allow(unused)] fn main() { pub struct AnalyticsThreshold { pub minimum_cohort: u32, } }
355. No small cohort breakdown.
356. Hard rule.
357. Distribution Status
#![allow(unused)] fn main() { pub struct DistributionStatus { pub target_count_class: DistributionCountClass, pub state: PublicationState, } }
358. Coarse.
359. No subscriber identity list.
360. Hard rule.
361. Content Recommendation Metadata
Publisher can provide topics/categories.
362. Cannot provide user-targeting segment IDs.
363. Hard rule.
364. No "show this to users like X" behavioral target baseline.
365. Public Promotion
Future economics/ads separate.
366. Must be labeled if ever implemented.
367. Not core.
368. Anti-Spam Publishing
Rate limits.
369. Source quotas.
370. Storage quotas.
371. No invasive identity verification requirement.
372. Hard rule.
373. Public Publisher Abuse
Can suspend publisher pseudonym/space capability.
374. Does not automatically disable personal account unless separate authority.
375. Hard rule.
376. Publication Rate Policy
#![allow(unused)] fn main() { pub struct PublicationQuota { pub max_items: u32, pub window: Duration, pub max_bytes: u64, } }
377. Tenant/social-space scoped.
378. No global user behavior score.
379. Draft Limits
Bounded count/bytes.
380. No unlimited cloud drafts.
381. Local disk limits configurable.
382. Background Media Upload
Resumable.
383. Publish can wait for upload completion.
384. Or public article published without optional media? policy-specific.
385. No broken references at commit.
386. Hard rule.
387. Media Upload Session
#![allow(unused)] fn main() { pub struct MediaUploadSession { pub upload_id: UploadId, pub blob: BlobId, pub expected_digest: ContentDigest, pub state: UploadState, } }
388. Upload State
#![allow(unused)] fn main() { pub enum UploadState { Pending, Uploading, Verifying, Complete, Failed, Cancelled, } }
389. Verify digest before publication.
390. Hard rule.
391. Offline Public Publishing
Draft local.
392. Publish command queued.
393. On reconnect:
revalidate auth/policy
finalize media
commit
394. Hard Rule
Offline queued publish does not bypass current policy at reconnect.
395. Scheduled Offline Publishing
If no server schedule exists, best-effort when online.
396. UI truthful.
397. Content Expiry
Optional.
398. Ephemeral publication.
399. Expiry Policy
#![allow(unused)] fn main() { pub enum ContentExpiryPolicy { Never, After(Duration), At(Timestamp), } }
400. Expiry Is Not Secure Erasure
Hard truth.
401. Expired content
Removed from active distribution.
402. Cached copies may exist.
403. Private encrypted content
key expiry/destruction can strengthen.
404. No false ephemeral claim.
405. Content Versioning
Storage/API/protocol versions separate.
406. Revision schema migration.
407. Unknown block
safe placeholder or reject.
408. Security-sensitive unknown
reject.
409. No silent active-content interpretation.
410. Hard rule.
411. Serialization
Postcard internal/protocol.
412. RON human export/config.
413. JSON external interop.
414. Article export
Markdown possible.
415. Sanitized.
416. No active script.
417. Creator Export
Exports:
drafts
published content
revision metadata
publisher profile
418. Excludes:
live session tokens
private signing key unless explicit secure key export
subscriber identities
419. Hard rule.
420. Publisher Key Backup
Part 33/57/66.
421. May backup encrypted logical key if user chooses.
422. HSM/secure element key may require continuity method.
423. No blind key cloning.
424. Hard rule.
425. Publisher Migration
Cross-provider/federation.
426. Export signed publisher continuity proof.
427. New domain can reference.
428. No global identity authority.
429. Hard rule.
430. Managed Publishing
Organization workspace.
431. Draft may be org-owned.
432. Ownership policy explicit.
433. Offboarding
Personal drafts remain personal if personal-owned.
434. Org-owned drafts remain org.
435. Hard rule.
436. Approval Workflow
Optional for managed publishing.
437. States:
#![allow(unused)] fn main() { pub enum EditorialState { Draft, InReview, Approved, Rejected, Published, } }
438. Reviewer capability scoped.
439. No reviewer automatic publish unless permitted.
440. Audit managed workflow.
441. No hidden personal draft audit.
442. Hard rule.
443. Publication Approval
Durable workflow.
444. Current revision approved by digest.
445. If draft changes after approval
approval invalidated.
446. Hard rule.
447. Approval Record
#![allow(unused)] fn main() { pub struct EditorialApproval { pub draft: DraftId, pub draft_digest: ContentDigest, pub approver: ManagedPublisherId, } }
448. No approving mutable pointer.
449. Good invariant.
450. Creator Workspace Search
Local.
451. Draft search index local encrypted/derived.
452. No central indexing of private drafts.
453. Hard rule.
454. Public Published Search
Central/public index allowed.
455. Private publication search local.
456. Observability
Safe metrics:
publish success
distribution lag
media upload failures
revision conflict rate
457. Forbidden metrics:
draft content
typing cadence
edit keystroke history
private topic interests
458. Hard rule.
459. No Keystroke Telemetry
Hard rule.
460. Draft Autosave Metrics
Only count/latency aggregate.
461. Publisher Analytics Separate
Thresholded and privacy-safe.
462. Publication SLOs
Examples:
draft durability
publish commit latency
distribution completion
media integrity
463. Security SLO
0 private draft indexed publicly
0 publication without target capability
464. Privacy SLO
0 login AccountId in public creator metadata
0 viewer identity analytics
465. Failure Modes
media upload fails
signing fails
distribution partially fails
federation unavailable
scheduler unavailable
466. Media Upload Failure
Draft remains.
467. Signing Failure
No publish.
468. Distribution Partial Failure
Publication remains committed; retry downstream.
469. Federation Down
Local publication succeeds; remote distribution retries.
470. Scheduler Down
Scheduled jobs recover from durable state.
471. No Duplicate Publication
Idempotency.
472. Hard rule.
473. Publication Idempotency Key
#![allow(unused)] fn main() { pub struct PublishOperationId(pub [u8; 32]); }
474. Same operation returns same committed result.
475. No duplicate public post from retry.
476. Hard rule.
477. Event Bus Integration
Part 75.
478. Events:
ContentPublished
ContentRevised
ContentRetracted
ContentDeleted
MediaFinalized
479. Minimal metadata.
480. No draft body on bus.
481. Hard rule.
482. Database Integration
Part 74.
483. Draft store, publication store, media metadata separate logically.
484. Transaction boundary:
revision + content head + outbox
485. No network call inside transaction.
486. Hard rule.
487. Authorization Integration
Part 81.
488. Creator capability checked.
489. Revise/retract/delete separate actions.
490. No create capability implies delete.
491. Hard rule.
492. Authentication Integration
Part 82.
493. Sensitive public identity/key changes may require step-up.
494. Routine posting does not require repeated MFA.
495. Account Lifecycle
Part 83.
496. Deleted account cannot publish.
497. Suspended publisher policy-specific.
498. Managed offboarding revokes managed publish capabilities.
499. No stale scheduled publish after deletion/offboarding.
500. Hard rule.
501. Profile Integration
Part 84.
502. Publisher profile projection.
503. Personal profile remains separate.
504. Contacts Integration
Part 85.
505. Direct contact posts use relationship capability.
506. Social Space Integration
Part 86.
507. Channel/community publication authority.
508. Feed Integration
Part 87.
509. Feed index after commit.
510. Ranking separate.
511. Edge Integration
Part 78.
512. Public publishing API L7.
513. Media upload bounded.
514. Private E2EE payload opaque to WAF.
515. East-West Integration
Part 79.
516. Publisher/media/index services mTLS.
517. Secrets Integration
Part 80.
518. Signing keys short-lived/secure handles where possible.
519. No signing private key in logs/env.
520. Federation Integration
Part 58.
521. Signed public publication envelope.
522. No raw internal service identifiers.
523. Crate Layout
Recommended:
crates/
├── siar-publish-core/
├── siar-draft/
├── siar-content-document/
├── siar-content-revision/
├── siar-publication/
├── siar-media-publication/
├── siar-publication-signing/
├── siar-publication-scheduler/
├── siar-publication-distribution/
├── siar-creator-state/
├── siar-publication-observability/
└── siar-publication-testkit/
524. siar-publish-core
Owns:
content IDs
publication targets
visibility
errors
525. siar-draft
Local draft lifecycle/sync.
526. siar-content-document
Safe post/article block model.
527. siar-content-revision
Immutable revisions/head/CAS.
528. siar-publication
Commit/retract/delete workflow.
529. siar-media-publication
Attachment finalization/transcoding/metadata stripping.
530. siar-publication-signing
Publisher pseudonym provenance.
531. siar-publication-scheduler
Durable scheduled publishing.
532. siar-publication-distribution
Feed/channel/search/federation outbox consumers.
533. siar-creator-state
Publisher/draft/scheduled state.
534. siar-publication-observability
Aggregate publish/distribution metrics.
535. siar-publication-testkit
offline/revision/media/distribution/privacy tests.
536. Error Taxonomy
#![allow(unused)] fn main() { pub enum PublishError { DraftNotFound, DraftConflict, InvalidContent, AttachmentIncomplete, AttachmentDigestMismatch, PublicationDenied, VisibilityDenied, SigningFailed, ScheduleInvalid, PublicationAlreadyCommitted, RevisionConflict, ContentRetracted, ContentDeleted, DistributionFailed, Internal, } }
537. Testing
Need dedicated publishing testkit.
538. Test Scenarios
offline draft
publish retry
revision race
scheduled publish
media failure
539. Offline Draft Test
Create/edit without network.
540. Draft Crash Test
Last committed autosave restored.
541. Multi-Device Conflict Test
No silent article-body loss.
542. Unauthorized Publish Test
Target capability required.
543. Media Metadata Test
EXIF/GPS stripped.
544. Media Digest Test
Corrupt upload rejected.
545. Private Media Test
Server cannot generate plaintext thumbnail post-encryption.
546. Publication Commit Test
Revision/head/outbox atomic.
547. Publish Retry Test
No duplicate post.
548. Distribution Failure Test
Committed publication retries asynchronously.
549. Revision Race Test
CAS conflict, no silent overwrite.
550. Retraction Test
Removed from active feed/discovery.
551. Deletion Test
Stale federation/cache cannot resurrect.
552. Scheduled Publish Test
Durable timer survives restart.
553. Offline Scheduled Test
UI indicates best-effort when device execution required.
554. Identity Test
AccountId never appears in public creator metadata.
555. Pseudonym Rotation Test
Continuity proof optional/not forced.
556. Moderator Test
Moderator cannot rewrite signed author body.
557. Managed Approval Test
Approval bound to exact draft digest.
558. Account Deletion Test
Pending schedule cannot publish after account deletion.
559. Federation Test
Remote receives publication projection, not draft/internal state.
560. Analytics Test
No viewer identities exposed.
561. Search Test
Draft/private content never enters public index.
562. Backup Test
Deleted/retracted state survives restore.
563. Fuzzing
Fuzz:
article blocks
publication envelope
revision chain
media metadata
federated publication envelope
564. Property Tests
Properties:
only committed publication can enter distribution
content head always references committed revision
deleted/retracted content cannot become active from stale replica
creator account identity is never present in public publisher projection
565. Formal Verification Targets
Strong candidates:
draft→publish state machine
revision/head CAS
publish/distribution outbox
scheduled publish cancellation
deletion anti-resurrection
566. Kani Candidate
revision/state transition invariants.
567. TLA+ Candidate
publish commit + distribution retry + retraction race.
568. Loom Candidate
concurrent revision/publish/retract.
569. Performance
Draft editing
local.
570. Publish commit
small metadata transaction.
571. Media upload
streaming/resumable.
572. Distribution
async.
573. Public search indexing
async.
574. No fanout in request thread.
575. Hard rule.
576. Large Article
Block streaming/limits.
577. No giant single DB blob required.
578. Media references separate.
579. Feed projection small.
580. Creator Workspace Pagination
Draft/publication list paged.
581. No load-all-history.
582. Security, Privacy & Correctness Invariants
Mandatory:
1. Draft, published content, and immutable revision identities remain separate; draft identifiers never become public publication identifiers.
2. Draft authoring is local-first and does not require server/network availability.
3. Private drafts and private publication media are never required to exist as server-side plaintext.
4. Publication requires explicit target-scoped capability and cannot widen visibility beyond policy/authorization.
5. Public creator/publisher pseudonyms remain separate from account/login, transport, mailbox, payment, and telemetry identities.
6. Media metadata such as GPS/EXIF/device identifiers is stripped by default before publication.
7. A publication becomes visible to distribution systems only after its revision, content head, and outbox commit durably.
8. Publication retries are idempotent and cannot create duplicate posts.
9. Revisions are immutable; edits create a new revision and concurrent edits cannot silently overwrite each other.
10. Moderators may control visibility inside their scope but cannot silently rewrite an author's signed content.
11. Retraction/deletion epochs prevent stale caches, backups, federation replicas, or delayed jobs from resurrecting removed content.
12. Creator analytics are aggregate/thresholded and never expose viewer identities, detailed dwell behavior, contact graphs, or precise location histories.
583. Initial Production Scope
Implement first:
typed DraftId/ContentId/ContentRevisionId
local encrypted draft store
autosave/crash recovery
post/article safe block model
publication targets/visibility
target-scoped publication capabilities
media upload/finalization/digest verification
EXIF/GPS stripping
immutable content revisions + CAS head
publisher pseudonym/signing support
transactional publication + distribution outbox
feed/channel/public-search distribution
retraction/deletion tombstones
durable scheduled publishing
encrypted optional multi-device draft sync
thresholded creator analytics
publishing testkit
Then add:
collaborative drafts
CRDT-based coauthoring
advanced public provenance chains
cross-provider publisher migration
privacy-preserving creator analytics
formal publishing/distribution verification
584. Definition of Done
Part 88 is complete when:
- drafts are local-first and crash-safe
- draft/publication/revision identities are separate
- public creator identity is pseudonymous/scoped
- publication requires target capability
- private draft/media state stays encrypted
- media metadata is stripped by default
- revisions are immutable and race-safe
- publication commit precedes distribution
- distribution is idempotent and asynchronous
- scheduled publishing is durable and policy-aware
- retraction/deletion anti-resurrection works
- moderation cannot rewrite creator-signed body
- private/public search boundaries are explicit
- creator analytics remain thresholded/privacy-safe
- offline/revision/media/distribution/fuzz/formal tests are specified
585. Final Architecture
AUTHORING
│
▼
LOCAL DRAFT
│
▼
VALIDATION / MEDIA FINALIZATION
│
▼
IMMUTABLE REVISION
│
▼
PUBLICATION COMMIT
│
▼
DISTRIBUTION OUTBOX
┌────────┼────────┐
│ │ │
FEED CHANNEL FEDERATION
│ │ │
└────────┼────────┘
▼
DISCOVERY/DELIVERY
Publishing safety model:
local-first drafts
+
scoped publisher identity
+
immutable revisions
+
transactional publish
+
async idempotent distribution
+
private media encryption
+
anti-resurrection
+
privacy-safe analytics
not:
upload every draft and edit to a central server, expose the account behind every pseudonym, then synchronously fan out publication everywhere
586. Final Principle
Publishing should preserve the creator's control over identity, visibility, revision history, and distribution while keeping draft and behavioral data private by default.
The correct model is:
author locally
+
publish through scoped authority
+
sign as chosen identity
+
commit before distribute
+
revise immutably
+
retract honestly
+
delete with anti-resurrection
+
measure only in aggregate
This architecture gives SIAR a local-first, privacy-preserving content-publishing foundation for posts, articles, announcements, media, social spaces, public publishers, managed organizations, and federated distribution while preserving the anonymity, least-authority, and social-graph privacy guarantees established across Parts 34–87.