Open decisions and debatable changes
A running list of things that need Kevin's call or a second opinion. Newest at the top of each section. Items move to the roadmap or the spec once decided.
Decisions needed
- OPEN QUESTION: a dedicated import format for design systems made in Claude. Brand → Import brand reads a design system exported as W3C design tokens (DTCG JSON) or CSS custom properties through its Design tokens source, and Figma variables with their modes (theming.md). The export format of a design system made in Claude is not confirmed, so no reader guesses one. Needed: the format (or a sample export), whether it carries component styles that should become block styles, and whether it should be a fourth source or detected inside Design tokens.
- Shared brands: locking a part resets the children's overrides of it. When a parent locks a part a child had overridden, the child's override is dropped (published and drafted) and the part follows the parent; unlocking it later does not bring the child's old values back. Keeping the override dormant would need the child's own values stored apart from its effective brand. Also open: a site created later starts with an empty brand profile (or its parent's when it inherits); should a new site copy the default site's voice instead?
- Brand import: logo rules have no field. Logo rules from a PDF guide (clear space, minimum size, do and don't) are listed as notes because the brand has no field for them; add one?
- Brand import: voice rows drafted. Decided 2026-11-07: the brand profile is per site (migration 0041 copied the instance-wide one to every site) and has a draft like the rest of the brand, so applied voice rows land in the brand draft and reach the AI tasks only when a person publishes.
PUT /api/brandstill writes the published profile directly and keeps a draft's voice in step. - Brand import: unapplied imports kept 24 hours. An import waits for review in
brand_import(logo uploads under<dataDir>/brand-imports/) and is pruned afterBRAND_IMPORT_TTL_HOURS(24) on the next import. Long enough? - Page builder: a keyboard path for adding and moving blocks. Puck 0.24 drags blocks with the pointer only (it registers no keyboard sensor), so from the keyboard a block can be selected in the Outline, edited, duplicated and deleted, but not added or moved (upstream report, finding 4). Options: wait for Puck; or add our own controls through the overrides: an Add block menu in the header that inserts after the selected block, and Move up and Move down on the block's action bar. Neither is built.
- Registry four-eyes review: second reviewer. Decided 2026-11-07: turn
REGISTRY_FOUR_EYES=1on for spillwaycms.com once a second reviewer account exists (approve refuses the version's publisher and its namespace maintainers with403 four_eyes). Still open: who the second reviewer is. - Hosting plans. Decided on 2026-11-05 in the "Spillway hosting plans on Accorbis" document: three plans (Site $49, Campus $249, Enterprise $1,499), one $0.10/GB overage rule, Auto with a $49 floor and a hard cap, one price worldwide, R2 as the default store, one Accorbis-owned Cloudflare zone, email support included with priority support as a paid add-on, HA Postgres as a recommended choice at install on Campus, uptime credits on Pantheon's Elite schedule, 30% education and nonprofit discount, pay 10 months get 12, migration fee by size, AI on Accorbis keys with fair use then credits. Per site for Site and Campus; Enterprise is one multisite instance with 10 sites included and more by quote. Decided 2026-11-07: declining HA does not lower the Campus price; one Campus price includes it.
Debatable changes already made (revert if disagreed)
- Kevin's decisions of 2026-11-07 (the "Spillway decisions for Kevin" document, all agreed):
- Security reports go through GitHub's private vulnerability reporting, with
security@spillwaycms.comas the email alternative; conduct reports go toconduct@spillwaycms.com, forwarding to two people at KWALL. v0.1.0 is tagged after those addresses and the brand-token fix landed. - Release tags are pushed by Kevin (this session's git access cannot push tags); merges happen when Kevin says so in the conversation.
- Trusted modules on spillwaycms.com are reviewed by KWALL maintainers within 5 business days; no paid fast-track until there is a queue worth paying to skip.
- Registry sign-in adds email magic links for publishers who are not on GitHub; Google sign-in is skipped for now. Not built yet.
- Organizations keep both rules as built (the namespace wins over package ownership; a plain member publishes only when named a maintainer) and stay free until organizations ask for more; billing is revisited after launch.
- The importer keeps landing in a workstream by default, and keeps AI on by default with the estimate shown before it is spent (built in #18).
- The public
/brandpage is off by default andnoindexwhen on (built in #14). - The page builder's accessibility is fixed on our side, with the issue text for Puck in
docs/dev/upstream/puck-accessibility.md(built in #19).
- Security reports go through GitHub's private vulnerability reporting, with
- Page builder on phones: the real builder, not a notice. At 390 px the builder now works in Puck's phone layout (the panels open from the rail at the bottom); the header wraps to two rows and its actions become icons with their names kept for screen readers. The alternative was a "The page builder needs a wider screen" notice with a link back to the editor below a set width. Chosen because the phone layout passes the accessibility crawl and quick fixes (a typo, a style) are worth having on a phone; dragging blocks there is still awkward.
- Importer AI usage: decided, on by default with an estimate. Decided 2026-11-07 (Kevin): AI stays on by default when a provider is configured, and the estimated AI calls and tokens, with the share of the monthly token cap, are shown before the crawl starts (wizard,
POST /api/imports/estimate,spillway import) and again, measured, before the classification spends them. Each job can turn it off (Use AI for type proposals,--no-ai,options.useAi: false); above the remaining cap the wizard asks for an explicit confirmation and the cap enforcement is unchanged. Reading the code corrected the premise: the type proposals are one call per classification (two with the retry) carrying every cluster, not one call per cluster, and no other importer step uses AI. Pricing is not shown because the AI layer meters tokens only (importer.md). - First release: v0.1.0. Decided 2026-11-06 (Kevin left it to us): nothing was ever published as 0.1.0, so the first public release is v0.1.0 with everything folded in. The Unreleased notes are folded into one
[0.1.0]entry; the tag is pushed by hand asdocs/dev/releases.mddescribes, sincepnpm releaserefuses a version equal to the current one and is for every release after. - Repository and image names: kwall-llc. Decided 2026-11-06: the code stays at
kwall-llc/spillway-cms, so the release image isghcr.io/kwall-llc/spillway-cms(the release workflow names it after the repository) and the docs, the fleet's default image and the links say so. - npm: the
@spillway-cmsscope. Decided 2026-11-06: Kevin created thespillway-cmsorganization on npmjs.com, so the packages are@spillway-cms/shared,blocks,sdk,client,astroandnext(and the private workspace packages follow the same scope). Add anNPM_TOKENrepository secret (an automation token with publish rights on the org) and the release workflow publishes the MIT packages with provenance.coreandfleet(AGPL) ship as the image, not on npm. - Auto plan: Redis step. Decided 2026-11-06: Auto may delete the Redis add-on after the site has run cleanly on the in-process cache for the step's dwell time, and recreates it with the same plan and region on restore. The cache is disposable, so no data is lost; every other deletion stays forbidden.
- Cost model object store. Decided 2026-11-06: R2 is the default and the cost model uses its rates ($0.015/GB-month, zero egress). It is cheaper and allowed through Cloudflare's CDN under its terms; Tigris stays a per-site option for customers who want one Fly invoice.
- Backups and key files. Decided 2026-11-06: backups must restore completely, so they carry the instance's key files, form uploads and installed modules. Without
BACKUP_ENCRYPTION_KEYthe run is flagged and the System tab and/status.jsonwarn; the fleet sets the key on provisioned sites. - Importer off-site redirects: decided, drop by default. (G-18) Source redirects whose target is another host are left out of the landing, counted in
summary.redirectsDroppedand noted;offsiteRedirects: 'keep'(wizard checkbox,--keep-offsite-redirects) lands them. Alternative was keeping them with only the audit row. - Registry smoke load in the worker. (G-19) Done: the sandbox worker compiles the Wasm and checks the ABI; the main thread only reads the memory limits from the header. Nothing to decide; listed so the review item has a home.
- Shared saved views: managers share, a person's own default wins. Personal views stay user preferences (
views:<table>); shared views are rows of their own (shared_view, migration 0036) for everyone on a site or chosen roles, written with the newviews.sharepermission (manager and admin). A person's own default beats a shared default; a shared view for named roles beats one for everyone. Alternatives: let editors share too, or let a shared default override personal ones. - Kit dependencies: built as proposed.
requires: { kits, modules, core }inkit.json, resolved recursively at install from the bundled kits and the registry (kits.md). The bundled kits declare none; spillwaycms.com installs its website kit (inkwall-llc/spillwaycms.com) and the bundleddocskit as two steps rather than one depending on the other.
- Importer home page. The imported site's
/lands at/homebecause the setup wizard's home page already holds/. Alternative: replace the starter home page when the owner asks. Current:/homeplus a note in the report. - Importer menus. Crawled navigation lands as
import-mainandimport-footermenus so nothing overwrites the site's menus; the owner swaps them in. Alternative: replacemainwhen the site is empty. - Importer created types. Only the title field is required on types the importer creates (an import cannot promise every field is filled). Fine, or require the body too?
- Page cap semantics. The cap counts fetched plus failed pages; assets and redirects do not count.
registry.publishis granted to every role including viewer so anyone with an account on spillwaycms.com can publish; review and namespaces limit abuse. Alternative: a separate "publisher" role.- Registry pages on the public site are cached for at most 60 seconds and evicted on every registry mutation.
- Theme = a kit with
kind: "theme"and at least one screenshot, not a separate package format. - Registry client fetches now pass the SSRF guard; a registry on a private network needs
SPILLWAY_ALLOW_PRIVATE_URLS=1. - Module tarballs from the registry are capped at 20 MB.
- Catch-all pages: a page whose last path segment is
any(for example/registry/any) renders every unmatched path below its parent. Used for package and publisher pages; a reserved word in paths as a result. - The docs site body is generated from the repository Markdown at build time; there is no Markdown field on the
doctype.
Not verified against real services
Fly.io provisioning, Okta and Entra SAML and OIDC, GitHub OAuth (fake only), HubSpot, SMTP, the four AI providers, Meilisearch, Tigris and R2. Each needs credentials and a short live run; see docs/dev/roadmap.md.
Spillway 0.1.0 · Edit this page on GitHub