docs publish-cookbooks.md

Publish a cookbook and grant the team

A LEMC admin does not have to choose between handing out full control and doing every deployment personally. Give an author a narrow review lane, publish one governed capability, and let teammates and agents run it through LEMCSSH with their own rights.

Grant authorship to the author. Grant execution to the user. Cookbook authority protects source and publication; app authority protects who may run the installed computation.

The authority split

RoleAuthorityOutcome
Account adminAccount membership and grantsCreates the narrow author, deployer, and runner roles.
Cookbook authorView/create/edit cookbook authorityOwns the operating contract, source, images, and review changes.
App ownerPublished cookbook and app authorityInstalls the reviewed capability and manages its run ACL.
App memberCurrent account access plus app run grantDiscovers and runs authorized actions through the browser or LEMCSSH.

A run grant does not grant cookbook edit, image publication, secret retrieval, or account administration.

Prepare one reviewable bundle

Keep the operating contract readable in one source bundle. An agent can draft it from a natural-language brief, but a human reviews the inputs, images, callbacks, ACLs, cleanup, and proof before publish. The public access path does not require a local client installation.

cookbook.yaml
Dockerfile
terraform/
tests/
README.md

Keep the protected value outside Git, agent prompts, YAML, command arguments, logs, artifacts, and rendered output. Define each Provider requirement once in the top-level alias catalog. A Custom Provider requirement includes an owner-qualified Secret. A recipe or callback lists only required aliases. The catalog contains no value or binding.

cookbook:
  name: Credential Check
  canonical_name: credential-check
  secrets:
    team-credential:
      provider: team-credential-check
      secret: alice/TEAM_CREDENTIAL
  pages:
    - page: 1
      name: Credential
      recipes:
        - recipe: Check credential
          canonical_name: check-credential
          secrets:
            - team-credential
          now:
            steps:
              - step: 1
                name: Use the bounded Provider result
                image: local/alice/credential-caller@sha256:REVIEWED_DIGEST
                timeout: 1.minute

Providers and Secrets stay independent

A Custom Provider uses a stored Secret. It does not give the stored Secret to the recipe. The flow is:

  1. Store. The owner creates USERNAME/SECRET_NAME in the write-only User Secrets catalog. List and inspect surfaces return metadata only.
  2. Review. An authorized user reviews and approves one strict YAML Provider Profile. A Custom Profile pins one exact image digest and result schema.
  3. Declare. Define each Provider requirement once in the top-level secrets alias catalog with its secret. A recipe or callback lists only required aliases. Omission grants no Provider access.
  4. Bind. The Cookbook owner binds each selected requirement to its exact approved Profile version on the Cookbook’s Providers tab. Apps use that binding and need no separate setup. A copied Cookbook carries no binding or value. Until a pair is bound, recipes that need it show Needs setup and cannot run.
  5. Run. Only a selected Custom Provider guest receives plaintext. It supplies bounded result and context. Each NOW, IN, EVERY, or callback job receives one validated direct alias map of its selected aliases through LEMC_PROVIDER_RESULTS_YAML and its fixed integration context.
  6. Clean. LEMC completes Provider and recipe cleanup. Secret and context bytes stay out of payloads, events, logs, artifacts, diagnostics, audit, and proof.

A Custom Provider is trusted code. It receives plaintext and can transform or disclose it. Review its exact source and digest before approval. The recipe receives bounded context and runs its cloud tools itself.

Create the first Development Image

Before a recipe can run hosted-untrusted work, it needs a digest-pinned image that entered LEMC’s managed path. Accepted teams use the server-owned Builder over LEMCSSH so the agent never gets a Docker socket or host shell.

  1. Authenticate and inspect contracts: lemcli help --all --format=json, then lemcli builder images --help.
  2. List existing images: lemcli builder images list --format=json.
  3. Compile and test through the Builder, for example lemcli builder images compile-run IMAGE_UUID --expected-revision REVISION_UUID --idempotency-key REQUEST_UUID --follow, sending Dockerfile or source as an input block: end the line with <<TOKEN, send the lines, then a line that is exactly TOKEN.
  4. Record the immutable digest the Builder returns. That digest is what cookbook YAML pins later.
  5. In recipe steps, write image: local/USERNAME/IMAGE@sha256:REVIEWED_DIGEST for a Local Image. Keep standard Docker naming for remote digest references. Do not use a mutable tag.
  6. Prefer a multi-stage or minimal runtime image so compilers and package indexes do not ship in the final layer.

Hosted-untrusted jobs require a digest-pinned image (@sha256:…). A local Docker tag, remote :latest, or other mutable ref is not production-ready; LEMC fails closed when the cookbook still points at an unauthorized or non-digest image. The Builder path is server-owned: bounded stdin in, jailed compile in a fresh guest, managed digest out—not a shell or Docker host for the agent. See also the LEMCSSH Builder notes.

Create the first cookbook

  1. Assemble the reviewable bundle above (cookbook.yaml, images, optional Terraform, tests, README).
  2. Declare pages and recipes as separate capabilities. Prefer create / list / delete / launch-from-image style recipes over one shell surface.
  3. Pin every step image: to a Builder or reviewed managed digest as …@sha256:<hex>. Never publish a cookbook that still says :latest.
  4. A LEMC registry pin is written '{FQDN}/accounts/…@sha256:<hex>'. {FQDN} means this install's LEMC registry. Tools write it. Quote it when you write it by hand, and do not replace it with a host. The same YAML then moves between installs.
  5. A recipe can set its guest size with resources: cpu, memory_mb, and disk_mb. The defaults are 1 vCPU, 256 MiB, and 512 MiB. An install refuses a run that asks for more than its Runner cap. LEMC leaves empty optional fields out when it writes the YAML.
  6. When a recipe needs a Provider, define the requirement once in the top-level alias catalog with its owner-qualified Secret. Let each recipe or callback list only its required aliases. Keep protected values outside Git and the agent context.
  7. Document form inputs, timeouts, cleanup, the bounded Provider result, and proof so a reviewer can approve without reverse-engineering the container.

Form fields are not a separate template product. Each field’s variable becomes an uppercase environment variable; the container receives the option value, not the display label. A hosted guest drops lemc.env;KEY=value lines, so do not depend on them. Full types, conversion, and precedence live under Form fields become environment variables and LEMC verb wire format.

Review, bind the Provider, and create the first app

  1. Review. Confirm declared inputs, digest-pinned images, Provider trust, callback order, idempotency, timeouts, network boundary, and teardown proof.
  2. Store. The Secret owner supplies the value through the write-only User Secrets catalog. LEMC stores it separately and returns metadata only.
  3. Publish. A user with the Cookbook edit grant publishes it with cookbooks lifecycle published COOKBOOK_UUID --value true. Each Local Image step needs a verified build first.
  4. Create and bind. A user creates the App with apps create --cookbook-uuid COOKBOOK_UUID --name NAME. The App keeps its own copy of the YAML. The Cookbook owner binds each Provider requirement to the approved Profile on the Cookbook’s Providers tab. The App needs no separate setup.
  5. Grant. The App owner grants only the teammate or agent scope that should run the action. A run grant gives no Secret read or Profile edit authority.

LEMCSSH is the public remote command path for discovery, secret status, Builder work, and job execution. Cookbook creation, app creation, publication, and ACL mutation remain explicit reviewed account operations unless the remote contract exposes that operation.

Share the app with other users and agents

Grant authorship to authors and execution to runners. Expanding the run ACL is how teammates and agents discover the same Tool without receiving secret values or cookbook edit rights.

  1. Add only the people or agent identities that should run the action.
  2. Prefer Individual scope for personal workspaces and Shared or ACL scopes when the contract is intentionally multi-user.
  3. Tell callers to re-run discovery: apps list, then jobs surface, before jobs run.
  4. Remind them that discovery is not permission; admission re-checks authority on every job.

Grow into more advanced apps

  • Add pages for distinct operator workflows instead of one overloaded form.
  • Use before_run callbacks and timed in / recurring every recipes for destroy-after-TTL and cleanup proof.
  • Keep durable Terraform state under authorized /lemc workspace mounts so later jobs hydrate reviewed state.
  • Ship governed child jobs for page/recipe callbacks with preflight, idempotency, and browser/LEMCSSH parity.
  • Keep each recipe a bounded computational unit: declared inputs, pinned images, policy, and observable proof.

For workspace variables, mounts, and LEMC verbs, continue with Recipe state and LEMC verbs.

Let an agent draft the work

Give Codex, Claude, Grok, Gemini, or another approved agent the operating contract. Ask it to inspect the LEMCSSH help manifest before it writes source, and keep the real credential outside its context. Point it at llms.txt for the machine-readable map.

Contact me to work together.
Register the invited SSH key for demo.letemcook.dev.
Fetch https://letemcook.dev/llms.txt
Run: pipe lemcli help --all --format=json to ssh -T demo.letemcook.dev
Inspect builder, secret, and job contracts.
Draft the cookbook, containers, Terraform, tests, and ownership checks.
Never request or read Secret values.
Define provider: NAME requirements in cookbook.secrets.
Add secret: USERNAME/SECRET_NAME to each requirement.
Let each recipe or callback list only its required aliases.
Leave Profile approval and Cookbook binding to the reviewed Web workflow.

The agent may use LEMCSSH to inspect metadata, compile a server-owned Development Image, and submit a reviewed action. Only an admitted Custom Provider guest receives plaintext. LEMC returns a bounded result plus redacted proof.

Let a teammate or agent run it

After registration and a run grant, the caller uses the same action contract as the browser:

ssh -T demo.letemcook.dev <<'EOF'
lemcli auth whoami --format=json
lemcli apps list --format=json
lemcli jobs surface app --uuid APP_UUID --scope individual --format=json
lemcli jobs run app --uuid APP_UUID --action ACTION_ID --follow --render jsonl
EOF

Both callers receive the same task identity, system and recipe steps, live events, terminal reason, logs, artifacts, and cleanup proof.

What the central authority proves

  • the author was authenticated and authorized to edit the cookbook;
  • the image entered an account- and cookbook-scoped publication path;
  • the recipe points to immutable digests with recorded ownership;
  • the app binds a reviewed cookbook snapshot;
  • the caller passed current account and app checks before admission;
  • browser and LEMCSSH callers observe one durable execution record.