Architecture

graph LR
    browser[Browser] --> asset[asset-adapter-htmx]
    browser --> booking[booking-adapter-htmx]
    asset --> assetContract[asset-contract]
    booking --> bookingContract[booking-contract]
    assetImpl[asset-impl-timescale] --> assetContract
    bookingImpl[booking-impl-timescale] --> bookingContract
    assetImpl --> db[(TimescaleDB)]
    bookingImpl --> db

The slices

examples/skills-only-app/
crates/asset-contract/contractEquipment models, policy descriptor, service port
crates/asset-impl-timescale/implementationEquipment service, repository, migration
crates/asset-adapter-htmx/adapterCatalog pages and staff forms
crates/booking-contract/contractReservation models, interval validation, action ports
crates/booking-impl-timescale/implementationTransitions, constraint mapping, migration
crates/booking-adapter-htmx/adapterReservation forms and views
web/compositionWires both slices into one host

Why the constraint matters

The booking rule — no overlapping approved or checked-out intervals for one item — cannot be enforced by a check-then-insert: two requests can pass the check at the same time. The implementation therefore pairs the service rules with a PostgreSQL exclusion constraint, and maps the constraint violation back to a domain error the form can show. The database is the authority; the service is the friendly face on top of it.