Vibes DIY
Vibes DIY / Docs
creator docs · pattern

The deploy button

The problem: you have a dangerous action — deploy to production, publish the release, run the migration — and you want a big friendly button with a real permission model around it. Traditionally: an internal tool plus an IAM policy plus an audit trail.

The pattern: make pressing the button write a document, and make the access function decide who may write it. The capability is the ACL.

js// access.js — the press capability
export default function (doc, oldDoc, user, ctx) {
  if (doc.kind === "press") {
    if (!user) throw { forbidden: "sign in to ship" };
    if (!user.isOwner) ctx.requireAccess("crew"); // the deploy crew channel
    return { channels: ["crew"], grant: { public: ["status"] } };
  }
  // …status docs, config, etc.
}

Grant the crew channel to the humans allowed to ship. Everyone else sees the button render LOCKED — the UI reads its own capability with useVibe("presses").can.create and tells the truth, because the same rule runs server-side on the actual write. There's nothing to bypass: the button is just a doc write, and the doc write is gated.

Downstream, the press doc enters a doc state machine: a watcher (a CI lane or the backend itself) sees the press, triggers the real deploy, and writes status back — which the button page renders live as the deploy progresses. The press ledger is the audit trail, with author, timestamp, and outcome on every doc.

In production: jchris/ship-button

The platform ships itself with this pattern: jchris/ship-button fronts the release fan-out workflow. Its dashboard reads the repo's tag streams and CI runs client-side, ctx.callAI summarizes "what's about to ship" from the pending commits (the story), and the glowing SHIP IT is crew-gated exactly as above.

A detail worth stealing: when the platform's own operator opened it while browsing under an alt handle of the same account, the button rendered LOCKED — crew grants are handle-based, and even the owner's other handle doesn't inherit the press capability. The access model didn't special-case anybody; that screenshot ended up in the launch post because the lock telling the owner "no" is the whole pattern working.

Where it generalizes

Any privileged action wrapped as a doc write inherits the full stack: roles and channels for who, the state machine for what happened, the operator console for watching it, and live sync so the person who pressed and the person who watches see the same truth. Approve-the-expense, publish-the-newsletter, unlock-the-door — same button, different verb.