Skip to content

fix: keep post drafts unscheduled by default - #209

Merged
paulocastellano merged 8 commits into
trypostit:mainfrom
drbelt27:fix/unscheduled-drafts
Aug 1, 2026
Merged

fix: keep post drafts unscheduled by default#209
paulocastellano merged 8 commits into
trypostit:mainfrom
drbelt27:fix/unscheduled-drafts

Conversation

@drbelt27

@drbelt27 drbelt27 commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Drafts no longer get an implicit schedule. Creating a post without scheduled_at / date leaves scheduled_at = null. Moving a post to scheduled requires an explicit future datetime unless the post already has a reusable future schedule.

Shared across web, public API, and MCP via PostStatusRules::scheduledAtRules() / requiresExplicitSchedule() so the three entry points cannot drift.

Publish-now is unchanged: status = publishing still sets scheduled_at = now() and dispatches publish.

Behavior

Action Before After
Create draft with no schedule Defaulted to today 09:00 UTC scheduled_at = null
Create/apply with date=YYYY-MM-DD That day at 09:00 UTC Unchanged
Create with future scheduled_at Stored as given Unchanged
Update to scheduled with no scheduled_at and post has none/past Could succeed poorly Validation error on scheduled_at
Update to scheduled reusing an existing future scheduled_at Allowed; keeps existing time
Update to scheduled with a past scheduled_at Rejected (where after:now applied) Still rejected
Publish now (publishing) Sets scheduled_at = now() Unchanged

Test plan

Create / drafts

  • Web: create a post with no date → draft with scheduled_at = null
  • Web: create/apply template with date → draft scheduled that day at 09:00 UTC
  • API: create post without scheduled_at → draft, scheduled_at = null
  • API: create with past scheduled_at → validation error
  • MCP: create with empty args / omitted / explicit null schedule → unscheduled draft
  • MCP: create with past scheduled_at → validation error

Schedule update (web / API / MCP)

  • Draft with scheduled_at = null + status=scheduled without new time → rejected (scheduled_at required)
  • Draft with past scheduled_at + status=scheduled without new time → rejected
  • Draft with past schedule + status=scheduled + past scheduled_at → rejected (after:now)
  • Draft with future scheduled_at + status=scheduled without resubmitting time → succeeds and keeps the same datetime
  • Draft + status=scheduled + valid future scheduled_at → succeeds
  • Draft update with status=draft and no scheduled_at → still succeeds (stays unscheduled)

Publish now

  • Web/API: status=publishing without scheduled_at → publishes; scheduled_at becomes ~now
  • Confirm publish is not blocked by the new schedule-required rule

Regression smoke

  • Calendar does not show unscheduled drafts
  • Post editor opens an unscheduled draft (empty schedule picker) and can save as draft
  • Post editor can pick a time and schedule successfully
  • Duplicate post still creates an unscheduled draft

@cursor
cursor Bot force-pushed the fix/unscheduled-drafts branch 2 times, most recently from e28f12a to b34a397 Compare August 1, 2026 18:16
Require scheduled_at only when status is scheduled and the post has no
usable future schedule. Share that rule across web, API, and MCP, keep
create without a date as null, and preserve the legacy date → 09:00 UTC
fallback.
@cursor
cursor Bot force-pushed the fix/unscheduled-drafts branch from b34a397 to 38b0945 Compare August 1, 2026 18:16
cursoragent and others added 6 commits August 1, 2026 18:24
Type requiresExplicitSchedule status as ?string, reuse a local status
variable in request/tool validation, tighten the web reject assertion,
and collapse overlapping MCP unscheduled-create cases.
Reuse the typed status() helper across FormRequests and the already-parsed
$status in UpdatePostTool so schedule checks stay consistent and less noisy.
Centralize schedule validation in PostStatusRules, normalize status parsing
in one place, and align past-schedule coverage across entry points.
Add feature coverage for null/past schedule rejection, explicit scheduling,
draft saves, publish-now without a schedule, calendar exclusion, and
09:00 UTC date defaults across web, API, and MCP.
Keep the inline is_string check at the few call sites that read raw
request status before validation — no shared wrapper needed.

Co-authored-by: Cursor <cursoragent@cursor.com>
Accept mixed status in PostStatusRules and rely on strict comparisons
with Rule::requiredIf / Rule::when — malformed input simply does not match.

Co-authored-by: Cursor <cursoragent@cursor.com>
@paulocastellano
paulocastellano merged commit a33ff5d into trypostit:main Aug 1, 2026
5 checks passed
@paulocastellano

Copy link
Copy Markdown
Contributor

@drbelt27 thank you, i have improved that... and it's merged on main branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants