CLOCK

Advance Clock

Advance the billing clock to trigger subscription renewals and invoice creation.

Payment Behavior

Set what happens when the engine attempts to charge each payment method.

SAO Core

Schema, Machine, Instance, Outcome. Every resource type is a compiled state machine. Transitions are validated, outcomes are immutable.

Billing Engine

Advance the clock, find due subscriptions, create invoices, attempt payment. The full billing cycle in pure functions.

Payment Simulator

Configure per-card behavior: succeed, decline, or auth failure. See how the billing engine handles each scenario.

The dashboard above is composed from five Gutenberg block types. Each block is a top-level entry in the page spec, self-positioning via position or view fields. The shell boots the JS runtime; the other blocks are pure configuration the runtime interprets.

Dashboard Shell
dashboard_shell

The layout container. Defines the sidebar or topbar chrome, the list of views (with labels and routing keys), and a JS bundle that boots the runtime.

Clock Display
clock_display

Renders the current simulated (or real) time. Declares its position within the shell. The value comes from the runtime, not the spec.

Clock Advance
clock_advance

Buttons that advance the billing clock by configurable increments. Declares which view it belongs to. Each step has a label and a day count.

Payment Behavior
payment_behavior

Per-payment-method controls that set what happens on charge attempts: succeed, decline, or auth failure. Declares its view and the available options with visual tones.

View Detail
Part of DashboardViewSpec

Not a standalone block — a property of views in the shell. Defines what sections appear when a user clicks into a resource (e.g. customer detail showing subs, invoices, PMs).

At compile time, Gutenberg serializes each block's config into the HTML (via data attributes or inline JSON). At runtime, the shell's JS bundle boots, discovers the other blocks in the DOM, reads their config, and mounts them into the declared positions. The blocks carry no JS of their own — they are pure configuration that the runtime interprets.

YAML Spec Gutenberg Compile Shell JS Boot Mount + Render
BlockFieldExampleMeaning
clock_displaypositionnav_footerBottom of the sidebar nav
clock_advanceviewcontrolsInside the Controls view
payment_behaviorviewcontrolsInside the Controls view
Local Mode (Today)

The shell's JS bundle creates a Database and BillingEngine in memory. Clock advance calls engine.advanceClock(). Payment behavior calls engine.payments.setBehavior(). All state is local. Full re-render on every action.

Streaming Mode (Future)

The shell connects to a Durable Object via WebSocket or SSE. Clock advance sends POST /api/clock/advance. Outcomes stream back and update the UI incrementally. The specs don't change — only the bundle changes.

The critical design invariant: specs describe what the UI shows and what controls are available. They never describe how state is computed or where it lives. The runtime is the only moving part between local simulation and production streaming.

Top-level blocks, not nested

Each interactive block is a top-level entry in the page spec. Self-positioning via position or view fields. Avoids deep YAML nesting. Each block is independently authorable and lintable.

Shell absorbs view nav

The navigation sidebar is part of the shell spec's views array, not a separate block. Nav is intrinsic to the shell's layout — separating it creates a reference coupling without adding flexibility.

Detail is a view property

Click-to-detail is a detail field on DashboardViewSpec, not a standalone block. It describes what happens when a resource is selected — which sub-resources to show, whether to show alerts.

Specs describe structure, not state

No block spec contains data values (clock time, resource counts, payment method IDs). The spec says show a clock here in date format. The runtime fills in the actual value. This is what makes the spec portable between local simulation and streaming production.