Skip to content

capsulectl v0.1.0-rc9

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 07 Oct 21:12
· 98 commits to main since this release
8e9030e

capsulectl v0.1.0-rc9

Security

verify --bundle now fails a bundle whose disclosed payload was changed.

The flaw. In v0.1.0-rc3 through v0.1.0-rc8, capsulectl verify --bundle checked each disclosed payload against what its
record sealed, but did not let that result change the verdict. A bundle in which a disclosed agent_input or agent_output had
been edited after sealing was reported as:

  • "verdict": "VALID", with exit status 0;
  • "status": "disclosure_mismatch" for that member, listed under disclosures in the same output.

The same releases also reported VALID for a bundle whose disclosures named a record the bundle does not hold.

What was not affected:

  • The checks on the records themselves: record identity, the record signatures, the checkpoint signature, log membership and
    interval coverage. An edited record, or an edited checkpoint, was reported INVALID as before.
  • verify --capsule.
  • The self-checking HTML page. Its own verifier refused such a bundle ("Bundle verification failed"), and showed none of its
    rows. That holds:
    • for bundle --html and disclose --html from rc5 (in rc3 and rc4 those commands' --html was not implemented, and they
      wrote no page);
    • for deal report --html from rc3.

What changes in this release. verify --bundle reports INVALID, exit status 1, when any disclosed member is anything other
than a match or withheld:

  • a mismatch;
  • a member that cannot be disclosed;
  • a member whose record seals no digest for it;
  • a disclosure for a record the bundle does not hold.

What to do. If you relied on verify --bundle from rc3 to rc8 to accept a bundle that discloses payloads, check that bundle
again with this release. Reading the disclosures list in the earlier output shows an edited payload (any status other than
disclosure_match or withheld), but may not show a disclosure for a record the bundle does not hold; only re-checking with this
release catches that case. Bundles that disclose nothing are not affected.

Behaviour changes for existing deal profiles

The checkpoint cadence ticks every 5 minutes

A deal profile's witness cadence, its checkpoint cadence, now defaults to a tick every 5m, give or take 1m. It was every 1h,
give or take 10m.

  • No change to the construction: one cadence-log entry per tick whether or not anything happened, and nothing publishes on
    deal activity.
  • Witness load: about 288 submissions per profile per day, up from 24.
Your profile What happens
Sets no cadence Moves to the new default at upgrade.
Sets both cadence.interval and cadence.jitter Keeps them.
Sets only cadence.jitter May now be refused: the jitter must be under half the 5m default, so under 2m30s. The error names both values. Set cadence.interval (for example 1h), or lower the jitter.

The poll. Schedule capsulectl --profile <name> cll checkpoint cadence --wait-up-to 5m every 5 minutes.

  • deal tick is the same command and stays callable.
  • A run with no tick due publishes nothing. It contacts the witness only to retry a cadence delivery still pending, once that
    delivery's backoff has passed.
  • Keep --wait-up-to: it publishes each tick at its jittered time, not on the scheduler's grid.

Receipts say when a pending checkpoint will reach the witness, from the profile's own cadence. For example: "within about 6m
(every 5m, give or take 1m)".

The action class on deal records, and cancels are never spend

Each check, action and disclosure sealed from this release carries action_class and taxonomy_version: "2" (new optional
x-deal-v0 members, also sealed inside the typed proposed-action/v0 and action-record/v0), so a limit keyed on an action's
class (money.purchase, booking.create, …) can select deal records. The classes are those of the published action taxonomy v2.

  • Committing to a purchase has the same class as paying for it.
  • A pair the table does not name is external_commitment.other.
  • A cancel is never spend. Every cancel seals spend_minor: 0. A cancel with an amount seals direction: "in". A cancel
    that returns a payment it names is money.refund. An unmatched cancel's amount moves to cancelled_amount_minor and it carries
    no amount_minor. A cancellation fee is recorded as fee_minor, not as spend.
  • Shared copies: a cancel's check that carries an amount is now withheld from copies shared with a counterparty.
  • Records already sealed are unchanged and verify as before.

Materiality: sealed at open, a re-pin mid-deal is flagged

These build on the pinned materiality predicate described under "Carried from rc8" below.

  • Sealed at open. deal open seals the predicate the profile pins into the deal's baseline (materiality, additive). It
    comes from the profile, never from the input.
  • A re-pin mid-deal is flagged. A later check under a different predicate carries a materiality_changed difference: it is
    shown on the card and pauses the check.
  • A deleted predicate file refuses with its own message: "materiality predicate file missing; re-pin it with profile update".
  • What is sealed. Sealed records carry the predicate's digest and a commitment to its name and version (label_commitment):
    • the user's own copy opens the commitment (materiality_openings);
    • a copy shared with a counterparty discloses the digest only;
    • shared copies say a predicate change in fixed words, without the predicates' names.
  • Fixed: shared copies withheld every check step once the verdict began recording materiality in rc8. Verdicts that rc8
    sealed with the name and version in the clear stay withheld from shared copies.

Carried from rc8 (not described in its release notes)

Which agent picks pause a deal check is a pinned materiality predicate. Which attributes the agent picked on its own pause a
check is no longer compiled into capsulectl. It is a materiality predicate (materiality-predicate/v0).

  • A profile with no predicate pauses on every attribute the agent picked. To keep the earlier behaviour, pin the example
    predicate, which reproduces it:
    capsulectl --profile NAME profile update --materiality skills/deal/profile/materiality-predicate/neutral.json.
    capsulectl doctor --profile NAME says which applies.
  • Pinned by digest in the profile (materiality.digest). A check refuses, sealing nothing, when the pinned file has changed;
    re-pin it with profile update --materiality FILE.
  • The user's policy. Setting the predicate is the user's to do: a check takes no predicate of its own.
  • Recorded. Every check says which predicate decided (name, version and digest, or digest none) in its output, and seals it
    in its verdict.

New

Typed action records (opt in: deal open --records typed)

A deal can seal its authority steps as typed action records, beside its x-deal-v0 evidence records in one chain:
task-authority/v0, proposed-action/v0, action-evaluation/v0, action-approval/v0, action-record/v0 and
action-outcome/v0. action-report/v0 is defined, and will be sealed by a later release. Deals opened without the flag are
unchanged.

The check contract. The evaluation carries proposed_action_digest, task_authority_ref, ruleset_digest,
materiality_digest, valid_until and authority_basis.

  • A step after valid_until is refused.
  • An approval never extends to a changed proposed action.
  • An ASK is answered only by the user's own approval, on the card the check showed.

Platform approval observations. deal note --kind platform_approval records that another platform asked for approval, and
what it showed and returned. It authorizes nothing.

The receipt's Authority block. For each action in a typed deal, the receipt lists every authority layer it relied on, in the
order of its sealed authority basis, each with its own time:

  1. your request;
  2. your rules (DO or ASK);
  3. your approval on the card;
  4. any platform's own approval, marked as observed;
  5. the action.

The block is in the JSON report, the receipt page and the emailed receipt. It is in the user's own copy only.

The Capsule follows the authority basis. A typed action's Capsule reads its disposition from its sealed authority_basis:

Authority basis Capsule
Within the user's rules (a DO) decide with approver: policy
The user's own approval decide with approver: human
No covered basis fyi

A platform's approval never makes it human.

A self-checking report of records you sealed

The README has a worked example, run in CI exactly as written, that turns sealed records into a bundle plus a page that checks
itself offline. It uses:

  • a SQLite profile with a log;
  • a report/v1 root citing the records;
  • one checkpoint;
  • disclose --out bundle.json --html report.html;
  • verify --bundle.

The README states what VALID rests on: keys the bundle carries, which a reader compares with the producer's key obtained
another way. It also states what the page does not check: the checkpoint's signature and the records' signatures.

Fixes

  • verify --bundle accepts the log id from the completeness certificate. Bundles built on a JSONL profile failed with
    checkpoint_field_missing:log_id, though capsulectl wrote them. The signed log id must now equal every log id the bundle
    states, in the certificate, the checkpoint or both.
  • The deal receipt page renders deal bundles. The vendored evidence-graph viewer threw "root aggregate payload is not
    disclosed" on a bundle with no evaluation summary, and showed a blank page. It now renders the bundle and says it has no
    aggregate view.
  • Shared copies of deals keep their check steps. See "Materiality" above. (One new withholding: a cancel's check with an amount; see "The action class" above.)

Dependencies

  • github.com/action-state-group/agent-action-capsule/go: v0.6.0 → v0.6.1-0.20261007011327-65b3fdc8f358 (the commit 65b3fdc,
    untagged). That commit carries the viewer fix, and also brings:
    • stricter verifier type checks;
    • negative zero written as 0 (RFC 8785);
    • the Result v0 emitter root.
  • github.com/action-state-group/evidencebook: v0.1.1, unchanged.

Verify

Prebuilt capsulectl binaries (linux/amd64, linux/arm64, darwin/arm64).

  • Checksums: sha256sum -c SHA256SUMS.
  • Build attestation, with no GitHub account:
    gh attestation verify FILE --bundle capsulectl-v0.1.0-rc9.sigstore.json --repo action-state-group/capsule-cli --signer-workflow action-state-group/capsule-cli/.github/workflows/release.yml