ZIFFER home

Start here — your first hour

You have a sheet from us with an account name, three policy files, a receipt verification key and an API key.

You have a sheet from us with an account name, three policy files, a receipt verification key and an API key. This page is the shortest path from that sheet to a verified receipt for an action a person approved. Six steps, about an hour, the last twenty minutes of it watching it work.

Nothing on this page is new. Every command is quoted from the guide that explains it, and each block says which one, so when you want the reasoning it is one click away and there is only ever one description of each thing.

What you need in front of you: your onboarding sheet, a terminal, a browser, and somewhere to put a private repository.

StepRoughly
1Install the tool5 min
2Your policy repository and your signing key10 min
3Enrol yourself as the person who approves5 min
4Publish your first policy10 min
5Three lines in your AI agent15 min
6Watch a low, a high and a forbidden action10 min

1. Install the tool

One command. It checks the prerequisites, verifies the release signature before it downloads a binary, installs ziffer, makes your signing key and writes the two certificate requests.

Quoted from install.md § 0.1.

curl -fsSL https://github.com/ziffer-hq/ziffer-spec/releases/latest/download/install.sh | sh

Press Enter at every prompt for a complete install. --dry-run shows every command without running one; --yes asks nothing. If it refuses, it refuses by name and does nothing after it — the names are in the same section.

Send us back the two certificate requests it wrote and your public signing key. Keep the private key. We never see it, and nothing we run can sign your policy with it.


2. Your policy repository and your signing key

Take a copy of the policy repository template we sent you. It is the complete example policy, its three pipeline files ready to run, and one command for the key.

Quoted from the template's README.md.

bin/new-signing-key.sh

It writes the private key outside the repository and the public half inside it. Commit the public half; put the private key's text into the repository secret POLICY_SIGNING_KEY. Then the four other secrets and the eight variables, and one environment called ziffer-production — the README has the table, and install.md section 5 says where each value comes from.

Overwrite the three files marked "from us" with the ones on your sheet: receipt_identity.json, door_identities.json and attesters/registry.json. A bundle still carrying the demonstration tenant's copies is refused by name.

door_identities.json names the service that shows your approvers what they are authorising and signs what they were shown. For you that is the approval service at the link in your invitation — the page in section 3 below — and it is not a setting: it follows from who is in your registry. Change one and the other has to change with it, so we produce both together and your publish is refused if they disagree.

attesters/registry.json arrives empty, and section 3 is what fills it. Until somebody is in it, nothing that needs an approval can get one: an action that asks for one waits and then expires. That is why enrolling yourself comes before your first publish and not after it.

Then make the rules yours. floors.json, risk_functions.json and reversibility.json are the three that decide what happens to an action, and policy-by-example.md walks every file line by line.


3. Enrol yourself as the person who approves

Your administrator creates an invitation link with invite-approver.sh, which they download and verify from the release (install.md § 11), and the admin certificate we signed for them (approvers.md § 2). It connects over the internet to the address on the ZIFFER_APPROVAL_ADDR row of your handover sheet. They send the link to you. Open it on the device holding the passkey or hardware key you want to use, press Register this device, and unlock it. The page shows the line of policy your key produced.

Quoted from approvers.md § 3.

git apply approver-jane_o.patch

That is us handing you the entry as a patch to policy/attesters/registry.json, and you applying it. It adds two things that have to agree — the entry, and your assurance level beside it — and changes nothing else. Review it like any other change.

We cannot add an approver to your policy. Anybody who could would be able to approve their own actions.


4. Publish your first policy

Your first signed policy reaches us at enrolment: you hand us the signed folder out of band, and we verify it under your public key before anything is placed; a folder that does not verify is refused and nothing is placed. Every policy after it, your own CI publishes (policy-ci.md), and this step is the first of those.

Open a pull request. The policy-validate workflow runs with no key at all: it prints exactly what your signature would cover, then grades every proposal in policy/examples/ against the rules in the pull request. You can run the same grading on your own machine before you push:

Quoted from policy-ci.md § 4.

ziffer decide  <bundle-dir> --unsigned --now <RFC3339> --proposal <file>

Merge it. The publish-policy workflow reads the epoch we hold, writes the next one into your manifest, checks that the committed public key is your signing key's, signs, verifies what it signed, and publishes.

When it prints active, your rules are in force — every process that reads policy is serving them. That is seconds, not an operator's working hours. If it refuses, it prints the refusal's name and what to do; the table is policy-ci.md § 5.


5. Three lines in your AI agent

Propose, wait, verify. Your action runs only after the receipt holds.

Quoted from sdk.md § 8.

    decision = client.wait_for_receipt(client.propose(proposal).decision_id, timeout=30.0)
    if decision.receipt is None:
        raise PermissionError(f"ziffer refused: {decision.refusal_category}")

and, before the action happens:

Quoted from sdk.md § 8.

        verify(decision.receipt, json.dumps(proposal).encode(), anchor)

Four environment variables, each a row on your sheet: ZIFFER_API_KEY (the key is your tenant — you never put a tenant name in a request), ZIFFER_API_URL, ZIFFER_TRUST_ANCHOR pointing at the receipt verification key on your sheet, and ZIFFER_SUITE_FLOOR, the weakest signature suite you accept. TypeScript is sdk.md § 9; the whole example, with what each refusal means, is the same page.


6. Watch a low, a high and a forbidden action

Send three proposals from your AI agent, in this order, and watch what each one does. This is the whole product in ten minutes.

  1. A low-risk action. It passes. The answer carries a receipt, verify accepts it, your action runs. Nobody was asked anything.
  2. A high-risk action. The answer is ATTEST and there is no receipt yet: the decision reached the attestation stage and approvers are being asked. Your phone lights up. The page opens locked — it carries nothing about the action until your key opens it — and once you approve, the action releases and the receipt appears on your next read.
  3. A forbidden action. It is refused as PolicyRefused; the clause that refused it is in the console and your audit chain, not in the answer. Do not retry it: the same bytes get the same answer, and that is the point.

ATTEST is the gate, not a refusal. Do not re-propose on it — the proposal is already in flight, and a second one is a second action. sdk.md § 5 is what every refusal means; sdk.md § 6 is how to list everything we are holding for you.


When something does not work

Every refusal in this system has a name, and the name is the answer. Quote it back to us rather than describing the symptom: support.md has what we need with it and what we can and cannot see from our side.

Where it went wrongRead
the installinstall.md — the refusal table in § 0.1
the pipelinepolicy-ci.md § 5 — every answer the publish endpoint gives
the rules themselvespolicy-by-example.md
approvalsapprovers.md
the SDKsdk.md § 5
anything elsesupport.md

What this hour does not cover

The default rung works end to end, and it is the one this hour sets up. To run the Executor in your own environment — the second rung, where the credential that touches your systems never leaves your network — write to hello@ziffer.io.

On this page