Skip to content

registry: agents, their scopes, refusals and push kinds - #90

Merged
frahlg merged 2 commits into
mainfrom
claude/registry-agents
Oct 15, 2026
Merged

frahlg merged 2 commits into
mainfrom
claude/registry-agents

Conversation

@frahlg

@frahlg frahlg commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

What

Names for agents, edited here first as the registry rule says. An owner can let an assistant (ChatGPT, Claude, Grok through MCP at FTW Cloud), Sourceful support for one ticket, or the release check reach the box. The box enforces everything; these are the words both sides use.

  • Roles agent, support and release. Each is the most a grant of that kind may carry; a grant names a subset.
  • Scopes ftw.logs.read, ftw.config.read, ftw.diag.run, ftw.dispatch.hold, ftw.goals.request and ftw.update.request. Scopes now take the verbs run, hold and request as well as read and write.
  • Ops carry agent, the scope that opens each to an agent. Holds (battery.hold, loadpoint.hold, loadpoint.boost) run under caps and end by themselves. Durable changes (site.mode.set, planner.prefs.set, loadpoint.soc.set, loadpoint.surplus_only.set) wait for an owner as agent.request.
  • Capability access.agents.
  • Refusals E_GRANT_EXPIRED, E_OP_NOT_GRANTED, E_CAP_EXCEEDED, E_RATE_LIMITED (the one retryable), E_NEEDS_OWNER, E_BAD_SIGNATURE, E_NO_APPROVAL_KEY, E_NOT_FOUND.
  • Push kinds agent.added and agent.request, to every owner.

The wire, the approval signature and the box page are in docs/agents.md in srcfl/ftw (the paired PR below).

In this app: contract.ts, the retry table and the push toggles take the new names, and the bare-scope test accepts the new verbs. A toggle appears only when the box's rules list the kind, so nothing changes until a box sends them.

Paired PRs

Contract-pair: srcfl/ftw@claude/agents-contract

Tests

  • npx vitest run: 108 files, 1,102 tests pass.
  • svelte-check: 0 errors.
  • check-contract-drift.mjs against the box's copy: both files byte for byte.

After the review (adversarial, at f557f6d)

Fixed before merge, the three blockers and everything that changes signed bytes or wire shapes:

  • 1. The public door. Agent rows carry tun: false and no copy scopes; only FTW Cloud's keys part opens an agent's session, never /v1/app, /v1/app/once or the relay (docs/protocol-cloud.md). Offers are signed (SignedOffer {o, kid, sig}, protocol.OpenOffer) by a pinned offer key, live at most 10 minutes, carry clientHost and verified, leave home empty, and a support offer comes only from SupportClientID.
  • 2. Holds. battery.hold and loadpoint.boost lose their agent scope. A new agent_args block allowlists each op's arguments, with labels (so voltage, max_amps_per_phase and the rest stay with owners). Holds carry their setter, an owner's hold wins (E_NEEDS_OWNER), an agent clears only its own, maxW is |W|, and revoke or expiry ends an agent's holds.
  • 3. The box page. Every widening route needs the house password, loopback included; drivers never reach the box's own API.
  • 5. Replay memory keyed by the signed bytes; agent.confirm signs [reqId, agent, op, sha256(args)]; request ids are 128 bits; an atMs from before the box started is refused.
  • 6. The signed offer's fields as above; the owner types the code on the universal-link path; the app refuses an unknown home.
  • 9. Request args checked on arrival against agent_args and the op's own checks.
  • 11. by is staff:<id> or bot:<name>, refused from any session but support.
  • 16. agent.widen signs the row's key.
  • From cloud-mcp: the roster carries the box's Noise key (Roster.noise); typed reads live.get, loadpoints.get, cars.get, drivers.get in a registry reads table, cursors on logs and events, agent ids under the box's own key.
  • Also in the wire now: approval.key.set takes prevSig, audit rows carry count, agent.decided, E_CLOCK_SKEW, push kinds agent.expiring, approval.key.set, owner.added, ftw.update.request marked reserved, E_NOT_FOUND worded for any id (the car contract can reuse it).

Vectors regenerated: approval (widen and confirm bytes changed), a signed offer, and the roster (with noise and an agent row).

🤖 Generated with Claude Code

An owner can let an assistant, Sourceful support for one ticket or the
release check reach the box through FTW Cloud. The registry names what the
box enforces for them:

- roles agent, support and release, each the most a grant may carry;
- scopes ftw.logs.read, ftw.config.read, ftw.diag.run, ftw.dispatch.hold,
  ftw.goals.request and ftw.update.request, so scopes now take the verbs
  run, hold and request as well as read and write;
- an agent key on each op, the scope that opens it to an agent;
- the capability access.agents;
- eight refusals, from E_GRANT_EXPIRED to E_NOT_FOUND;
- push kinds agent.added and agent.request.

docs/agents.md in srcfl/ftw is the wire.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-15T17:07:55.967669Z 01d9db6 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 01d9db64bc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

# To every owner, when an agent asks for a durable change. It waits for
# one of them to confirm it, and runs out after twelve hours.
title: Waiting for your answer
body: "An assistant asks to change a setting. Open FTW to confirm or decline."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Route request pushes to a confirmation screen

When a box emits agent.request, tapping the notification cannot reach the promised confirmation flow: src/sw.ts routes every non-charging push to /, and a repo-wide search finds no agent-request approval view or API. The request therefore remains pending until it expires even after the owner follows “Open FTW”; implement and deep-link the approval flow, or direct the owner to the box page where the request can actually be handled.

Useful? React with 👍 / 👎.

# the release check access to the box. Access from outside the house is
# news every owner should hear, as with cloud.granted.
title: New access to your box
body: "You gave an assistant or Sourceful access. See who has access in the app."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Link access alerts to an agent roster

When agent.added is delivered, the advertised inspection path does not exist in this app: the current Access screen only reads paired phones from /api/app-link/devices, and a repo-wide search finds no use of access.agents or any agent roster. An owner following this security-sensitive alert therefore cannot see which agent was granted access; either add the agent list before shipping this copy or point the notification to the box page that has it.

Useful? React with 👍 / 👎.

# the release check access to the box. Access from outside the house is
# news every owner should hear, as with cloud.granted.
title: New access to your box
body: "You gave an assistant or Sourceful access. See who has access in the app."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid attributing every grant to its recipient

When one co-owner creates a grant, this event is sent to every owner as specified immediately above, so owners who did not perform the action are nevertheless told “You gave” the access. For a security-sensitive access alert this misidentifies the actor; use neutral wording such as “An assistant or Sourceful was given access,” or include the actual granting owner.

Useful? React with 👍 / 👎.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
ftw-webapp 31a144b Commit Preview URL

Branch Preview URL
Oct 15 2026, 06:09 PM

… kinds

From the review of the agent contract:
- agent_args: what an agent may put in each op, with a label per argument
  for showing a request to the owner;
- reads: each read an agent may send and its scope;
- battery.hold and loadpoint.boost lose their agent scope until the box
  can bound them;
- E_CLOCK_SKEW for an approval whose time is too far from the box's, and
  E_NOT_FOUND worded for any id;
- ftw.update.request marked reserved;
- push kinds agent.expiring, approval.key.set and owner.added.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@frahlg
frahlg merged commit f2d2d45 into main Oct 15, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant