    Authorising {{HOST}} to pull the seed feed

    The container pulls master data as its own read-only Gitea user, with a
    deploy key only it holds. Nothing here needs a particular machine: you need
    root on this container and a Gitea account that can administer users.

      contract     {{CONTRACT}}
      Gitea user   {{GITEA_USER}}
      feed         {{REMOTE}}
      key          {{KEY}}
      config       {{CONF}}

    1. On this container, as root: make the keypair here, so the private half
       never leaves it.

         mkdir -p "$(dirname {{KEY}})"
         ssh-keygen -t ed25519 -N '' -C '{{GITEA_USER}}@{{HOST}}' -f {{KEY}}
         chown root:root {{KEY}} {{KEY}}.pub
         chmod 600 {{KEY}}
         cat {{KEY}}.pub          # the public half, for step 3

       If a key is already there and only needs attaching, skip to step 2.

    2. In Gitea, as an administrator: create the user, if it does not exist.

         Site Administration > User Accounts > Create User Account
           username   {{GITEA_USER}}
           email      any address you control; it is never mailed
           password   random - nobody logs in as this account

       Then edit the account and tick "Restricted", so it sees only what it is
       explicitly given. Add it to the read-only team:

         data_controls > Teams > muli-contract-containers > Add Team Member

       That team holds "code: read" on the feed repository and nothing else.
       Do not give the account anything more: its key lives on a container.

    3. Attach the public key from step 1 to {{GITEA_USER}}.

       The web UI only lets an account add keys to itself, so either sign in as
       {{GITEA_USER}} (Settings > SSH / GPG Keys > Add Key), or, with an admin
       token, from anywhere:

         curl -fsS -X POST "$GITEA_URL/api/v1/admin/users/{{GITEA_USER}}/keys" \
           -H "Authorization: token $GITEA_ADMIN_TOKEN" \
           -H 'Content-Type: application/json' \
           -d "{\"title\": \"{{HOST}}\", \"key\": \"$(cat {{KEY}}.pub)\", \"read_only\": true}"

       The same API creates the user and team membership in step 2:
         POST /api/v1/admin/users                      (with "restricted": true)
         GET  /api/v1/orgs/data_controls/teams/search?q=muli-contract-containers
         PUT  /api/v1/teams/<team id>/members/{{GITEA_USER}}

    4. On this container: check {{CONF}} names the feed and the key.

         SEED_REMOTE={{REMOTE}}
         SEED_BRANCH=master
         SEED_SSH_KEY={{KEY}}

       muli-neo-database writes it from seed.conf.example on install if absent.

    5. Prove the credential, then pull:

         muli-db-seed-pull --check     # changes nothing
         muli-db-seed-pull

       or let muli-db-converge do it as part of building a contract database.

    Revoking this container later is removing the key from {{GITEA_USER}}, or the
    user from the team. It affects no other container.
