AI asks. Staff confirm.
A resort concierge with an AI front end. The AI can request things on your behalf — but resort staff confirm before anything happens. The AI gets a backend; the humans keep the authority. That's the whole point.
The permissions are the app. This is the whole data model — schema.ts, the first of the app's three files (its import line, not shown, brings these names in from "create-dillo/schema"):
// The schema the live backend serves today (span2/live-schemas filing, re-verified at deploy).
export default schema({
Audit: table({
action: string().max(80),
authorization: string().max(200),
guestId: relation.user(),
principalId: string().max(160),
principalType: string().max(40),
requestId: string().max(200),
resourceId: string().max(200),
}).permissions({ view: owner, edit: nobody }),
Conversation: table({
guest: relation.user(),
resort: relation.team(),
role: string().max(20),
stay: relation('Stay'),
text: string().max(1000),
}).permissions({ view: members, edit: roles('admin', 'owner') }),
Menu: table({
content: file().accept('application/pdf').maxBytes(1048576),
resort: relation.team(),
title: string().max(120),
}).permissions({ view: members, edit: roles('admin', 'owner') }),
Request: table({
details: string().max(1000),
guest: relation.user(),
resort: relation.team(),
status: string().max(20),
stay: relation('Stay'),
}).permissions({ view: members, edit: roles('admin', 'owner') }),
SpaSlot: table({
available: boolean(),
resort: relation.team(),
startsAt: string().datetime(),
stay: relation('Stay'),
}).permissions({ view: members, edit: roles('admin', 'owner') }),
Stay: table({
arrivesAt: string().datetime(),
guest: relation.user(),
leavesAt: string().datetime(),
resort: relation.team(),
room: string().max(20),
}).permissions({ view: members, edit: roles('admin', 'owner') }),
Trace: table({
agentId: string().max(120),
guestId: relation.user(),
input: string().max(20000),
operation: string().max(80),
output: string().max(20000),
principalId: string().max(160),
requestId: string().max(200),
}).permissions({ view: owner, edit: nobody }),
});