Skip to content

Guide Store Files

Kris edited this page Apr 2, 2026 · 1 revision

Store Files

Store files provide file-backed repositories — YAML files that automatically seed and optionally persist repository data. Place a .store file alongside your .aro source files, and its contents become available as a repository before your application starts.

Quick Start

Create a YAML file with the .store extension:

# products.store
- id: p1
  name: Widget
  price: 9.99
- id: p2
  name: Gadget
  price: 24.99
- id: p3
  name: Gizmo
  price: 14.99

The repository is ready to use — no loading or importing needed:

(Application-Start: My Shop) {
    Retrieve the <products> from the <products-repository>.
    Compute the <count: length> from <products>.
    Log <count> to the <console>.  (* Output: 3 *)

    Retrieve the <widget> from the <products-repository> where <id> is "p1".
    Extract the <name> from the <widget: name>.
    Log <name> to the <console>.  (* Output: Widget *)

    Return an <OK: status> for the <startup>.
}

Naming Convention

The filename determines the repository name by appending -repository:

File Repository
users.store users-repository
config.store config-repository
products.store products-repository
order-items.store order-items-repository

File Format

Store files use YAML — consistent with aro.yaml and plugin.yaml. Each top-level list entry becomes a repository item:

# Each entry should have an "id" field for identity-based operations
- id: admin
  name: Admin User
  role: admin
  email: admin@example.com
- id: guest
  name: Guest User
  role: viewer

If an entry doesn't have an id field, ARO generates a UUID automatically.

Read-Only vs Writable

Read-Only (Default)

By default, .store files are read-only seed data. Runtime Store and Delete operations modify the in-memory repository but never touch the file on disk.

This is the right choice for:

  • Reference data (countries, categories, product catalogs)
  • Default configuration
  • Secrets and API keys (add to .gitignore)

Writable Stores

To make a store writable — meaning runtime changes persist back to the file — set the POSIX other-write permission bit:

chmod o+w sessions.store

When the o+w bit is set, ARO:

  1. Seeds the repository from the file at startup
  2. Monitors Store and Delete operations on that repository
  3. Debounces changes (1-second window) to batch rapid mutations
  4. Writes changes atomically via a temporary file and rename
  5. Flushes all dirty stores on graceful shutdown (SIGINT/SIGTERM)
# Create a writable store for session data
touch sessions.store
chmod o+w sessions.store
(createSession: Session API) {
    Extract the <data> from the <request: body>.
    Store the <session> with <data> into the <sessions-repository>.
    (* This Store will be persisted back to sessions.store *)
    Return a <Created: status> with <session>.
}

Checking Permissions

ls -la *.store
# -rw-r--r--  products.store    (read-only: o-w)
# -rw-r--rw-  sessions.store    (writable: o+w)

Behavior Summary

Aspect Read-Only Writable
Load timing Before Application-Start Before Application-Start
Read access Normal Retrieve Normal Retrieve
Store/Delete In-memory only In-memory + persisted to file
File on disk Never modified Updated on flush
Observers Fire normally Fire normally
Missing file Repository starts empty Repository starts empty; file created on first flush
aro build Embedded as read-only resource Build error

Crash Behavior

Mode What happens on crash
Read-only No risk — file is never modified
Writable At most ~1 second of changes lost (debounce window)

All writable stores flush during graceful shutdown. If the process is killed with SIGKILL or crashes, only changes within the last debounce window are lost.

Build Restrictions

aro build rejects writable store files. A compiled binary cannot write back to embedded resources.

# This will fail:
chmod o+w sessions.store
aro build ./MyApp
# Error: Writable store files cannot be used in compiled binaries.
#   - sessions.store has o+w permission set
# Hint: Remove world-write permission (chmod o-w sessions.store) to embed as read-only data.

# Fix: make read-only before building
chmod o-w sessions.store
aro build ./MyApp  # Works

Read-only .store files are embedded as seed data in compiled binaries.

Application Structure

MyApp/
├── openapi.yaml         # OpenAPI contract
├── main.aro             # Application-Start
├── handlers.aro         # HTTP handlers
├── products.store       # Read-only: product catalog
├── config.store         # Read-only: application config
└── sessions.store       # Writable: persisted session data (chmod o+w)

Use Cases

Reference Data

# countries.store
- id: US
  name: United States
  currency: USD
- id: DE
  name: Germany
  currency: EUR
- id: JP
  name: Japan
  currency: JPY

Application Configuration

# config.store
- id: max-retries
  value: 3
- id: timeout-seconds
  value: 30
- id: feature-dark-mode
  value: true
(Application-Start: My App) {
    Retrieve the <timeout-config> from the <config-repository> where <id> is "timeout-seconds".
    Extract the <timeout> from the <timeout-config: value>.
    Configure the <http-client: timeout> with <timeout>.
    (* ... *)
}

Secrets (gitignored)

# secrets.store (add to .gitignore!)
- id: api-key
  value: sk-abc123...
- id: db-url
  value: postgres://user:pass@host:5432/db

Simple Persistence

# Make writable for runtime persistence
touch cart.store
chmod o+w cart.store
(addToCart: Cart API) {
    Extract the <item> from the <request: body>.
    Store the <item> into the <cart-repository>.
    Return a <Created: status> with <item>.
}

Interaction with Repository Features

Store files work seamlessly with all existing repository features:

  • Repository Observers fire for seeded entries (one created event per entry at startup)
  • TTL and maxSize can be configured normally via Configure action
  • Filtered retrieval works with where <field> is <value> on seeded data
  • Index-based access (:first, :last, :0) works on seeded data

Next Steps

Clone this wiki locally