Files
Claude Opus 5 b729aa3a67 kiosk: the authenticated API and two panels
what the mobile app needs is now buildable against something real: GET /apps,
GET /key, GET /install/:app/:platform/:version, POST /installs, plus device and
build verbs. all under /api/kiosk, all behind a platform session.

the install URL is built per request and never stored, because it carries the
CALLING user's key - two people asking for the same build get different links,
which is the point: the artefact route is public and the key is what authorises
it.

deliberately NOT here: the four requests that arrive with no session. installd
fetching the manifest and the ipa, the device posting its udid, safari
downloading a mobileconfig. a plugin cannot serve an unauthenticated route
today, so those wait for the platform primitive and will land in api/public.ts
- a separate file so the two surfaces cannot be confused by whoever reads
either one.

so /install returns a correct URL pointing at a route that does not exist yet.
that is the shape the app should build against.

layout is a horizontal root with the app list first, and that is load-bearing:
on a phone WorkspaceRenderer collapses horizontal groups to children[0] and
PluginScreen passes no mobilePanelId, so first is the only panel a phone shows.
the install page is the one page that must work in mobile safari.

PUBLIC_URL is read from the environment rather than officer-url.mjs, which
exports only loopback URLs - ios is not on loopback, and it needs https with a
cert it already trusts or it declines silently.
2026-08-18 03:07:56 +00:00

22 lines
871 B
TypeScript

import type * as KioskSchema from './schema';
/** A published build, as stored. `profileExpiresAt` is the date it stops launching — see the schema. */
export type KioskBuild = typeof KioskSchema.kioskBuilds.$inferSelect;
export type KioskBuildInsert = typeof KioskSchema.kioskBuilds.$inferInsert;
export type KioskDevice = typeof KioskSchema.kioskDevices.$inferSelect;
export type KioskDeviceInsert = typeof KioskSchema.kioskDevices.$inferInsert;
/**
* One app as the catalogue presents it: its newest build per platform.
*
* The mobile app opens with this, and the shape is deliberately flat — it decides for itself what is
* installed (URL schemes) and at which version (the shared keychain), so the server does not model that.
*/
export type KioskApp = {
appName: string;
displayName: string;
ios: KioskBuild | null;
android: KioskBuild | null;
};