Social post approvals, and what an auto-publish switch actually switches off
An approval gate on social posts is a default, not a law. Here is what the switch that removes it actually removes, and the one case that ignores the switch.

An approval on a social post is a pending row that holds the submission until a person decides on it, and in Market4 that hold is a default rather than a law. Every app carries an auto-publish switch. With it off, a submission opens a PUBLISH_POST approval and nothing reaches the network until somebody approves. With it on, the same submission runs immediately — including the immediate kind, the one that cannot be recalled. One case ignores the switch entirely: a submission that costs extra money is never auto-approved.
A social post approval holds a payload, not a post. When the gate is on, Market4 stores the whole submission — the text after every policy has been applied, the channels it is aimed at, the scheduled time — as the payload of a pending approval, and creates nothing on the social side. Approving it is what runs the registered handler that pushes to Buffer. That ordering matters: a payload sitting in the queue has already been through the platform policy and the link-cost policy, so the thing a person approves is the thing that goes out, not an earlier draft of it.
The seven action types are PUBLISH_POST, SEND_BULK_EMAIL, SPEND_MONEY, ANALYTICS_CHANGE, BUFFER_PUBLISH, GTM_CHANGE and SERPAPI_SWEEP. A scheduled or immediate social post files under PUBLISH_POST. They are kept apart rather than collapsed into one queue because approving a post and approving a charge are different questions, and each type has its own execution handler that reads its own payload shape.
An approval gate on social posts protects the audience first and the author second. The audience is protected because a post that goes out to a public timeline is read by people who did not ask for it and cannot be asked to un-read it. The author is protected second, and more narrowly: from a mistake in a template, a wrong channel, a date that turned out to be a Sunday. Framing the gate as protecting the author alone is what leads people to switch it off the moment they trust themselves — which is the wrong test, because the risk was never their competence.
Three submission types exist and they carry different amounts of regret. A draft is stored locally and never handed to Buffer at all. A scheduled post is written into the calendar and pushed to Buffer inside a short window before its time, so cancelling it costs nothing until that window opens. An immediate post is handed over in the same call with Buffer's own share-now mode, with no cancel window at all.

An agent that can write its own audit row can write a plausible one. Four properties keep the trail out of reach: the row is written on the far side of the tool boundary, storage is append-only, the actor is a reference, and recording never fails the operation.

Market4 turns one release note into a changelog page, a blog post, a mail-out and a week of social posts — and then tells you which of them brought anyone back.
| Submission type | Reaches Buffer | Can it be cancelled | What the gate is worth |
|---|---|---|---|
| draft | Never | Not applicable — it was never going out | Little; nothing is public |
| schedule | At a push window before the scheduled time | Free until the push window opens | A second chance you already had |
| now | In the same call | No cancel window exists | The last chance there is |
Auto-publish does not stop immediate posts, and in Market4 it once did. Immediate publishing used to force the approval gate back on even for an app whose owner had switched it off, on the reasoning that a sent post cannot be un-sent. That reasoning still holds as a description of the risk, but it was removed as an override. Irreversibility is the thing the switch is a decision about, so honouring the switch everywhere except the irreversible case left the switch meaning almost nothing and left the approval queue exactly as full as before.
One rule survives the switch. Keeping a link on an X post multiplies the per-post cost the product pays, so a submission with a link kept forces an approval open regardless of the auto-publish setting. The code that decides this is a two-line function: an action type of SPEND_MONEY always requires approval, and everything else requires it only when auto-publish is off. Money leaving a card is never auto-approved, whatever the action happens to be called.
Three things sit between a social submission and the network in Market4, and the approval is only the middle one. The organisation-wide kill switch is checked first, before any approval may even be opened, so pulling the emergency brake stops the queue from growing rather than merely from draining. Then comes the platform policy, which can throw on a disabled network or quietly downgrade a scheduled post to a draft on a network set to draft-only. Then the approval. Then, at execution time, the kill switch and the quota are checked a second time — an approval can be granted and the execution still come back as a failure.
A pending approval in Market4 expires 72 hours after it was opened unless the caller asked for a different window. Expiry is not a soft state: a request past its deadline is flipped to EXPIRED, either by the sweep that marks overdue rows in bulk or lazily by the next attempt to decide on it. The four statuses are PENDING, APPROVED, REJECTED and EXPIRED, and an expired social post is not a rejected one — nobody said no, the clock simply ran out, which is a different lesson about the queue.
It is worth most on immediate posts and least on drafts. A draft never leaves the product, and a scheduled post can be cancelled for free until its push window opens, so the gate is mostly repeating a chance you already have. An immediate post has no cancel window at all: once it is handed to the network there is no product-side undo. If you keep the gate on for one thing, keep it on for that.
Nothing is published. The approval flips from PENDING to EXPIRED, either through the sweep that marks overdue rows or lazily when someone next tries to decide on it, and the stored payload stops being executable. The submission has to be made again. An expired approval is deliberately kept distinct from a rejected one, because nobody actually declined it — the 72-hour window simply closed.
No. The function that decides whether an approval is needed returns true for the SPEND_MONEY action type before it ever looks at the auto-publish setting. In practice this covers keeping a link on an X post, where the link multiplies the per-post cost: that submission opens an approval even on an app that otherwise publishes without waiting, and the extra cost is reported in the submission's warnings.
No. Approval and execution are separate states in the record for exactly this reason. A request can be APPROVED and its execution still come back FAILURE, because the kill switch, the daily quota and the Buffer budget are re-read when the handler actually runs rather than when the decision was made. A queue drained hours after it filled is judged against the conditions at drain time.
Before it. When an organisation has pulled its emergency stop, a social submission is refused before an approval request can even be opened, so the queue does not quietly fill up with work waiting for the brake to be released. The same check runs again at execution time, which means an approval granted before the stop was pulled will still not publish after it.
An agent writing at volume will run out of evidence long before it runs out of topics. There are three honest moves at that point, and inventing a plausible figure is not one of them.

Most of the port survived the swap. The two methods that did not are the two that decided how the whole feature has to work from now on.