Skip to content

πŸ—οΈ An ambient capability ceiling cannot tell the host's own acts from the document'sΒ #677

Description

@taras

Report

The xmd plan authorship profile refuses its document a file, a command, a
service and the network. It refuses them ambiently β€” middleware on
API.Files, API.Process, API.Fetch and API.Service over a scope β€” and a
call carries no mark saying who made it. API.Process.exec looks identical
whether an exec fence reached it or the command itself did, so the ceiling
refuses the host's own acts as though the document had asked for them.

It has surfaced twice, a layer apart, and both times in front of a user:

Both ended with the same line, before any Plan could be written or reviewed:

xmd plan asked for a command, which the authorship profile grants to nothing

Both are fixed today by the command taking its own scope before it installs the
ceiling and running that one act there β€” inScope and the FormOpener wrapper
in packages/cli/src/authorship-profile.ts. It works, and it is a list the next
host act has to be added to by hand.

Why the obvious fixes do not work

A provider cannot do this for itself. The natural rule β€” "a provider does its
work in the scope it was installed in" β€” does not escape the ceiling, because
core builds the root provider inside the document execution and around the rest
of the chain: withRootProvider (packages/core/src/agent/components.ts:280,
:323) calls rootProvider.factory(...) and then invokes nextDocument from
within it. The provider's own scope β€” stateScope,
packages/acp/src/provider.ts:825, which already serves the permission bridge β€”
is therefore under the ceiling.

Measured rather than reasoned: a probe placed at the factory, with the ceiling
installed as Execution.around({ document }) middleware and tried on both sides
of installAgentComponents, reports

PROBE: construction refused: xmd plan asked for a command, which the authorship
profile grants to nothing

Narrowing the ceiling does not help either. Wrapping only the document body
leaves every arrangement above unchanged, because the provider's construction and
its later calls are both inside that body.

A component-only ceiling does not cover it. Refusing the document the
components that reach a capability would leave exec fences untouched: those are
a language feature, not a component.

So the only scope outside the ceiling is one captured before the ceiling exists,
and the command is the only party that can capture it. That is what the current
fix does, and no rearrangement of the existing pieces removes the need for it.

What would remove it

Each of these is a change to the capability model, not a refactor:

  1. A carrier the refusal can read. The ceiling stops covering a scope and
    starts answering a question about the caller β€” an unforgeable value the
    document's own calls carry and the host's do not. This is the same shape as
    the rule that a precheck cannot bind a later dispatch.
  2. Construct the root provider outside the document execution. If a provider
    the host configured were built where the host installed it, its own scope
    would sit outside a document-scoped ceiling, and "a provider does its work in
    its installation scope" would be enough on its own.
  3. A per-execution capability set. The execution is given the capabilities it
    may use, rather than running under ambient middleware that everything in scope
    inherits.

Open questions

  • Is the host/document distinction one the engine should express at all, or is a
    profile that needs it always going to state its own acts?
  • If a carrier: what holds it, and what stops a document reaching it β€” a document
    can already install middleware of its own.
  • Does the same question apply to xmd workflow, which states a strict profile
    but grants its document no ambient refusal of this kind?

Acceptance

  • A host act performed while a ceiling is installed is not refused as the
    document's, without the command naming that act in advance.
  • Adding a third host act to xmd plan requires no change to the ceiling.
  • The document's own refusals are unchanged: a file, a command, a service and the
    network stay refused, including from an exec fence and from an authored
    element inside an <Answers> region.
  • The inScope helper and the FormOpener wrapper in
    packages/cli/src/authorship-profile.ts are gone.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions