Rails target profile
Status: Evidence-backed direction. This page owns the first Rails target's shared conventions and routes to each subject's lowering.
The Rails target lowers a reviewed Foundation Plan into an ordinary Rails application with PostgreSQL and Hotwire. Generated Rails source is the inspectable home for business behavior, workflows, authorization, and correctable validation. Database constraints back up storage invariants and concurrent writes. The Compiler composes a fixed Core, derived Capabilities, and an application-specific Domain. A profile release pins runtimes and conventions, so a newer default does not silently change a reviewed build. A database-owned behavior or framework replacement needs an owner-approved exception. Each subject's lowering has its own page, listed under Current directions. The support inventory (repository-only) records what the Compiler generates. A Plan's reviewed GapSet lists what that Plan's Foundation omits.
On this page
- What a profile release may need to identify
- Architectural default
- Foundation composition
- Current directions
- Rails guardrails
- Admission of derived behavior
- Alternatives and open questions
- Code and checks
What a profile release may need to identify
A released profile identifies:
- compatible Foundation Plan format versions;
- the Rails, Ruby, PostgreSQL, frontend, and toolchain versions it supports;
- fixed conventions the Compiler may derive without project judgment;
- behavior the Plan can activate and the rules used to derive it;
- choices that Foundation Plan authoring may surface;
- verification and generated-app quality rules; and
- evidence and compatibility for each material lowering.
The profile helps propose a Foundation Plan. A reviewed snapshot can pin the profile release so a newer default does not silently change that build.
Platform-only rendering choices do not mutate an existing Rails profile. The current iOS direction gives SF Symbol, bundle-identity, and Xcode-value transforms their own immutable lowering release. The current Compiler selects that lowering and records it with the generated native project. Shared Rails behavior and constraints remain part of the Rails profile.
Architectural default
The first profile uses:
- a centralized Rails application layer;
- PostgreSQL as the relational database;
- server-rendered HTML with Hotwire for the primary web interface;
- ordinary framework source rather than a First Draft runtime; and
- a single generated repository containing the output surfaces derived for that application.
This is a strong first hypothesis, not a claim that a centralized Rails backend always wins. Generated Rails source is the primary, inspectable home for business decisions, workflows, authorization, and correctable validation. Database constraints and other PostgreSQL features enforce atomic storage invariants, race safety, query semantics, and referential integrity; they are not the sole implementation of behavior that a user or maintainer must understand, invoke, authorize, or correct.
For Domain lifecycle and business behavior, start with pinned Rails APIs and healthy common gems. Search the ecosystem and read the exact framework or gem source before generating a wrapper, scheduler, or substitute API. Active Record owns the inspectable behavior. PostgreSQL constraints may backstop that path, but database-originated mutations, triggers, RLS-owned authorization, and generated business values need a separately documented owner exception. Decision 0024 (repository-only) records this boundary and the current bounded Reference-deletion realization.
A database projection and its Rails projection must derive from the same application fact and have agreement tests. RLS may provide defense in depth only behind the same generated authorization policy, not become a second policy source. Triggers do not own workflows or external side effects. When a database rejection represents an error a user can reasonably correct, generated Rails behavior should reject it through the ordinary application error path, with the database remaining the final concurrent-write backstop.
Rails has two roles in First Draft:
- It is the first output architecture.
- Its conventions, ecosystem, and mature applications are a principal corpus for discovering recurring product semantics and implementation failures.
The second role does not turn the Plan's semantic application definition into a Rails API. Rails' own doctrine emphasizes a coherent default stack while preserving substitutions; First Draft applies the same spirit at a more application-specific layer.
Foundation composition
The Rails Compiler composes:
- Core: schema-independent Rails setup and universal generation rules;
- derived Capabilities: accounts, attachments, mail, native clients, and other cross-cutting behavior; and
- Domain: application-specific models, constraints, policies, workflows, Scaffold routes and views, and tests.
firstdraft/foundation-rails-core is the current Core reference and extraction source. It is not a Foundation or a
permanent template authority. Dunbar150 and Shinar are hand-authored reference applications with different Rails
versions and UI systems. Their behavior is evidence until the Compiler can emit and verify equivalent results.
The Rails Capability catalog (repository-only) tracks behavior that can derive from Plan meaning and the current evidence for each direction. Rails Foundation quality (repository-only) describes the outcomes that every generated app, or an app with a particular risk surface, should satisfy.
Rails Core composition describes how the Compiler composes the pinned Core with renderer output. The application shell describes the routes, Home, legal pages, web manifest, and bookmark icons that every application receives.
Current directions
Each subject below has its own page. The Plan owner states what the subject means; the page states how this profile realizes it in Rails.
| Subject | Page | Plan owner |
|---|---|---|
| Model, constant, route, helper, and table names | Generated names | Data model |
| Identity, schema, migrations, indexes, and seeds | Domain storage | Data model |
| Field kinds, defaults, and modifiers | Fields | Field catalog |
| References, Associations, and deletion | Associations | References |
| Predicates, Orderings, and ordered finders | Scopes and ordering | Queries |
| Validations and database constraints | Data integrity | Validations |
| Accounts and Rodauth | Authentication | Accounts (repository-only) |
| Policies and Action Policy | Authorization | Policies (repository-only) |
| Scaffolds, forms, pagination, preload, and returns | Scaffolds | Screens (repository-only) |
| State Machines and AASM | State transitions | State Machines (repository-only) |
| Routes, Home, manifest, icons, and mail host | Application shell | Foundation Plan |
| Core pin, paths, dependencies, app documents | Core composition | Compiler |
| Generated RSpec suite and coverage disclosures | Generated tests | None |
| Components, theme, and Appearance | Generated UI | Foundation Plan |
| iPhone and Android clients | Native capability | Foundation Plan |
| Derived Capabilities | Capability catalog (repository-only) | Foundation (repository-only) |
| Quality, operations, and security | Foundation quality (repository-only) | None |
These shared directions have no page of their own:
- Runtime: Rails 8.1, Ruby 4.0, and PostgreSQL. Core and Dunbar150 implement this direction. The
rails-sketch/2026-09-bookmark-assetsprofile pins Ruby 4.0.5 and Rails, Active Record, and Active Support 8.1.3.1; the complete profile still needs explicit pins for its other runtime and toolchain inputs. - Content Security Policy: Core uses Rails 8.1.3.1's commented initializer without an active policy. The quality owner (repository-only) records the tradeoff and continuation boundary.
- Web UI: ERB, Turbo, Stimulus, and Tailwind, with Basecoat Vega for HTML components and selected shadcn
base-vegaReact islands mounted through Turbo Mount. The generated UI owner defines shared components, theme ownership, agent continuation, maintenance, and the qualification boundary. - UI source: MIT-licensed Basecoat and shadcn source plus original First Draft components. Emitted
licenses/retains notices and copied-source provenance. Accessibility proof belongs to the qualified components and states; a permissive license or upstream component name does not establish it. - First Draft UI: Rails Blocks Pro may be used only in First-Draft-owned surfaces. Pro source never enters generated or extractable output.
- Background work: use Active Job with a supported queue when application behavior needs it. Retry, idempotency, and diagnostics are capability outcomes.
- Notifications: keep application-owned recipient occurrences separate from channel delivery. Noticed is a
candidate orchestrator, Action Push Native is a candidate APNs/FCM adapter, and
web-pushis a separate browser adapter. None is an unconditional dependency; see Notifications (repository-only). - Error monitoring: use a tested adapter with an owner-visible verification path. Rollbar, Skylight, or another vendor remains replaceable.
- Abuse controls: activate them for public and authenticated input surfaces. Rate limits, spam handling, and challenge choices remain slice-specific.
- Accessibility: use semantic components, keyboard and focus behavior, automated checks, and manual or device gates. Reference coverage is not generated proof.
- Internationalization: emit translation-ready user-visible behavior from the first Foundation. Exact lint and testing policy still needs a slice.
- Deployment: use an owner-controlled, replaceable adapter. Render is a working reference path, not a permanent product requirement.
- Native: treat the cross-tree Hotwire Native Capability as provisional. The iOS and Android support inventory rows (repository-only) each compile one public index. Native Account self-navigation and session restoration remain a partial Account gap; see Accounts (repository-only) and native capability.
Current directions should not be promoted merely because a dependency is already installed in the First Draft service or Core reference. The next concrete application decides which slice needs proof.
Rails guardrails
- Prefer conventional inspectable Rails source over a generated inner framework.
- Emit ordinary public Rails declarations and preserve their pinned framework behavior. Add wrappers or depend on framework-internal AST only when generated-runtime proof shows ordinary Rails violates an authored semantic guarantee; surprising conventional writer behavior alone is not an admission rule.
- Do not use
default_scopeto hide lifecycle, tenancy, or ordering behavior. - Do not infer destructive cascade behavior when the Schema is silent; see decision note 0010 (repository-only).
- Derive authorization scopes and per-record decisions from one allowing Policy Expression, then test their equivalence.
- Account for behavior that bulk writes can bypass.
- Put reliable data rules in the database when that is the clearest enforcement; keep user-facing failures useful.
- Do not install dormant vendors merely because a future application might need them.
- Do not ship browser-accessible production consoles or hidden credentials.
- Use substantial editable drafts adapted from the attributed Basecamp policies for Core's
/termsand/privacy. The consumed Core includes these drafts and their application-owned completion guidance inDEPLOY.md. Keep the visible draft notice and bracketed unknown operator, contact, provider, and retention details. The owner completes them against the application's actual practices before inviting real users. Do not infer an operator, jurisdiction, or privacy practice, or treat signup acceptance as proof of legal readiness. Retain the source and CC BY 4.0 notices when adapting the policy text. - A generated off-canvas drawer or overlay that presents modally needs a real
<dialog>or equivalent tested modal behavior: initial focus moves inside; focus remains contained; Escape and an explicit close control dismiss it; background content is inert; and focus returns to the opener. A checkbox may toggle CSS state but does not provide modal semantics. Permanently visible, nonmodal sidebars are exempt. - Test modal open, keyboard traversal, Escape, explicit close, and focus return. Static accessibility scans do not prove those interactions. See the recovered interface research (repository-only).
- Keep conditional dependencies and source provenance inspectable.
- Every consumer that derives profile-specific names or output must require the exact target and profile it implements.
Admission of derived behavior
A candidate behavior becomes part of the profile after an end-to-end slice exercises:
- product-language authoring, Foundation Plan validation, and an exact relevance rule or trigger;
- any genuinely material Foundation Plan choice and user review;
- a declared owner among Core, derived output, target adapter, and owner prerequisite;
- deterministic Rails lowering, its fixed profile consequences, and derived external prerequisites;
- interactions with other activated behavior;
- positive, denial, malformed-input, failure, retry, and interaction behavior that the claim covers;
- fresh generation followed by clean-workspace whole-application verification;
- generated setup, operations, coverage reporting, and repository guidance, with an owner-visible verification path for external services; and
- continuation by the user's agent without First Draft.
The admission test answers three questions explicitly:
- Would generating this behavior substantially reduce repeated continuation work or predictable defects?
- Is the trigger more precise than “many apps have it”?
- Can the Compiler prove a coherent result across storage, model APIs, routes, Scaffold views, operations, and tests?
A released profile proves every outcome it claims to realize. Proof exercises the observable boundary: the protected route, unavailable dependency, failed job, denied file, restore path, keyboard interaction, or delivered message. Installation, configuration, or a passing static scan alone is not behavioral proof of a claimed safeguard. An unproved safeguard remains a gap. A pre-alpha Compiler may still emit a conventional partial when the generated application stays coherent, the reviewed GapSet names the unfinished consequences, and the output does not claim the missing safeguard.
Common gems and application censuses (repository-only) nominate recurring needs, and a popular gem may provide the best lowering. They do not preselect the serialized concept or permanent library, or decide whether a concept is Core, Capability, Domain, a Field, a target adapter, or post-compilation work.
Alternatives and open questions
Revise the profile when a generated application exposes a repeated continuation failure, a dependency adds more ceiling than leverage, Rails changes an important convention, or controlled target evidence favors another stack.
Code and checks
The support inventory (repository-only) records which probed subject kinds the Compiler generates and routes each unprobed kind to its owner, and the evidence index records runtime observations. The machine reference (repository-only) names the current Analyzer and Compiler releases, accepted Plan format, target profile, and API contract.
- The Capability catalog (repository-only) owns derived behavior and its trigger, consequence, and proof boundaries.
- Foundation quality (repository-only) owns universal, triggered, and operational outcomes.
Target-specific code lives under FoundationPlan::RailsTarget. Do not introduce FoundationPlan::Targets::Rails;
its final constant would compete lexically with the host application's top-level ::Rails constant.