docs themes.md

Themes are server-owned and account-selected

A LEMC theme supplies paint, fonts, and approved images for an account’s web interface. The server owns layout and the theme lifecycle. An account admin chooses which installed or promoted theme the account uses.

A teammate or agent should not need host filesystem access just to inherit the team’s visual language.

Can a user or agent upload a theme?

Only through the managed theme lifecycle—never as arbitrary CSS or JavaScript. Current releases accept a portable lemc.theme.bundle/v2 contract: design tokens, attribution, and allowlisted PNG slots only. They reject custom CSS, HTML, JavaScript, fonts, SVG, WASM, archives, and remote asset URLs.

Built-in themes (Default, Banilla, Jellyware) ship with the product as system-scoped sources. Authorized actors can export a built-in, fork it locally, then use the API or LEMCSSH theme commands to validate, upload an immutable draft, preview, and promote under user, account, or system ownership as their authority allows. Upload alone does not activate a theme for the account.

A basic member or cookbook author cannot install or activate a theme for the whole account. Theme files load as same-origin interface assets and affect everyone who inherits that account selection, so activation stays an account-admin decision.

Authority map

ActorWhat they can do todayWhat they cannot do
Server operator / superadminOwn system-scoped themes; operate the installation and built-in catalog.Does not choose a tenant account theme unless also acting as its admin.
Account adminSelect a built-in or promoted account theme in Account Settings; manage account-scoped theme drafts when authorized; inspect settings through LEMCSSH.Cannot smuggle executable web source through the theme contract.
Member or cookbook authorInherit the account’s current theme; may hold a private user-scoped draft only when the product grants that surface.Cannot install or activate an account theme with basic cookbook authority.
AgentUse the same authorized LEMCSSH theme and account-settings commands as its human identity.Gets no special theme authority beyond that identity’s grants.

Pattern: theme the LEMC workflow your team already uses

A corporate theme changes LEMC’s logo, colors, icons, background, and typography without replacing the application underneath. The signed-in identity, app metadata, Individual/Shared/ACL scope tabs, page wiki, recipe action, monitor, and durable result remain in the same familiar places.

  • Identity and discovery: the navbar shows the signed-in teammate while app ACLs decide which apps and actions that identity can see.
  • Context and action: each app page keeps its wiki, uploaded wiki images, declared form inputs, and bounded recipe action together. The wiki can explain exactly what every recipe button does before a teammate runs it.
  • Progress and proof: the monitor, events, logs, terminal result, and artifacts stay attached to the job after the theme changes.

The homepage’s Cloud Casserole example gives the fake user Maya access to a People Operations app, then applies the company logo, layered blue palette, and clean sans-serif application type. Its five-second automatic crossfade introduces the change. Only after it completes do the compact previous and next controls appear on either side of the caption below the iframe. Their restrained outline and shallow shadow separate them from the caption without covering the preview. They switch immediately so an operator can compare both presentations without losing the app context. Finance Reporting, Leadership Briefing, and Web Filter Review can remain separate apps with separate ACLs for the teams that need them.

Teammates use that branded LEMC web UI. Agents use the same action contract through LEMCSSH and receive the same task identity, events, artifacts, and terminal result. The theme changes presentation; it never grants permission by itself.

Create the theme with a natural-language agent

You do not need to hand-style every page. Give Codex, Grok, Kimi, or another agent a company logo, the primary and accent colors, accessibility requirements, and a short description of the desired feel. Ask it to start from a built-in export (Default, Banilla, or Jellyware), preserve the portable bundle layout, and return a reviewable lemc.theme.bundle/v2 package.

A useful brief can be this small:

Theme name: acme
Logo assets: ./brand/
Primary color: #243b64
Accent color: #f2a900
Direction: calm, technical, and familiar to our operations team

Export a built-in theme, map the supplied logo and colors into tokens and
approved PNG slots only, check readable contrast, and return the bundle plus a
changed-file list. Do not install or activate it.

The agent helps create the files; it receives no special LEMC authority. An authorized person or agent then validates and uploads the draft through the managed lifecycle, previews it, promotes an accepted artifact, and lets an account admin select it. Teammates who only know the web UI inherit the result the next time they load the account.

Managed lifecycle: export, upload, preview, promote

Themes are selected by immutable theme_id and version_id (content digest). Display names are labels, never authority keys. Built-ins are system-scoped. Custom work uses account or user ownership.

  1. Export a built-in or authorized version to obtain the public source inventory (manifest, tokens, attribution, approved PNGs).
  2. Edit only tokens and allowlisted images. Do not inject CSS, HTML, or scripts.
  3. Validate the directory or transport bundle before upload.
  4. Upload stores one immutable draft. It does not preview, promote, or assign the version.
  5. Preview compiles a server-owned synthetic document under tight CPU, memory, and network limits, then records an artifact digest and evidence.
  6. Promote requires that exact accepted artifact_digest before the version can be assigned.
  7. Select the theme for an account in Account Settings (account-admin authority), or keep a private user assignment where the product allows it.

Accepted source lives as a digest-addressed bundle in object storage. Tokens and attribution have no direct browser route. Raster assets are served only by immutable theme ID, version ID, and allowlisted role with private, nosniff, same-origin policy.

Admin or authorized agent: select it

In the browser, open Account → Settings, choose the theme under Theme, and save. The route is protected by account-administration authority. Built-ins always appear; a promoted managed theme appears when the account is allowed to use it.

An account-admin agent can inspect the selected theme through LEMCSSH:

ssh demo.letemcook.dev account settings get --format=json

Discover remote theme commands with ssh HOST help --all --format=json and ssh HOST themes --help when your identity is authorized. To roll back a visual change, select a known built-in in Account Settings, then inspect the result again through the same settings command.

Verify and retain it

  1. Hard-refresh an authenticated account page and confirm the selected CSS and icons return HTTP 200.
  2. Check Account Settings with ssh demo.letemcook.dev account settings get --format=json.
  3. Exercise desktop and mobile pages before inviting the team back in.
  4. Retain the immutable theme_id, version_id, and promoted artifact_digest in your change record so operators can reproduce or roll back the selection.

What the governed contract enforces

The portable bundle is a data contract interpreted by server-owned templates and compilers—not an unrestricted file drop. Current releases already enforce the hard edges a team should expect:

  • a manifest, immutable version digest, file-count limit, and size limit;
  • decoded PNG validation (signature, dimensions, no animation, no polyglot trailer);
  • no HTML or JavaScript payloads, plus explicit token and image policy only;
  • immutable staging, preview evidence, and a separate promote decision before assignment;
  • ownership scopes (system, account, user) that never change after creation.

Giving an automation agent host filesystem access is not a substitute for that governed upload contract.