Intellectual Frontiers

Scaffold Bare Metal Feature Defaults

Use this skill when the user wants to choose or write down the feature defaults for a new AI-native application in the Bare Metal Software style - sign-in, roles, tenancy, audit trail, files, search, reports, backups, jobs, and the rest of the two-dozen…

This skill is Labor as Code™ for one chapter of Bare Metal Software: "The Features Every App Needs, and One Choice for Each." Read that chapter for the reasoning behind each default — this skill only executes the method (fill in the sheet, commit it to the spec) and does not carry the argument for why any one default is right. It also does not decide anything the book leaves to the reader: which features actually apply to this project, whether the project is enterprise or prosumer, whether Rust is acceptable, and whether any "change it only when" condition has actually been met are always the user's calls.

The book's own fieldwork prompt for this chapter is "Fill In the Feature Sheet" — this skill is that prompt turned into a repeatable procedure, with the book's own default table as the ground truth instead of something reconstructed from memory each time.

Before running

Confirm these with the user before producing anything, in plain conversation. Do not guess any of them:

  1. Enterprise or prosumer. An enterprise app is one hosted system many organizations use (tenancy, per-customer SQLite files, Stripe subscriptions, single sign-on eventually). A prosumer app is one a single serious user installs and runs on their own machine (one data folder, a one-time purchase, self-updating signed binary). Get this right first — a dozen of the defaults below split on it.
  2. What this application actually is — the real product, not a generic CRUD app. From that, and only from that, decide with the user which features in the catalog below are actually in scope. Do not run every row against every project: an internal tool with no payment, no mobile app, and no field devices has no business filling in Billing, Mobile release pipelines, or Edge device rows. Draft a candidate in-scope list and have the user confirm or edit it before step 1.
  3. Is Rust acceptable? The book's default stack is one Rust binary for the reasons its preface gives (single-file program, compiler safety, no runtime to install, a small container image). If the user's organization has ruled Rust out, the fallback is a JavaScript platform that compiles to a single binary (Deno or Bun) — note this once, up front, and do not re-litigate it feature by feature.
  4. Does this project handle regulated or sensitive data (health information, payment data, other regulated PII)? Several defaults below (virus scanning, business associate agreements, the runtime model's data-handling default) change meaningfully if so, and the answer has to come from the user, not be inferred from the product description.

Step 1: Confirm the in-scope feature list

Using the user's answers above, propose which rows from the table below actually apply to this project. Typical exclusions: Billing (no paid product yet), Offline/sync (no mobile or edge component), the mobile and edge device rows (web-only product). Get explicit confirmation before moving on — an unconfirmed scope list produces a spec full of defaults for features the project doesn't have.

Step 2: Walk the feature table

This is the book's own table, one row per in-scope feature. For each row, state the default and its reversal condition exactly as written below — do not paraphrase them into something vaguer, and do not substitute a different default because it "feels more modern." The whole point of the chapter is that these are settled choices, not a menu.

FeatureDefaultChange it only when
Sign-inPasskeys + email link, mature auth library, session rows in SQLiteAn enterprise customer requires single sign-on; add OpenID Connect only
RolesFour roles (owner, admin, member, viewer) in one table; one permission functionA paying customer needs a rule the four roles cannot express
StateThe lowest level of the State Complexity Ladder that fits each kind of state; files firstQueries, concurrency, or operations need the next level, measured
TenantsOne SQLite file per customerThousands of customers or cross-customer queries, measured
AuditAppend-only table written in the same transaction as every changeA regulator requires storage your own admins cannot touch
FilesOn disk by content hash; row in SQLite; object store for backup onlyMore than one server must serve the same files
SearchSQLite FTS5Millions of documents and a relevance team
ReportsNightly Parquet export + DuckDB; CSV/Excel downloadNumbers must be minutes old, not hours
PDFsPrint-styled HTML rendered by a headless browserA fixed official form is required
ImportsStaging table, validate, error workbook backSource is a live system, not a file
JobsJobs table + worker threads in the same programMore than one server must share the queue
SchedulesSchedules table read by the program’s worker threadsA job must run while the program is stopped; the host scheduler starts a one-off container
Live updatesServer-sent eventsBrowser must send many messages per second
CacheNoneA measured slow query; in-memory map only
EmailOutbox table + provider over SMTP/HTTP; inbound via provider webhookProvider pricing changes the business
NotificationsTable + badge + daily digest; urgent kinds immediateUsers ask for different timing
APIJSON over HTTPS at /api/v1; hashed API keys; OpenAPI generated from the specA partner requires OAuth
WebhooksSubscriptions table, HMAC-signed, six retries over a dayNever
BillingStripe Checkout + portal; entitlements table; signed license file (prosumer)Selling where Stripe does not serve
Settings/flagsOne settings table with scopesNever
BackupsLitestream + nightly copies + monthly automatic restore drillNever
Logs/healthJSON lines to standard output, kept by the container runtime; /health; /status pageCustomer ops team requires OpenTelemetry
Front doorInside the program: rustls TLS, ACME certificates, rate and size limits, timeoutsA second host arrives; a load balancer takes over TLS and limits
UpdatesNew image replaces the container + forward-only migrations; self-update (prosumer)Never
Offline/syncDevice SQLite + change log + one sync endpoint; conflicts keptNever
LanguagesEnglish only; strings table when a customer pays for a secondA paying customer needs another language
Admin/admin pages in the same programNever
Runtime modelPlain HTTPS, schema-checked output, no write access, eval set, audit every callNo vendor will sign the agreement you need; run a model on your own host
Identifiers, time, moneyUUIDv7; UTC ISO 8601 text; whole centsNever
UploadsAllow-list by first bytes; size limit at the front door; no virus scanA customer contract requires scanning
HostDebian stable, container runtime, keys-only SSH, three ports, hardened containerNever
BuildLock file, pinned toolchain, vendored dependencies, static signed binary in a minimal imageNever
DeploymentContainer-first: one image, one Compose file, one volume; scripts in the repository build and deploy itMore hosts than one Compose file per host can manage, measured
Signing (prosumer)Windows code signing and macOS notarization from release oneNever
Third-party scriptsNone on any page, everNever

Step 3: Test every "never" and every condition against today's evidence

For each in-scope row, ask the user one question: does the "change it only when" condition already hold, today, with evidence?

  • If no (the common case), the default stands. Move on.
  • If yes, do not silently swap in the alternative. Stop and ask the user to state the measurement that moved them (a load number, a contract clause, a customer count) — this is the book's own rule: "write down the measurement that moved you." A default changed without a stated measurement is exactly the failure mode this chapter exists to prevent, so do not proceed past this point on the user's assertion alone; get the actual number or document.
  • Every row that escalates gets one short file in the project's decisions/ folder: the feature, the default, the alternative chosen, and the measurement. Draft this file's contents but do not invent a measurement that wasn't given to you.

Step 4: Write the spec section

Turn the confirmed table (defaults plus any escalated rows) into the project's own specification document, one sentence per feature, in the plain-language style the book itself uses for the table — this is meant to be read by both a human and a harness, so keep each line a single settled statement of the default:

Sign-in: passkeys, plus a sign-in link by email for devices without
passkeys. Session is a random token in a cookie with a matching row
in SQLite; an admin can revoke by deleting the row.

Roles: four roles (owner, admin, member, viewer) in one table. All
permission checks go through one function.

[... one line per confirmed feature ...]

Step 5: Scaffold the repository shape, if asked

Only if the user wants the actual folder structure created (not every user does — some just want the spec written), lay out the shape the book describes as "the repository the harness works in":

mkdir -p spec constitutional-tests ops decisions
  • spec/ — the feature-defaults document from Step 4, plus one file per boundary as the project grows.
  • constitutional-tests/ — the tests, models, and proofs the harness may never weaken to make its own change pass.
  • ops/ — the Dockerfile, the Compose file, and the deploy, backup, restore, and check scripts, once they exist.
  • decisions/ — one short file per default the project changed from the book's own default, and the measurement that moved it (Step 3).

Do not scaffold application code from this skill. This skill's job ends at a written, confirmed spec and (optionally) the empty folder shape a harness will fill in from that spec.

The check that catches this chapter's own failure mode

Before calling the sheet done, reread every row that is NOT the book's default. For each one, confirm there is a real, stated, measured condition attached to it — not "it seemed safer," not "we might need it later," not "that's how we did it at my last company." The chapter opens with the warning this check exists to catch: "Add one [vendor or service] per feature and a small app is carrying twenty dependencies before it has served its first customer." A feature sheet with several unjustified deviations from the defaults is that failure happening in real time. Flag every such row back to the user before treating the sheet as finished.