| Mode | What it grants | How to enable |
|---|---|---|
| Viewer tokens | Read-only URLs anyone can open in a browser | slideless share <id> mints a token |
| Dev collaboration | Edit access — another authenticated user can push new versions | slideless invite <id> --email <addr> |
Roles
In v0.5, every presentation has exactly one owner and zero or more dev collaborators.- owner — the original creator. Can push, pull, share, unshare, invite, uninvite, delete.
- dev — invited collaborator. Can pull and push new versions. Cannot mint viewer tokens, invite others, or delete the deck.
viewer and admin will slot in later without a migration.
The slideless.json manifest
Every folder you push or pull gets a slideless.json at its root:
Invite lifecycle
- Owner invites by email.
slideless invite <id> --email alice@example.com. - Invitee exists? If Alice already has a Slideless account, she’s linked immediately (
status=active). - Invitee doesn’t exist? The row is stored
status=pending. Alice gets an email with a link. - Claim on signup. When Alice signs up with the same email, the existing
onUserDocumentCreatedtrigger flips every matching pending row toactiveand attaches her new uid. She sees the deck next time she runsslideless list. - Push, pull. Alice runs
slideless pull <id>, edits,slideless push. Her pushes show up withcreatedByRole: 'dev'in the version history. - Uninvite.
slideless uninvite <id> <collaboratorId>— revocation is immediate.
Cross-device workflow (owner only)
Even without collaborators,push/pull solve the “laptop → desktop” problem. On device A:
Push conflicts
Everypush on an existing presentation sends the last version you pulled as expectedBaseVersion. If the server has moved past that (someone else pushed), you get:
slideless pull && slideless push. --force bypasses the check and overwrites the remote collaborator’s work — use only when you know.
Plan limits
A push consumes the pusher’s organization quota, not the owner’s. A free-tier collaborator pushing to a paid-tier owner’s deck spends free-tier caps on that push. This prevents a trivial abuse vector and keeps billing intuitive.Pending-invite expiry
Pending invites expire 14 days afterinvitedAt. A scheduled function flips expired rows to revoked automatically.
Security model
- Every write endpoint re-runs an access check per request — no cached auth, no session tokens to leak.
- Revocation is immediate: a
uninvitetakes effect on the very next API call. downloadPresentationAssetverifies the requested SHA-256 appears in the requested version’s manifest, preventing an authenticated caller from enumerating unrelated blobs.- The CLI re-hashes every downloaded blob and aborts on mismatch — even a compromised bucket can’t ship bad bytes.