Chapter 27: Sessions, Forms, Auth, And Passwords

Part IV: MVC, Data, Auth, Forms, and AI

Why this chapter matters

Forms and sessions are where web apps meet user identity. This chapter teaches the flow without hiding password and session safety behind magic.

What you will build

You will build the logic for a local login flow: form maps, schema validation, credential normalization, password hashing and verification, session maps, CSRF checks, and route guards. The runnable example is a command-line harness so it can validate the auth/form behavior without starting a server or logging secrets.

Concepts in plain English

A form submits user input. A session remembers a user across requests. Password handling must hash, verify, and avoid logging secrets.

The chapter uses these concepts:

Vocabulary and commands

Primary coverage: sessions, auth package helpers, forms package helpers, password_hash, and password_verify.

Guided example

Open examples/learn/27-auth-forms/login_flow. Its manifest imports the local first-party auth and forms packages by path:

code[dependencies.auth]
path = ".ricochet/packages/auth"

[dependencies.forms]
path = ".ricochet/packages/forms"

Run the harness:

coderco run examples/learn/27-auth-forms/login_flow/auth_flow.rco

The first section demonstrates the core password words without printing the hash:

code"Long unique passphrase 2026" password_hash value rawHash var
"Long unique passphrase 2026" $rawHash password_verify value println

For application flows, prefer the auth package wrapper so password policy and credential normalization stay in one place:

code"ada@example.com" "Long unique passphrase 2026" auth_password_hash value storedHash var
" ADA@Example.COM " "Long unique passphrase 2026" "ada@example.com" $storedHash auth_credentials_verify login var
$login "authenticated" at println

auth_password_hash validates policy before calling password_hash. auth_credentials_verify normalizes the submitted credential before comparing it with the stored credential and hash.

Session helpers work with ordinary maps:

code"ada" "csrf-token-123" auth_session_for_user session var
$session auth_user_present
$session "csrf-token-123" auth_csrf_valid
$session "/login" auth_route_guard

The route guard returns a map with ok, redirect, and reason. That shape is easy for controllers to inspect before returning a view or redirect.

Form helpers build field maps and schema-shaped validation results:

code"email" "ada@example.com" form_field emailField var
$emailField "value" at form_required

form_schema
  "email" "string" form_required_field
  "password" "string" form_required_field
schema var

formData map
$formData "email" " ada@example.com " auth_credential_normalize put drop
$formData "password" "Long unique passphrase 2026" put drop
$formData $schema form_schema_validate validForm var

The harness prints only booleans and policy names:

codeCore password verify:true
Auth login authenticated:true
Session user present:true
CSRF valid:true
Route guard ok:true
Password storage:argon2id
Field required:true
Form valid:true
Empty form valid:false
Cookie same_site:Lax

How to read the example

Read the MVC example in layers. First identify the route or command that enters the app. Then find the controller action. Then follow the data into the response, view, model, or database boundary. Each layer is still ordinary Ricochet: values first, words second, and explicit results at boundaries.

Try it

Change the submitted password in the auth_credentials_verify call and rerun the harness. The result should keep ok true for the verification operation itself, set authenticated to false, and report an invalid-credentials reason.

To move this logic into MVC controllers, bind declared args such as ( email password session ctx -> Response ), validate the form, verify the credentials, then write the session map only after authentication succeeds.

Check your understanding

Common mistakes

Safety notes

The example does not print password hashes, session cookies, or CSRF tokens. The literal passphrase is a local learning fixture, not an application secret. Do not log submitted credentials, stored hashes, session cookies, or CSRF tokens in real apps.

Production guidance

Production auth should document password policy, session lifetime, cookie settings, CSRF policy, secret handling, reset/recovery flows, lockout/rate-limit policy, audit logging, and deployment assumptions. The scaffold login loop is a copyable local beta starting point, not a complete production auth system.

What you know now

You know where form validation, credential normalization, password hashing, CSRF checks, route guards, and session maps fit in a Ricochet MVC login flow.

Next step

Continue to Chapter 28: AI Capabilities And The AI Package.