Seed catalogue · Knowledge
Slate
A self-hosted knowledge workspace where pages live in a tree inside containers, with structured records, search and AI beside them.
- Alternative to
- Notion, Confluence, under MIT
- Domain
- a page in a tree in a container
- Version
- 0.1.0
- Contract
- 191 clauses across 27 areas
- Maturity
- foundation-and-components-consolidated: TanStack Start and Hono share one Worker with native sessions and the knowledge migration; real-export parsers and the supplied-prop UI library pass their regressions and clean-checkout verification; all 191 product contract journeys remain planned; no deployment or release tag
No product screenshots have been published.
What you get
Everything below is generated from the seed's own manifest and contract. No rounded-off claims, no numbers we made up.
Operating cost
Runs on your cloud's free tier
The seed declares the free plan as the default deployment. Its own estimate, thresholds and sources are below, unedited.
- Status
- estimated and not measured; no deployment of this contract's product exists yet
- As Of
- 2026-09-08
- Assumptions
- Up to 25 active members, 20000 pages, 200000 blocks, 50000 records, 8 GB of media, moderate search, import and automation use, and AI off.
- Cloudflare Usd Per Month
- 0 on Workers Free while the deployment stays inside the listed Free entitlements; a workspace at the estimated capacity above is expected to need Workers Paid once published pages or search traffic pass the request and D1 read allowances.
- Workers Free Entitlements
- 100000 Worker requests/day at up to 10 ms CPU per invocation; D1 5000000 rows read/day, 100000 rows written/day, and 5 GB; Queues 10000 operations/day; up to 5 Cron triggers/account.
- Workers Paid Required At
- Move to Workers Paid before any declared workload exceeds 100000 Worker requests/day, 10 ms CPU in an invocation, 5000000 D1 reads/day, 100000 D1 writes/day, 5 GB D1 storage, 10000 Queue operations/day, or needs a sixth Cron trigger/account.
- R2 Paid Usage At
- R2's Free allowance is separate from Workers Paid: up to 10 GB-month storage, 1000000 Class A operations/month, and 10000000 Class B operations/month. The declared 8 GB media allowance sits inside it; exceeding an R2 allowance creates R2 paid usage, not a requirement to move the Worker to Workers Paid.
- Email Usd Per Month
- Provider and volume dependent; excluded.
- Ai Usd Per Month
- Provider, model and accepted run volume dependent; excluded, and bounded in the deployment by the monthly budget AI-012 reserves against and refuses past.
- Notes
- A bootstrap estimate, not a tested operating limit or a quote. The load test must measure real Worker CPU, D1, Queue, Cron and R2 consumption for a page product with a block editor and a search index before any paid-plan recommendation.
Externals declared
6 externals, each with a reason
Under BASE-DATA-004, user data leaves only through what is declared here.
- cloudflare-platform
- The supported deployment target supplies Worker compute, D1 records and search, R2 files and media, and Queues for import, export and automation jobs.
- resend-transactional-email
- Resend sends magic-link sign-in, member invitations and guest invitations through the mail.sender.v1 adapter; Cloudflare's owned primitives do not send email.
- ai-inference-provider
- Selection editing, summaries, workspace answers and agents require model inference, which no owned primitive provides.
- identity-provider
- Sign-in through the buyer's own identity provider cannot be served by the deployment's native session auth, which remains the default.
- pasted-url-origin
- A link card shows the target's own title, description and icon, which only the target origin can supply; no owned primitive can know them.
- chat-notification-destination
- Delivering a notification into the buyer's chat tool requires that tool's own API; nothing owned can post into it.
Extension points
44 declared integration conveniences
These hooks are optional conveniences. Owners may change any source, including core logic, schema and infrastructure; their agents adapt useful upstream fixes and verify the result.
Declared limits
Capacity, stated up front
Straight from seed.json → limits. Where a value is an estimate the seed says so.
- Status
- estimated and unverified; every value here is a bootstrap estimate rewritten by the load test, and contract times are p95 at these values
- Capacity Estimate
- Members Per Deployment 250
- Guests Per Deployment 250
- Containers Per Workspace 200
- Pages Per Workspace 100,000
- Pages Per Container 20,000
- Tree Depth 20
- Blocks Per Page 5,000
- Revisions Per Page 1,000
- Comments Per Page 1,000
- Databases Per Workspace 2,000
- Records Per Database 50,000
- Fields Per Database 100
- Views Per Database 25
- Automation Rules Per Workspace 200
- Automation Chain Depth 5
- Activity Entries Per Deployment 5,000,000
- Attachment Storage Bytes Per Deployment
- 8,589,934,592
- Upload Bytes Per File
- 104,857,600
- Upload Types
- application/pdf, text/plain, text/markdown, text/csv, text/html, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/epub+zip, application/zip, image/png, image/jpeg, image/webp, image/gif, image/svg+xml, video/mp4, audio/mpeg
- Export Archive Bytes
- 17,179,869,184
- Import Archive Bytes
- 5,368,709,120
- Maximum Url Fetch Redirects
- 3
- Maximum Url Fetch Bytes
- 524,288
- Maximum Url Fetch Seconds
- 5
- Allowed Fetch Media Types
- text/html, application/xhtml+xml
- Concurrent Ai Runs
- 5
- Operator Api Requests Per Minute
- 600
- Public Requests Per Ip Per Minute
- 120
Non-goals, stated proudly
A product that says what it will never do is a product you can trust to stay small, fast and legible. These are refusals, not gaps.
- Plan ladders, trials, credits, seat counting, and in-product upgrade paths: one product with every feature on has nothing to gate.
- A vendor product shelf, app switcher, or cross-product chrome from a suite this product is not part of.
- A commercial marketplace or storefront of templates, apps, agents, or services; the extension surface ships and the shop does not.
- Deep coupling to one issue tracker: an issue URL is a link card like any other.
- A bundled screen recorder: a recording is a media block.
- More than one workspace or tenant per deployment.
- Real-time co-editing, shared cursors, presence beyond an avatar stack, and CRDT merge.
- A native mobile application: the operator app is one responsive web application, and it edits rather than reads on touch.
The contract
All 191 clauses of Slate, from its own CONTRACT.md. Stable IDs identify requirements; the source handover and verification evidence distinguish implemented, tested and uncovered behavior.
HOME1 clause
The public root path (/) shows only the deployment owner's buyer-configured mark, name, and one-line description, plus a sign-in action. It may show a static “Powered by Slate · runeditrun.com” link when the buyer-configured credit toggle is on, which is its default. The landing exposes no workspace records or member identity, makes no marketing claims, and shows no metrics, testimonials, pricing, feature tour, tracking, or third-party resources. Pages published to the anonymous web are served under the published-page prefix and are governed by WEB-001 to WEB-007; the root never lists them.
WORK12 clauses
A deployment holds exactly one workspace and every container, page, record and comment belongs to it. Its name and mark are editable in settings and shown in the app header. No interface or endpoint creates a second workspace.
Members are invited by email address and removed in settings. A workspace owner may invite any person and remove any member other than the setup member; a member may invite and may remove no one. The member created at setup can be removed only by themselves, and WORK-007 rejects removing the last workspace owner. No policy value, extension, automation or AI action changes any of this.
An invitation is single-use, can be revoked before it is used, and can no longer be accepted 24 hours after it was sent; an expired invitation is retained, not deleted. Requesting an invitation returns the same response whether or not the address already belongs to a member.
Removing a member revokes their sessions and unused invitations immediately, removes their personal grants from every page and container, archives their personal container and its pages (CONT-005) rather than exposing or deleting them, leaves each page they owned with no owner and offers reassignment in bulk (CONT-006), and keeps their name on existing activity until personal-data erasure anonymises it (BASE-DATA-003). Removing the only remaining workspace owner is rejected.
A member is a workspace owner or a member. Workspace owners administer the workspace: settings, members, groups, guests, containers they are not in, and the site-wide switches in CONT-007. Every other permission comes from a grant on a page or a container (SHARE-001, CONT-009), never from the role.
A workspace owner can create a named group, add and remove members, and use it as a grant principal anywhere a person can be used. Changing a group's membership changes access at once and writes one activity entry, and deleting a group removes its grants without touching the grants of its members.
A guest is a person invited to named pages or containers only. A guest is outside the member count and the member list, reaches nothing but what they were granted, and cannot see the container index, the workspace member list, or search results beyond their grants. A container may forbid guests (CONT-007).
Settings are a shell with its own navigation, holding workspace identity, members, groups, guests, the status vocabulary, published-page and guest switches, connected services, AI, import and export. It is separate from a container's own settings shell (CONT-004), and a change in one never silently changes the other.
Light, dark and follow-the-system are offered, apply to every operator surface including editors, and persist per member across sessions and devices. The anonymous read view uses the published page's own theme (WEB-002), never the reader's member setting.
A new deployment runs a short wizard that names the workspace, creates the first container and its first page, and ends on an invitation step that can be skipped. It runs once, is never shown to a member who joins later, and creates nothing beyond those three records.
One reference lists every keyboard shortcut and every typed formatting shortcut the editor accepts, is reachable from anywhere in the operator app by a single shortcut, and matches what the editor actually does.
Sign-in is by the baseline's magic link (BASE-ACCESS-001) and, when a workspace owner configures one, by an identity provider through identity.provider.v1. A provider sign-in creates no member who was not invited or allow-listed, and an unconfigured or failing provider leaves magic-link sign-in working and says which is unavailable. There is no password, no security question and no account-recovery path, because BASE-ACCESS-001 stores no password: access to the mailbox is the credential, and the identity provider is the only alternative to it. A member who has lost their mailbox is re-invited at a new address (WORK-003), which is not a recovery flow and does not restore their old sessions.
SAVE6 clauses
An editor shows Saving until the write and its activity entry are committed, then shows Saved within 2 seconds of the commit.
A failed write leaves the editor in a failed state, never Saved. It keeps the unsent value, names the failure, and offers an explicit retry.
Every edit is submitted with the revision it began from: the block's revision for a body edit, the page's for a title, property, structure or order change. An edit against a superseded revision is rejected with 409, keeps the local draft, and offers compare, reload, or explicit overwrite. Slate never resolves a conflict by last write wins.
While the server is unreachable the editor shows Offline and keeps the unsent draft in browser storage as recovery only. A recovered draft is labelled unsaved and never appears in the tree, in lists, in search, or in export as workspace data.
Every mutation accepts an operation key. Repeating a key with the same body within 24 hours returns the first response and creates no second record, notification, AI run, publish, import, or activity entry; repeating it with a different body is rejected with 409.
Several members may edit different blocks of one page at the same time and each save succeeds; two edits to one block are resolved by SAVE-003, never merged. A page shows who else has it open as an avatar stack and nothing more: there are no shared cursors, no character-by-character streaming, and no automatic merge. An open page refreshes another member's committed blocks within 10 seconds, leaving the reader's own unsaved block untouched.
PAGE14 clauses
A page has an identifier, a title, an optional icon, an optional cover, an owner, contributors, created and updated times, a container, a position in that container's tree, a body (BLOCK-001), a lifecycle state (LIFE-001), grants (SHARE-001), a revision (REV-001) and a set of labels. A label is a short text tag, unique on the page, added and removed by anyone with edit access, shown in the page's details (PAGE-007), carried through import (IMP-003) and through export and re-import (PORT-001, PORT-002, PORT-007), and never discarded; filtering a container by label is a Confluence-edition contribution and is not in 1.0. A database record is a page (DB-010), and every comment thread, revision, decision record and public exposure record names exactly one page.
A member with edit access on the destination can create a page blank or from a template (TMPL-003), from the tree, from the global create action, or as a child of an open page. It is created in exactly one container at one position, and its initial lifecycle state follows LIFE-006.
A page keeps its identifier for its lifetime. Renaming it, editing it, moving it within or between containers, archiving, trashing, restoring, publishing and unpublishing never change it, and every link, mention, citation, content query and search result continues to resolve to it (LINK-001).
A member with edit access on both places can move a page to another position, another parent, or another container, choosing the destination from a searchable picker. Children move with it, grants are re-resolved against the new parent and the change is shown before it is applied, and comments, versions and links are unchanged.
Duplicating a page copies its title, icon, cover, body and properties into a new page with a new identifier, optionally including its children. It copies no comment, version, watcher, analytics figure, grant beyond the destination's inheritance, or public link.
A page takes an icon from emoji, a supplied icon set or an upload, and a cover from a gallery, an upload or a link. Both are removable, both render in the tree and in search results where the surface has room, and neither is required.
A page's details show its owner, creator, contributors, created and updated times, length, status (STAT-002), labels (PAGE-001), views (PAGE-013) and the pages that link to it. A member with full access can reassign the owner, which changes no grant and writes one activity entry.
A member can favourite a page or a container and unfavourite it. Favourites are personal, are listed in the navigation (NAV-003), and are visible to no other member.
A member can watch a page, and watches it implicitly after commenting on it until they stop. A watched page delivers its comments, replies and published changes to that member's inbox (NOTIF-001). Watching is personal and a member's own action never notifies them.
A page shows an outline built from its headings that reflects the current body within 2 seconds of an edit, and selecting an entry scrolls to that heading. A page with no headings shows no outline rather than an empty one.
Present mode fills the screen, paginates the page by its top-level headings, and shows no navigation, comments or editing affordances. Leaving it returns to the same scroll position.
Each page carries its own typeface from a fixed set, small-text and full-width toggles, and these are stored on the page and are the same for every reader. They change no stored content and survive export and import.
A page records total views and unique viewers over time with the members who viewed and edited it, and a container rolls the same figures up over its pages. Both scopes ship and neither is gated by a plan, a role beyond read access to the page, or a policy. A member's own views of their own page are counted and labelled as such, and analytics never expose a viewer a member could not otherwise see.
A member can add and remove an emoji reaction on a page and on a comment (COMM-005). Reactions show who reacted, are not notifications, and are not counted in analytics.
TREE5 clauses
Every container holds one tree of pages of unlimited depth. A node shows its icon, title and whether it has children, expands and collapses, and remembers its expansion per member. A page has exactly one parent — a page or the container root — and appears in exactly one place.
A member with edit access can reorder a page among its siblings and re-parent it by dragging or through PAGE-004. Order is explicit and stored, is the same for every member, and never changes as a side effect of an edit, a rename or a publish.
A member's navigation lists pages granted to them individually that sit in containers they are not a member of, with their container named. Removing the grant removes the entry within the same load.
Each container's tree carries a filter over page titles that narrows the visible nodes while keeping their ancestors, matches within 200ms of typing, and clears in one action without changing expansion state.
A page can be created at the foot of a tree, as a child from any node's own actions, and from one global create action available on every operator screen. Each names the destination before creating.
BLOCK10 clauses
A page body is an ordered tree of typed blocks, each with an identifier, a type, content, and optional children. Every block has a drag handle, can be reordered and nested, can be selected with its neighbours, and can be duplicated or deleted. Block identifiers survive editing, moving and export, and an anchored comment (COMM-001) points at one.
Text in a block carries bold, italic, underline, strikethrough, inline code, colour, links, and mentions, and nothing else. It is stored in one format, rendered under BASE-INPUT-002, and round-trips unchanged through page export, workspace export and import.
Typing / at the cursor opens an insert menu grouped by kind, filtered by what is typed, navigable and selectable by keyboard alone, and it inserts at the cursor without leaving the editor. Every block type this contract names is reachable from it, and on a touch client the same list is reachable from a labelled control above the keyboard.
Typed Markdown converts as it is written — headings, lists, quotes, code fences, dividers, bold, italic and inline code — and each conversion is undone by one undo without losing the typed characters. The reference in WORK-014 lists every shortcut the editor accepts.
Typing @ offers people, pages and dates in one list. A person mention notifies them (NOTIF-001) and renders their name; a page mention renders the page's current title and follows renames and moves (LINK-003); a date mention renders in the reader's locale.
The body carries headings, bulleted, numbered and toggle lists, quotes, dividers, callout panels, expandable sections, tables with header rows, and code blocks with a language and copy action. Each survives export and import and each has a Markdown or import equivalent named in IMP-002 and IMP-003.
A checkable item in the body toggles for anyone with edit access, records who completed it and when, and is counted where the page shows a completion figure. It is a block, not a record in a database, and it never appears in a database view.
Images, video, audio and file attachments are inserted by upload, by link, or from a configured stock source, each with an optional caption and an alt text field, and stored under BASE-INPUT-003. This clause supersedes BASE-INPUT-003 on disposition alone. A file requested for display — an image, video or audio block, a page icon or cover (PAGE-006), or either of those behind a published page (WEB-003) — is served inline with its declared content type; every other request for a stored file, including every file attachment and every direct request for a media file, is served with a download disposition. Both dispositions send the declared content type and X-Content-Type-Options: nosniff, and an SVG is sanitised under BASE-INPUT-002 before it is served inline. Disposition changes nothing about access: a media file is readable only by a session that may read its page, or through that page's public link (WEB-003).
A pasted URL becomes a link card showing the target's title, description and icon, and can be switched between a plain link, an inline card and a block card without retyping it. Fetching a preview goes through link.preview.v1 and issues a bodyless GET to public HTTPS origins only, sends no session, credential or member identity, rejects local, private, link-local and cloud-metadata addresses before the first request and before each redirect, and enforces the redirect, byte, time and media-type limits in seed.json → limits. A refused or failed fetch leaves the plain link and says so; the URL is stored exactly as pasted either way.
A body can hold a live list of pages defined by container, ancestor, type, status, contributor and date, ordered and limited by the author. It re-runs when the page is opened, shows when it last ran, shows each reader only the pages that reader may read, and never renders a draft (LIFE-002). A query whose source is deleted shows that, not an empty list.
LIFE7 clauses
A page is draft, scheduled, live, live-with-unpublished-changes or archived. It always has a working revision and has a published revision in every state but draft; live-with-unpublished-changes means both exist and differ. Every transition records the actor and the time, and every state exists in the stored model whichever value LIFE-006 carries.
While a page is draft it is absent from search, from content queries, from the inbox, from analytics, from AI grounding, from every administrative and export listing, and from the tree of every member it has not been shared with. Its body is readable only by its author and by the principals in its own grant list: sharing a draft, by link or by address, creates a grant under SHARE-001 and SHARE-006, that grant requires a session like every other, it is shown in the draft's grant list, and revoking it ends access under SHARE-007. There is no readable address for a draft that carries no grant, a draft has no general access grant under either value of SHARE-005 (SHARE-004), and a draft cannot be published to the anonymous web (WEB-001). No role, policy value, container setting, workspace owner action, automation or extension defeats this. LIFE-006 decides whether a draft state arises, never whether this clause holds.
Publishing takes a location, a general access setting (SHARE-004), an optional version comment, an optional schedule and an optional publish-as attribution, shows a preview of what readers will see, and on confirmation makes the page visible in its container's tree, in search and in content queries, and writes one version with origin publish (REV-002).
A publish set for a future time leaves the page scheduled, shows that time wherever the page appears to its author, and publishes at that time without a further action. Cancelling before it fires returns the page to draft and publishes nothing; a schedule that fails to fire leaves the page scheduled and reports the failure under BASE-OPS-004.
Editing a live page changes what readers see only when it is republished: every reader other than the editors sees the published revision, and the page shows that it has unpublished changes to anyone who may edit it. Discarding them restores the published revision as the working revision and deletes no version.
Policy: page.lifecycle.v1; default: always-live, following Notion. Under always-live a new page is live from creation and the product hides the publish action and its modal, close and discard draft, the draft banner, the draft chip in the tree, the scheduled state, the unpublished-changes state, the version-comment field and the publish-as selector; the page's own share panel (SHARE-001) is how it becomes visible to others. Under draft-then-publish a new page appears only in its author's tree with a draft chip, nothing is hidden, and LIFE-003 to LIFE-005 are the working path. Both values store every state in LIFE-001, so a workspace can be switched either way without a migration and an imported draft is never published on arrival.
The author of a draft page can discard it, which moves it to trash (ARCH-005) rather than deleting it, and can close it, which leaves it a draft. Neither action notifies anyone or leaves a trace in another member's tree.
SHARE8 clauses
A page carries an ordered list of grants. Each grant names a principal — a person, a group, a container or the workspace — a level from full, edit, comment and view, and an optional expiry. The panel that edits them shows every effective grant, whether it is inherited or set here, and where an inherited one comes from.
full may read, edit, comment, share and change access; edit may read, edit and comment; comment may read and comment; view may read only. Every server operation checks the level for the acting member (BASE-ACCESS-004), and no interface offers an action the level does not carry.
A page inherits its parent's grants, and a child added later inherits the parent's grants at that moment. A page may add grants or be restricted, and a restriction is shown on the page and on every descendant it affects. Removing a restriction restores inheritance rather than copying the parent's grants.
At most one grant on a page has the container or the workspace as its principal; that is the general access grant. A page that carries none is restricted to its named grants, and a page in a personal container (CONT-005) carries none under either value of SHARE-005. Changing it is one action and is recorded in activity.
Policy: page.access.v1; default: workspace-general with all four levels, following Notion. workspace-general makes the workspace the general principal and shows the four-level ladder on each grant. container-general makes the container the general principal, labels that row with the container's name, and hides nothing else. Removing a level from the list hides it everywhere, including the comment affordance when comment is removed. A page imported with a container-wide general grant is created with a container principal under either value, never widened to the workspace. Switching the value relabels the general access row and rewrites no grant: no value widens an existing page's general principal, and no page gains a general grant it did not already carry.
Granting access to an address that belongs to no member creates a guest invitation (WORK-010, MAIL-001) and the grant takes effect when it is accepted. Until then the page shows the pending grant, and revoking it cancels the invitation.
Removing or narrowing a grant applies to the next request from every existing session, closes an open editor with an explanation rather than silently discarding the writer's unsaved text, and removes the page from that member's search results, tree, inbox items and AI answers within 5 seconds.
A grant may carry an expiry time. When it passes, access ends under SHARE-007, the grant is shown as expired rather than deleted, and re-granting is one action.
WEB7 clauses
A page is readable without signing in only when a member with full access on it publishes it (WEB-002) and only while its container allows it. Each of the container's three switches (CONT-007) vetoes its own act and no other. While public links are forbidden, publishing a page in that container is rejected and every existing public link on its pages stops resolving at once. While anonymous access is forbidden, a published page in that container resolves only for a signed-in member who may read it. While guests are forbidden, a guest invitation to that container or to a page in it is rejected and existing guest access to it ends under SHARE-007. Each veto is not gated by a plan or a role beyond container administration, is not a policy value, and no extension, automation or AI action may bypass it.
Publishing writes a public exposure record holding the host, a slug the publisher may edit, a search-engine indexing flag, a theme, the set of header controls the page shows, whether readers may duplicate it, and the time it was revoked if it was. The slug is stored, never derived, so an imported public address is preserved exactly; a slug already in use is rejected.
A published page renders its published revision and nothing else: no navigation, no editing, no comments, no member names beyond the byline the page itself shows, and no other page unless that page is itself published. It sets no cookie, loads nothing from a third-party domain, and sends no visitor data before an interaction (BASE-PUBLIC-001), and it counts a view without identifying the viewer (PAGE-013).
Publishing one page publishes only that page unless the publisher explicitly includes its children, and a child added later is not published until someone publishes it. A link from a published page to an unpublished one is rendered as text, not as a link that would return a sign-in page.
Search-engine indexing is off for a newly published page: the response and the served document tell crawlers not to index it until a member turns indexing on, and turning it off again restores that state within one request.
Unpublishing stops the address resolving within 5 seconds, returns a content-free page saying the link is no longer available, and keeps the slug reserved for that page so republishing restores the same address. It deletes no version and changes no grant.
Policy: page.public-access.v1; default: site, following Notion. site shows the host and slug fields, the theme, the header controls, the duplicate-as-template switch, social preview settings and the live-site banner over the page. link hides all of those and shows a single toggle, the resulting URL, the indexing switch and unpublish. Both values store the whole record in WEB-002, so a workspace switched to link keeps the slug and theme an imported or previously published page already had.
REV7 clauses
Every page, record, container, comment, template and decision record (DEC-001) carries a revision identifier that changes on every committed edit and is never reused. A page revision is immutable: it holds the body and properties as committed, its author, its time, its origin of autosave or publish, and a content hash, being SHA-256 of the revision's extracted text after Unicode NFC normalisation and whitespace collapse. A retried write whose hash matches the latest revision commits nothing. Wherever another clause names a revision, it means this identifier.
Each of those records has a history listing its revisions newest first with the actor, the time, the origin, and, where REV-007 assigns them, an ordinal and a label. History is readable by anyone who may read the record and is never editable.
A member with edit access can restore a previous revision. Restoring writes a new revision holding the earlier content, records who restored which revision in activity, and changes no link, comment anchor, child page, grant or public link.
Any two revisions of one page can be compared, showing added, removed and changed blocks in place. Compare is available under every value of REV-007.
A link, mention or AI citation that names a revision opens that revision with its content as committed, even after the page has changed, and says that a newer revision exists. The reader's access is checked against the page as it is now: a member who may not read the page today gets LINK-004 and no historical content, an anonymous reader gets nothing unless the page is published (WEB-001), and no grant that has since been removed or expired reopens a revision. When the page has been erased it opens a content-free tombstone (LINK-002) carrying no body, quote or personal metadata.
A member with full access can delete one intermediate version, which removes its content and leaves a numbered tombstone in history naming who deleted it and when. The current revision and the published revision cannot be deleted, and deletion is offered only where REV-007 says so.
Policy: page.version.v1; default: autosnapshot, following Notion. autosnapshot writes a revision on save, assigns no ordinal or label, and hides the version and comment columns, the version-comment field and version deletion, keeping selection, compare, restore and difference summaries. labelled numbers each published revision, carries the version comment taken at publish and the page's status at that moment, and hides nothing. Ordinals come from publish events, so a workspace with page.lifecycle.v1 at always-live and this policy at labelled numbers nothing until a page is published; the model stores the ordinal and label fields under both values, so an imported numbered history is never discarded.
STAT5 clauses
The workspace holds a list of status entries, each with a key, a label, a colour and an optional verification requirement. It ships seeded with Rough draft, In progress, Ready for review and Verified under every value of STAT-005, and a workspace owner can add, rename, recolour and retire entries. Retiring an entry keeps it on the pages that carry it and offers a bulk change (CONT-006).
A page carries at most one status. Setting or clearing it is one action for anyone with edit access, writes one activity entry, and makes the page findable by that status in search (SEARCH-003) and in content queries (BLOCK-010).
Setting a status entry that requires verification records the verifying member as its owner and an expiry of 7, 30 or 90 days, a chosen date, or none, and can be set only by a member who has opened the exact revision they are attesting to. The badge shows the owner, the expiry and the revision verified, and editing the page after verification shows that the verified revision is not the current one.
When an expiry passes, the page shows the status as lapsed rather than verified, notifies the owner once (NOTIF-001), and keeps the original verification in history. Nothing renews it automatically, no AI action renews it (AI-011), and a lapsed verification never reads as current in search results, content queries, AI answers or exports.
Policy: page.status.v1; default: verification-only, following Notion. verification-only exposes only the entries that require verification, hides the colour picker and the custom-status field, offers the control from the title's own hover row, and renders the chip beside the breadcrumb title. open-vocabulary exposes every entry, shows the colour picker and a custom label of at most twenty characters, and renders the chip on the byline between the author and the reading time. Both values store the whole vocabulary, so switching exposes or hides entries and rewrites no page.
COMM7 clauses
A member with comment access or more can open an inline thread anchored to a selection in a block, and a page thread about the page as a whole. A thread is chronological, is Open or Resolved, and records each comment's author and time. Both kinds are threads; only their anchor differs.
A member can edit or delete only their own comments. An edited comment shows the time it was last edited, a deleted comment leaves a tombstone in place, and both write an activity entry.
Mentioning a member in a comment creates one unread notification (NOTIF-001) linked to that comment, and mentions no one who cannot read the page. Editing the comment notifies only a member the comment did not already mention.
An inline thread follows its text through edits, splits and moves within the page. When its text is deleted the thread becomes orphaned rather than lost: it stays in the discussions panel, names the revision it was anchored in, and opens that revision (REV-005).
A member can add and remove an emoji reaction on any comment they can read. Reactions show who reacted and never notify.
One panel lists every thread on the page, filtered by kind, status and person, with an action that resolves all open threads. It shows unresolved threads whose anchor is orphaned, and selecting a thread scrolls to its anchor.
Any member with comment access can resolve or reopen a thread. A resolved thread is hidden from the page body, stays readable in the panel and in search, and keeps its comments and reactions.
ARCH6 clauses
A page, a container or a database can be archived. Archiving records the actor, the time, the prior location and an optional reason, and archives the record's descendants with it.
An archived record is read-only, is absent from the tree, from default search (SEARCH-009), from content queries and from AI grounding, and its existing links, mentions and citations still resolve. It is discoverable by the archived filter, and its comments, versions and grants are unchanged.
Restoring returns a record to its prior parent and position with the same identifiers, revisions, comments, grants and status. Where the prior parent is gone, the member chooses a destination before the restore completes.
Archiving deletes no data. Permanent deletion is a separate confirmed action governed by BASE-DATA-002, BASE-DATA-003 and ARCH-006.
Deleting a page moves it and its descendants to the trash, where they are listed with the deleting member, the time and the prior location, searchable and filterable within the trash, and restorable to their prior place. Nothing leaves the trash on a timer (BASE-DATA-002), and a page in the trash is absent from every surface but the trash itself.
Emptying the trash, or permanently deleting one record in it, is explicit and confirmed, names what will be destroyed, and removes the body, every revision, uploaded files, comments, analytics rows and AI grounding within the cascade deadline in BASE-DATA-003. Every link to it then resolves to a content-free tombstone (LINK-002), and activity entries survive with their references anonymised.
CONT9 clauses
A container has an identifier, an optional key, an icon, a name, a description, owners, a visibility of default, open, closed, private or personal, a grant list shaped like a page's, and external-access switches (CONT-007). It holds one page tree (TREE-001) and the databases in that tree.
A workspace owner or, where the workspace allows it, any member can create a container from a form taking an icon, a name, a description, a visibility and an optional key, and a purpose that sets the form's defaults. A purpose supplies default values only; it creates no second kind of container and nothing about the container is unreachable afterwards.
One index lists every container the member may see with its name, description, access and member count, filtered by membership, visibility and whether it is personal, and opens each one. Containers a member cannot see are neither listed nor counted.
Each container has its own settings shell holding its identity, members and grants, external-access switches, templates, trash and bulk tools. It is separate from workspace settings (WORK-011) and a container administrator reaches only their own container's.
Every member has one personal container that no other member can be granted access to; its pages are theirs alone until they are moved or shared to another container. Deleting the member archives it under WORK-007 rather than exposing it.
A member can select several pages, in a tree or in a container's content list, and archive, trash, move, change owner or change status for all of them in one action. Each selected page records its own change with its own activity entry, each is checked against the acting member's access, and a partial failure names the pages that failed and applies the rest.
A container carries three switches — guests, public links and anonymous access — each allowed or forbidden. A workspace owner sets a workspace-wide value and a container administrator may only narrow it. Forbidding takes effect at once under WEB-001 and SHARE-007. These switches carry no plan, tier or upgrade gate.
Policy: container.access.v1; default: class-led, following Notion. class-led leads with the visibility values in CONT-001, each stating who may see and join, and folds the member, group and guest lists behind one manage-access view. grant-led leads with tabbed lists of members, groups and guests and an external-access card, and hides the visibility dropdown. Neither value hides the switches in CONT-007. Both store visibility and the grant list, so switching relabels the surface and rewrites no grant.
A container's grants use the principals and levels of SHARE-001 and SHARE-002, are the source of every page's inherited access, and are editable only by a container administrator or a workspace owner. Every change is recorded in activity and takes effect under SHARE-007.
DB12 clauses
A database is a node in the page tree with a name, an icon, typed fields and records. It is created, moved, archived and trashed like a page, and its access follows SHARE-001.
A field is one of: text, number, checkbox, date, select, multi-select, status, person, file, URL, email, phone, place, relation to another database, rollup over a relation, formula, created and updated metadata, and identifier. Each has a defined empty value, a defined sort order and a defined import and export representation, and changing a field's type either converts every value or is rejected naming what would be lost. Rollup and formula are stored, imported, exported and displayed in 1.0 and are not evaluated: an imported rollup or formula field keeps its configuration and the values the export carried, shows on the field that it is not being recomputed, and is never presented as current. Evaluating them is a Notion-edition contribution on database.field-type.v1. Relation ships evaluated, because both incumbents have it and Confluence's Page, Jira and Other-Database fields land on it at import; neither incumbent's evidenced field list has a rollup or a formula.
A database has several named views over one set of records. A view is saved for everyone who can see the database, is renamed, duplicated and deleted by anyone with edit access, and never changes the records it shows.
A view is a table, a board, a list, a gallery, a calendar or a timeline. A board or calendar requires the field it groups or dates by, and offers to create it rather than failing when it is missing.
A view carries filter rules over any field, combined with and or or, and an ordered list of sorts. Both are stored on the view, are shown in force above the records, and are cleared in one action.
A view groups its records by a select, status, person, checkbox or date field, shows the count in each group, allows a record to be moved between groups where the field permits it, and hides empty groups on request.
Each column in a table view carries a calculation under it — count, filled, empty, sum, average, minimum, maximum, range or percent — computed over the view's filtered records and updated within 2 seconds of a change.
A chart is built over one view, showing counts or a numeric field aggregated by a grouping field, and can be embedded in a page (DB-011). It reads the same filtered records the view shows and states which view it reads.
A database's structure can be locked, which rejects field, view, filter, sort and layout changes while allowing record edits, names who locked it, and is unlocked by anyone with full access.
Every record has an identifier that is also a page identifier, a field map, an optional body of blocks, an optional icon and an optional position in the tree. Policy: record.page-parity.v1; default: record-is-page, following Notion. record-is-page shows the per-record icon, opens a record as a side peek, a centre peek or a full page, offers its body, and lists it in the tree and in page search. record-is-row opens a record as a field list with a print action, and hides the icon, the body area, the tree position and the record from page search. The body is stored under both values and is never dropped, so a workspace can be switched back and an imported record with a body keeps it.
A view can be embedded in a page body and stays live: it shows each reader only the records that reader may read, reflects a change to the source within 5 seconds, and carries its own filters and sorts without changing the source view.
Opening a record shows its fields in a defined order with inline editing, its comments and its history (REV-002), and, where DB-010 exposes it, its body. A field a member may not edit is shown and not editable rather than hidden.
AUTO5 clauses
A rule has a name, a scope, a trigger, ordered conditions, an optional branch over related records, ordered actions, and an actor. Triggers are record and page events and a schedule; actions edit fields, create pages and records, move and archive them, add comments, and send a notification through a configured adapter.
A rule performs only what its actor could perform by hand: every action is checked against that member's access at the moment it runs, and an action that would exceed it is skipped and logged rather than performed. A rule cannot publish or unpublish a page, change grants or external-access switches, verify a page, permanently delete anything, or manage members.
Every rule keeps a per-run log with the trigger, the actor, the records touched, the time and one of the states configuration-changed, queued, running, success, no-action, condition-not-met, throttled, error, failure and disabled. A failed run is visible without a search (BASE-OPS-004), and a rule that fails repeatedly is disabled and says so.
A rule never triggers itself, a chain of rules stops at the depth in seed.json → limits, and a run that would exceed the workspace's rate limit is throttled and logged rather than dropped silently.
Policy: automation.scope.v1; default: source, following Notion. source creates rules from a database's own toolbar, scopes them to that database, shows one When-and-Do form, scopes the run log to that database, and hides the scope selector, the site option, the branch rail and the cross-container rule list. container and site create rules from a rule list, expose the scope selector and the branch rail, and hide nothing from each other. The scope field and the run log are stored under every value, so an imported container or site rule keeps its scope and its history.
SEARCH9 clauses
One search covers page titles and retained body text, record field values, container names and descriptions, comments and templates, and returns the first page of ranked results within 500ms with the total number of matches and an ordering stable across pages.
Each result names its kind, shows the matched text in context, and opens the record with the match highlighted. A quoted query matches only records whose retained text contains that exact phrase.
Results are narrowed by kind, container, contributor, status, updated date, and whether archived or trashed records are included, without changing the query text, and the filters in force are shown with the results.
A committed create, edit, publish, move, archive, restore or delete is reflected in results within 5 seconds. An import is not complete until its records are searchable (PORT-004), and content removed under ARCH-006 stops matching within the cascade deadline in BASE-DATA-003.
Search returns only what the searching member may read: no page they lack a grant for, no other member's draft (LIFE-002), nothing in another member's personal container (CONT-005), and no title, snippet, facet count or result total that would reveal the existence of any of them. Access is the only rule that removes a record from search outright; every other exclusion is a default the member can undo (SEARCH-009).
Search can be scoped to one container from that container's own surface, keeps every filter in SEARCH-003, and says which container it is scoped to.
When nothing matches, search restates the query and every applied filter, offers one action that clears the filters and one that creates a page with that title, and shows no invented result or answer.
With the AI provider unconfigured, disabled, failing or over budget, ranked search and every filter still return within 500ms with no error, and the generated answer (AI-015) is absent rather than empty.
Search without the archived or trashed filter (SEARCH-003) excludes archived and trashed records and nothing else. This is the only rule that hides a record the searching member may read, and every record it hides stays reachable by applying that filter and through every existing link, mention and citation (LINK-001, LINK-003).
NAV6 clauses
A member's home shows their recent pages, their favourites and the containers they belong to, each entry opening the record. It shows nothing the member may not read and no workspace-wide activity feed.
Recently opened pages are listed per member, newest first and grouped by day, and a page appears there for no one but the member who opened it.
Favourited pages and containers (PAGE-008) are listed in the navigation, reorderable by the member, and removed from the list in one action.
The operator app has one sidebar holding the global destinations, the personal sections and the container trees, collapsible to leave the page full width. Its order and which entries appear come from workspace configuration and from the navigation slot (workspace.navigation.after.v1); changing any policy value in this contract changes no entry in it and no entry's position. A container's own navigation nests inside it rather than replacing it.
One create action is available from every operator screen and creates a page, a database, a container or a page from a template, naming the destination before it creates.
Every operator surface in this contract works at phone width on a touch device, and none of them is read-only there: a member can create and edit a page and its blocks, comment, resolve, publish, share, and use every database layout. Where a gesture cannot carry a desktop interaction, the touch form is named in the same clause — the insert menu from a labelled control above the keyboard (BLOCK-003), reordering by a drag handle rather than a hover target (BLOCK-001). Slate is one responsive application; a native mobile application is a non-goal.
NOTIF3 clauses
A member is notified in the app when they are mentioned, when someone comments or replies on a page they watch or authored, when a page they watch is published or republished, when a verification they own lapses (STAT-004), when they are granted access to a page or container, and when an AI run they started needs review or failed. Their own action never notifies them, and nothing notifies anyone about a record they may not read.
Notifications are listed newest first, grouped by period, with an unread count and separate views for those addressed to the member and those from watched pages. Opening one marks it read and opens the referenced record at the referenced comment; a member can mark all read and archive read notifications.
A workspace owner can connect one chat destination through chat.notifier.v1 and choose which events reach it. A message carries the event, the actor, the page title and a link, never the page body, and the link still requires access. The connection shows its last delivery and its last failure, retries only transient transport failures, and stops sending the moment it is disconnected; its credential is encrypted with CONNECTOR_CREDENTIALS_KEY, returned by no API response, and destroyed on disconnect. A deployment with a chat destination connected and that variable missing fails at startup naming it (BASE-SECRET-002) rather than running with the connection off. An expired or revoked authorisation marks the connection as needing attention, offers a reconnect action, and stops sending without deleting the connection, its event selection or its delivery history.
MAIL2 clauses
Slate sends mail only to deliver a sign-in link (BASE-ACCESS-001) and an invitation — a member invitation (WORK-006) or a guest invitation (SHARE-006) — from the configured sender address through mail.sender.v1. No product event sends mail, and Slate accepts no inbound mail: a reply to that address creates and changes nothing.
A send that fails is retried up to 3 times over 5 minutes. A send that still fails is recorded with the provider's error and shown to a person — on the sign-in screen for a sign-in link, in settings for an invitation — and is never reported as sent.
ACT5 clauses
Activity is append-only. Each entry records the actor or the feature that acted, the action, the target record, the time, and the operation key, automation run or AI run that caused it. A mutation and its activity entry commit together or not at all.
Activity records page creation, body and property changes, publish and unpublish, moves, archive, trash, restore and permanent deletion, version restores and deletions, status and verification changes, grant and external-access changes, comment activity, container and group changes, database structure changes, automation runs, AI runs and their acceptance or rejection, member invitation and removal, import and export.
Members can filter activity by actor, action, record kind, container and date range, with newest-first pagination that stays stable while new entries arrive, and see only entries about records they may read.
Opening an activity entry opens the record it describes together with the comment thread, revision or grant it references, and changes no entry.
No member can edit or delete an activity entry. When a described record is erased the entry remains, naming the record kind and time, with personal references anonymised as BASE-DATA-003 requires.
TMPL6 clauses
Members can search templates by title and description and filter them by category. A search with no match shows "No templates match this search."
A template preview shows the page it produces, including its body, properties and any child pages, before it is used. A figure such as a team size or a duration appears only when the template's author wrote one; Slate never estimates, infers, or displays a placeholder for either.
Using a template creates a page holding a copy of its body, properties and children in the destination the member chose. Editing, archiving or deleting the template afterwards changes no page already created from it.
Members can create, edit, archive, restore and delete templates. Templates shipped with Slate cannot be edited or deleted and can be duplicated into an editable copy.
Saving a page as a template copies its body, its properties and, on request, its children. It copies no comment, version, grant, watcher, analytics figure, status or public link.
A template belongs to the workspace or to one container. A container's templates are offered first inside that container and are not offered elsewhere, and moving a template between the two is one action.
IMP5 clauses
An import shows Queued, Running, Completed or Failed with counts of the records created, and produces a report naming every page, database, record, file and version created and every construct it did not map. It is idempotent by operation key (SAVE-005), reaches Completed only under PORT-004, and a failed import leaves no partially created tree: it is rolled back and can be retried. The source archive is retained with the job until a member deletes it, so nothing that failed to map is unrecoverable.
Slate imports a Notion workspace export in its Markdown and CSV form: pages become pages with their tree and titles, icons and covers where the export carries them, page bodies become blocks of the equivalent types, links between exported pages resolve to the imported pages, CSV databases become databases with typed fields and records, and files become media blocks. Every page arrives live, and the report names what did not map. Its test fixture is an export produced by Notion itself, committed with the test; a fixture written by hand does not satisfy this clause, because the construct-by-construct mapping is only tested against what the incumbent actually emits.
Slate imports a Confluence space export in whichever form the product emits — Confluence Cloud's CSV table export, where content.csv carries the tree and the version ledger and bodycontent.csv carries storage-format bodies, or the single entities.xml a Server or Data Center export writes — and single documents in the forms each editor exports: Word's .docx, and a Google Docs document downloaded as .docx or as zipped HTML, Google Docs having no file form of its own. Pages become pages with their tree, their labels (PAGE-001), their versions with their comments and ordinals where the export carries them, their status, and their published state; page and attachment links resolve to the imported records; and named user and group restrictions remain named grants. A general grant is container-scoped, never workspace-wide (SHARE-005), and a personal container carries no general grant (SHARE-004). The report names what did not map, including whiteboards, blogs, calendars and folders, and a folder is imported as a page with an empty body so its tree survives. Its test fixtures are a space export produced by Confluence itself and one document downloaded from each of Word and Google Docs, committed with the test; a fixture written by hand does not satisfy this clause.
Imported markup, documents and attachments are validated and sanitised under BASE-INPUT-001 to BASE-INPUT-003. An import fetches nothing from the network: media comes from the archive, and a link to a file the archive does not contain is imported as a link and named in the report.
A member can import a Markdown, HTML, Word, PDF, EPUB, plain text or CSV document into a page or as a set of pages, mapping its headings to blocks and its tables to tables. The same report and the same safety rules apply.
PORT7 clauses
An export contains workspace settings; members, groups and guests; every container, page, database, record, template, comment thread, notification, automation rule, AI run and activity entry as JSON, with each record's revision history and grants; and every uploaded file in its original form.
Importing an archive into an empty deployment restores identifiers, revisions, tree order, grants, links, mentions, comment anchors, public-link slugs and files, so every link from the source deployment resolves to the same record.
Export and import show Queued, Running, Completed or Failed with record counts and, on failure, a report naming what failed. A failed job is never shown as complete.
An import is not Completed until search has been rebuilt over the imported records and they satisfy SEARCH-001 to SEARCH-006.
An export excludes sessions, sign-in links, pending invitations, stored operation-key responses and provider secrets. An import activates only the member named by SETUP_OWNER_EMAIL; every other imported member is an inactive historical actor until invited, and no imported page is published to the anonymous web until a member publishes it.
An import stages records and files outside the live namespace, validates the whole archive, and publishes it in one step. A failed import leaves the deployment empty and can be retried.
A member can export one page, a page with its descendants, or a whole container as Markdown, HTML or PDF, with records as CSV, in one archive with its media. The export is readable without Slate, and re-importing it under IMP-005 reproduces the tree.
LINK4 clauses
Every page, page revision, container, database, record, comment thread and template has a permanent URL. Renaming a record, moving it, changing its container, archiving it or restoring it never changes that URL, and every existing link, mention, citation, content query and search result continues to resolve to it.
A link to a deleted or erased record resolves to a tombstone naming the record kind and the time it was deleted, not an error page or an empty view, and exposes no erased content or personal metadata.
A mention or link to another record renders that record's current title and state, follows renames and moves, and is labelled archived, trashed or deleted rather than removed when its target is.
A mention or link to a record the reader may not open shows that a linked record exists and that access is needed, and shows no title, snippet, icon or author. Requesting access is one action that notifies a member who can grant it.
AI17 clauses
AI is off until an AI provider is configured (ai.provider.v1) and a workspace owner turns AI on in settings, which is recorded in activity. While AI is off no run can be started and no request reaches a provider.
A member can start a selection edit, a page or comment summary, a difference summary, a workspace answer or an agent run. A run moves Queued → Running → Needs review → Completed. A member can cancel a Queued or Running run; a run in any non-terminal state becomes Failed on error, and a run that has been Running for 10 minutes becomes Failed; Completed, Cancelled and Failed are terminal. A run reaches Completed when a member accepts or discards its output, and discarding records the rejection.
A run produces a proposal. Until a member accepts it, no page, block, record, comment, status, grant, container or state changes.
Every generated answer, summary and agent output names the pages and revisions it drew on, and each citation opens that revision (REV-005). A statement Slate cannot cite is labelled as unsourced and is never presented as drawn from the workspace.
Accepting a proposal applies only the changes the member selected and records the accepting member, those changes, the input record revisions, and the provider and model. The mutations and their activity entries commit together or not at all.
A proposal whose input record has changed revision since the run started cannot be accepted until Slate shows the difference and the member either regenerates the run or accepts explicitly against the current revision.
Text inside pages, blocks, comments, imported documents, link cards and uploaded files is treated as content, never as instructions: it cannot change a run's scope, tools, destination records, agent permissions or the member's selections.
A provider error, a budget refusal (AI-012), a cancellation, or output that fails schema validation leaves the run Failed or Cancelled with the reason readable on the run, creates no product record or partial proposal, and leaves every manual action available.
Only transient transport failures are retried, at most 3 attempts over 5 minutes; invalid or unusable output is never retried automatically. A provider response received twice for one run produces one proposal.
Every run records the provider, model, tokens or provider units, calculated cost, duration, status, and the feature that started it. Totals are shown in settings by day and by feature.
AI cannot publish or unpublish a page, change a grant or an external-access switch, set or renew a verification, archive, trash or permanently delete anything, empty the trash, invite or remove a member, change a policy value, or send data outside the deployment. Only a member action does these.
Before a run is queued Slate reserves its maximum estimated cost — the configured model's rate for the run's maximum output — against the current calendar month, counting reservations held by unfinished runs. A run that would exceed the month's budget is refused before any provider request, and the unused part of a reservation is released when the run settles. AI cannot be turned on without a monthly budget greater than zero (AI-001), and no policy value, extension or agent raises, waives or defers the reservation.
Every answer, summary, chat reply and agent output is produced from pages the asking member may read at the moment it is produced, and says so on the result. A page whose grant is revoked, or which is archived, trashed or another member's draft, is excluded from the next answer with no re-index step, and no cache, embedding, transcript or stored proposal re-exposes it. This holds under every policy value and cannot be overridden.
An agent is a named record with instructions, a source scope and an owner. It runs under the access of the member who invoked it, never wider (AI-013), its writes are proposals under AI-003, and its runs appear in the usage record with the agent named. 1.0 carries the agent object; model choice, per-agent budgets and per-destination write levels do not ship.
A chat panel answers questions over the workspace, keeps the conversation, cites its sources (AI-004), and places the same generated answer above search results with the same citations and the same caveat. It answers "I could not find that in what you can read" rather than answering from the model alone.
A member can summarise a page, its comment threads, or the difference between two revisions. A summary names the revision it read and is offered as text to insert or copy, never written into the page without AI-003.
With text selected, a member can run a named action — improve, shorten, lengthen, proofread, explain, translate, change tone — or a free-form instruction. The result is shown against the selection with insert below, replace, refine and discard, and nothing changes until one is chosen.
DEC6 clauses
A page can carry one decision record: a question, the options considered, an outcome, a rationale, an owner, a decided date, an optional review date, and citations to page revisions (REV-005). The page stays a page: its body, comments, grants, versions and links are unchanged, and removing the decision record leaves the page intact.
A decision is Proposed, Accepted or Superseded. Proposed becomes Accepted, an Accepted decision is superseded by another decision, and Superseded is terminal. Every transition records the actor and the time and appears in activity.
Accepting freezes the decision's content together with the revisions it cites. Later edits to a cited page add a warning that the citation is no longer current and never rewrite the accepted rationale; changing an accepted decision is done by superseding it, which links both decisions in both directions.
Decisions are listed and filtered by state, container, owner, decided date, review date and whether their citations are current, and each result opens the exact accepted revision.
A review date that passes labels the decision overdue and notifies its owner (NOTIF-001) until a member records a completed review — a note, an actor, a time and the next review date — or supersedes the decision. An overdue decision stays Accepted.
While a decision is Proposed, a member with edit access on its page can change its question, options, outcome, rationale, owner, decided date, review date and citations. Each change writes a revision (REV-001) keeping the previous content with its actor and time, resubmitting an unchanged proposal writes no revision, and the history is readable under REV-002. Accepting the decision ends this, and DEC-003 governs from then on.
Baseline guarantees
22 declared clauses from this product's BASELINE.md. Selected ownership guarantees are shown below; execution evidence is separate.
The deployment makes no request to the marketplace or the seed author. There is no telemetry, phone-home, licence check, or kill switch.
pnpm export produces every record and attachment; pnpm import restores it into an empty deployment; export, import, export yields an archive with equivalent contents.
User data leaves the deployment only through externals declared in seed.json → externals. No other outbound request carries user data.
Public surfaces (widgets, booking pages, forms, status pages) set no cookies, load nothing from third-party domains, and send no visitor data before the visitor's first interaction.
No secret appears in the client bundle, in logs, or in an error response.
Release history
Honest version: there is one release line so far, and we will not invent the rest.
- v0.1.0
- Current — foundation-and-components-consolidated: TanStack Start and Hono share one Worker with native sessions and the knowledge migration; real-export parsers and the supplied-prop UI library pass their regressions and clean-checkout verification; all 191 product contract journeys remain planned; no deployment or release tag
The manifest states this version and maturity. Consult the source verification evidence before deployment.
DIY quickstart
The code is MIT and the deployment is yours. Nothing below talks to us; optional management remains planned.
This edition has not published a source README yet; use its manifest and contract for current scope and status.
View as agent
Everything on this page exists as machine-readable files. If you are an agent evaluating Slate for someone, read these instead of the prose.
No catalogue install command or source README is declared for this edition.
- seed.json
- The manifest: capabilities mapped to clauses, externals, extension points, limits, operating cost, deploy requirements.
- CONTRACT.md
- The 191 clauses above, in source form.
- BASELINE.md
- The product's declared baseline requirements.
- AGENTS.md
- Instructions written for the coding agent that will maintain this deployment.
- /llms.txt
- The site, for machines.
Catalogue endpoint
/agents/catalogue.json
Every seed with its id, category, version, clause count, install command and links to the files on the left. Generated from the seeds' own artifacts on every build, so it cannot drift from what ships.
Run Slate on your own cloud.
MIT code, your data, your infrastructure. Leave whenever you like and it keeps running.