← The cookbook

a headhunter is going to contact my beji about a role — set up what they'll be able to see, and get a key I can email them, capped and expiring, without touching a terminal

Verified on intent-tortoise-280 · 2026-08-07T15:13:46.996Z

A run against that face proves the ROAD exists. It says nothing about any other deployment's state.

What it declares

Actor · Who walks it
the twin's owner (one actor; their agent lays the scaffolding, then the owner only talks)
Credential · What they must be holding
minting agent token for the owner-side setup; a key over the Owner audience for the conversation; the minted visitor key for the proof
Ends with · What exists when it is done
a hands-free audience named for the recruiter exists on the twin with the role brief bundled in, and exactly one live key — capped at 12 messages, expiring in two weeks, handed back inside the conversation — opens that audience and nothing else

What the run proved

  • The end state did not already exist

    held

    check failed as required: twin 'recipe-hh-kr5evg' is not on the roster

  • The end state existed after the road

    held

    key j577a1r196ebfmfy62j5ga7gp18c1js5 opens 'Nordlys Search' on 'recipe-hh-kr5evg': cap 12, expires 2026-08-21T15:12:00.000Z, hands-free, holdings = [The role brief for Nordlys Search], thread opens

  • The end state was gone after cleanup

    held

    check failed as required: 0 live key(s) over 'Nordlys Search' (need exactly 1)

The road, as walked

  1. 1

    register PoW challenge

    GET /beji/challenge

    ok

    20 bits

  2. 2

    register agent

    POST /beji/register

    ok

    balance 5

  3. 3

    stake

    POST /beji/stake

    ok

    balance 30

  4. 4

    signup beji

    POST /beji/signup

    ok

    1 audience, 2 exhibits, staked 25

  5. 5

    set inference credential

    POST /beji/inference

    ok

    model tencent/hy3

  6. 6

    mint the owner key

    POST /beji/me/beji/recipe-hh-kr5evg/keys

    ok

    the owner's conversational seat; quota 10

  7. 7

    open the owner thread

    POST convex dm:openThread

    ok

    credential: the owner key

  8. 8

    turn 1: set up what the headhunter will see

    POST convex dm:sendMessage

    ok

    create_audience + create_expo, by asking

  9. 9

    audience landed, hands-free, exhibit bundled

    GET /beji/me/beji/recipe-hh-kr5evg/exposes

    ok

    toolset [] — the wall held on the create side

  10. 10

    turn 2: mint the key, capped and expiring

    POST convex dm:sendMessage

    ok

    mint_key, by asking

  11. 11

    the token came back in conversation

    ok

    reply contains the roster row's exact token — no terminal needed

  12. 12

    turn 3: ask for a key into the Owner audience

    POST convex dm:sendMessage

    ok

    must be refused: Owner carries tools

  13. 13

    the wall held

    GET /beji/me/beji/recipe-hh-kr5evg/keys

    ok

    key rows unchanged (2); no such key came back, no key row appeared

  14. 14

    end state reached

    ok

    key j577a1r196ebfmfy62j5ga7gp18c1js5 opens 'Nordlys Search' on 'recipe-hh-kr5evg': cap 12, expires 2026-08-21T15:12:00.000Z, hands-free, holdings = [The role brief for Nordlys Search], thread opens

  15. 15

    cleanup

    ok

    7 reversal(s) through the doors that exist

  16. 16

    end state removed

    ok

    check failed as required: 0 live key(s) over 'Nordlys Search' (need exactly 1)

What it left behind

7 Created
  • agent 'recipe-hh-kr5evg'
  • beji 'recipe-hh-kr5evg' (https://intent-tortoise-280.convex.site/recipe-hh-kr5evg) with audience 'Owner' + 2 exhibits
  • access key 'Eirik (the owner) — this conversation' over 'Owner'
  • owner thread jd79xd2rest1yfb5pyrmt84rjs8c0jfh on 'recipe-hh-kr5evg'
  • audience 'Nordlys Search' + exhibit 'The role brief for Nordlys Search' (created by the resident, in conversation)
  • access key 'Marit Sølvberg — Nordlys Search' over 'Nordlys Search' (minted by the resident, in conversation)
  • visitor thread jd73ax2q2rbg4c1xyw9gh3ezrd8c1kg2 on 'recipe-hh-kr5evg' (opened by the end-state check)
7 Removed
  • key 'Eirik (the owner) — this conversation' over 'Owner' — revoked (dead; row remains)
  • key 'Marit Sølvberg — Nordlys Search' over 'Nordlys Search' — revoked (dead; row remains)
  • audience 'Owner' — unpublished to draft (row remains)
  • exhibit 'The brief — shareable with recruiters' — unpublished to draft (row remains)
  • exhibit 'Private notes — never for recruiters' — unpublished to draft (row remains)
  • audience 'Nordlys Search' — unpublished to draft (row remains)
  • exhibit 'The role brief for Nordlys Search' — unpublished to draft (row remains)
3 Remaining
  • agent 'recipe-hh-kr5evg' (+ its token_ledger rows) no door removes it: no door deletes an agent
  • beji 'recipe-hh-kr5evg' with its exposes/expos (all drafted) and revoked key rows no door removes it: no door deletes a beji, an expose, an expo, or a key row
  • dm threads + messages on 'recipe-hh-kr5evg' no door removes it: no door deletes a thread

Anything still remaining is something this house lets you create and gives you no door to un-create. That is a one-way door, and naming it is a result of the run rather than an apology for it.

Walking it yourself

node challenges/recipes/recipe-headhunter-key.mjs

Recipes MUTATE. They create real rows, keys and blobs, and they are written for the dev deployment only — each one refuses a target that is not the deployment its .env.local names. Running one against production plants scaffolding in the surface real strangers read.

Every write in this house goes through an authority. A recipe names its credential by class and carries it on every mutating call; it will fail loudly rather than find an uncredentialed way in, and you must supply that credential yourself.

The same thing, for a machine: /cookbook/headhunter-key.json

Rendered from challenges/recipes/recipe-headhunter-key.mjs and its committed run at challenges/recipes/recipe-headhunter-key.run.json.

The header is parsed as text and the module is never imported — importing it would execute the road, and a page render must not be able to mutate a deployment.