Download the PHP package milpa/console without Composer
On this page you can find all versions of the php package milpa/console. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Table of contents
Download milpa/console
More information about milpa/console
Files in milpa/console
Download milpa/console
More information about milpa/console
Files in milpa/console
Vendor milpa
Package console
Short Description The projection layer of the Milpa PHP framework: surface projectors that turn one declared Operation into the shape each surface speaks — CLI flags, MCP tools — plus the signature gate that makes consent name the call.
License Apache-2.0
Package console
Short Description The projection layer of the Milpa PHP framework: surface projectors that turn one declared Operation into the shape each surface speaks — CLI flags, MCP tools — plus the signature gate that makes consent name the call.
License Apache-2.0
Please rate this library. Is it a good library?
Informations about the package console
# Milpa Console
> The **projection layer** of Milpa. [`milpa/command`](https://github.com/getmilpa/command) declares
> the atom — one surface-agnostic `Operation`; this package turns that atom into the shape each
> surface actually speaks. Today: **CLI** (flags, argument coercion, the signature gate) and **MCP**
> (tools an agent can call). One declaration, N surfaces.
[](https://github.com/getmilpa/console/actions/workflows/ci.yml)
[](https://packagist.org/packages/milpa/console)
[](LICENSE)
## Install
## Quick example
A plugin declares an operation once, through `milpa/command`'s `CommandProvider`. It does not say
anything about flags, JSON-schema or terminals:
The projectors give it a surface:
## Structured command input
An input field declared as `type: object` accepts an associative object from HTTP or a JSON
object in one CLI flag, for example `--source='{"session":"s-1","seq":7}'`. For an array
whose `items.type` is `object`, repeat the flag with one JSON object per item:
`--edits='{"find":"old","replace":"new"}'`. The shared coercer decodes these declared
structures before authorization and execution. Invalid JSON, scalar JSON and nonempty lists
in an object field are refused.
String fields and arrays without object items keep their existing values; JSON-looking strings
are not interpreted there. Object property values are preserved, including nested values and
unknown properties. This is transport coercion, not full JSON Schema validation: operations
remain responsible for validating their nested input contract. HTTP's associative JSON decode
represents both an empty object and an empty list as `[]`; the coercer cannot distinguish them.
## Consent names the call
On a terminal, `requiresConfirmation: true` is not a `--yes` flag. A flag consents in the abstract —
the same yes covers removing any plugin on any host — so `CliProjector` asks for a **signature that
names this call**: the operation, its arguments, the host and a nonce. `SchemaCoercer` turns argv
strings into the types the schema declares before any of that, so what gets signed is what runs.
The pieces are seams, not concretions: `OperationSigner` is the port,
[`GnupgOperationSigner`](src/GnupgOperationSigner.php) an adapter, and verification and nonce
spending live behind `milpa/tool-runtime`'s `OperationAuthorizer`.
`CliRunner` accepts a `signerAuthority` resolver for the verified current signer. A recognized
signer's scopes pass through the shared `PolicyGate` before any handler receives a grant.
An explicit `--sign` also authenticates read operations: the handler receives attribution and
the caller's separate `ToolContext`, allowing a delegating driver to retain that authority.
A resolver failure refuses the call. Returning `null` retains the existing local signing behavior;
the host decides when that fallback applies. Stored session ownership supplies no caller authority.
`CliRunner` also accepts `callerAuthority` for an authenticated token. A host `CallPolicy` registered
in the container judges the concrete arguments before asking for a signature, and again with the
verified signer's authority. `McpProjector` installs that same policy in a concrete `ToolRegistry`.
Its `OperationToolHandler` forwards the registry's explicit context to `OperationRunner`; argument
payloads cannot supply that context.
A host may register `OperationBoundary` in the container. The runner passes the operation, input,
current authority and a closure for the declared handler to it on every surface. This is where the
host can require a confined executor; the ordinary handler runs only when the boundary calls its
closure. Delegating operations must carry the third handler argument into every child call.
## Testing your own surfaces
`Milpa\Console\Testing\SignsOperations` ships in `src/` on purpose: Composer does not autoload a
dependency's `autoload-dev`, so a test helper that lives in `tests/` is unreachable for whoever
consumes the package. The trait hands you an always-signing signer and an accepting authorizer, so a
test that just needs to get past the gate can do so without a real key.
## Where this is going
[ADR-0035](https://github.com/getmilpa/governance) — *a projection is a value, not an effect* —
governs this package. Today `CliProjector::run()` executes and `McpProjector::project()` registers;
neither returns a surface model, and that is the thing being retrofitted: a projector will produce a
model and a renderer will materialize it, so a surface can change its renderer without touching its
projector.
## HTTP, without dragging identity in
`Milpa\Console\Http\HttpProjector` is the fourth surface: one route per operation, plus the generic
controller those routes point at. It arrived in 0.4.0 — until then it lived in `milpa/skeleton`,
because moving it as-is would have dragged `milpa/auth` into a floor meant to run without it.
What made the move possible is that admission sits behind an interface. The projector delegates
that decision to `OperationHttpPolicy`, and
[`milpa/admin`](https://packagist.org/packages/milpa/admin) publishes the implementation that uses
`milpa/auth`. Write your own and the projector will use it.
Unlike the other optional collaborators in this family, **not knowing is not permission here**: an
operation that declares scopes with no policy wired throws `UnguardedOperationException` (a 500)
rather than running unguarded. It stays a 500 and never a 401/403 — the caller did nothing wrong; the
host declared something protected and left it without a guard. An operation that declares neither
scopes nor a permission never touches any of this.
**What an operation answered decides the status.** The body is always the operation's own:
| the call | status | body |
|---|---|---|
| the operation answered | `201` if it mutates, `200` if it reads | its result |
| the operation ran and answered **no** — a boolean `ok: false` at the root of its result | `409` | its result, untouched |
| the input did not fit the declared schema | `422` | `{errors}` |
| a mutating operation that asks for consent, first call | `428` | `{requires_confirmation, confirm_token}` |
| a listener stopped it before it ran | `409` | `{error, code: "MILPA_OPERATION_STOPPED"}` — no `ok` |
| the operation threw | `500` | `{ok: false, error: "internal_error", reference}` — the message stays in the log |
`ok: false` is the verdict `OperationRunner::verdict()` reads for every surface — the terminal exits 1
on it — so over HTTP a refusal is no longer a `201`: a client that looks only at the status
(`curl -f`, `fetch`'s `response.ok`, a CI) sees that the house said no, and one that reads the body
finds the same sentence it always found. `409` and not `422`, so a caller can tell «fix your request»
from «the house answered no». A result with no `ok`, or an `ok` that is not a boolean, is not a verdict.
When an HTTP operation delegates work to tools, its handler can accept a third optional argument,
`?Milpa\ToolRuntime\Contracts\ToolContext $authority`. The projector builds it from the authenticated request
and `OperationRunner` carries it alongside the second argument, `InvocationContext`. Attribution
and authority stay separate: the runner neither authorizes child calls nor stores a current user
in the container. The delegate must pass this authority to its tool gate. Missing authentication
or an empty scope list yields an empty list; it never inherits a local terminal's wildcard.
## Requirements
- PHP >= 8.3
- [`milpa/command`](https://github.com/getmilpa/command), [`milpa/core`](https://github.com/getmilpa/core),
[`milpa/tool-runtime`](https://github.com/getmilpa/tool-runtime), [`milpa/http`](https://github.com/getmilpa/http)
- `psr/http-message` and `psr/http-factory` — interfaces only. The HTTP projector asks for the PSR-17
factories instead of picking a PSR-7 implementation for you.
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md) and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).
## License
Apache-2.0 © Rodrigo Vicente - TeamX Agency. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
---
Milpa is designed, built, and maintained by **[Rodrigo Vicente - TeamX Agency](https://teamx.agency/?utm_source=github&utm_medium=readme&utm_campaign=milpa&utm_content=console)**.
All versions of console with dependencies
PHP Build Version
Package Version
Requires
php Version
>=8.3
milpa/command Version >=0.28 <1.0
milpa/core Version >=0.12 <1.0
milpa/http Version >=0.1.5 <1.0
milpa/live-tui Version >=0.4 <1.0
milpa/plugin Version >=0.7 <1.0
milpa/tool-runtime Version >=0.19 <1.0
psr/http-factory Version ^1.0
psr/http-message Version ^1.1 || ^2.0
psr/log Version ^3
milpa/command Version >=0.28 <1.0
milpa/core Version >=0.12 <1.0
milpa/http Version >=0.1.5 <1.0
milpa/live-tui Version >=0.4 <1.0
milpa/plugin Version >=0.7 <1.0
milpa/tool-runtime Version >=0.19 <1.0
psr/http-factory Version ^1.0
psr/http-message Version ^1.1 || ^2.0
psr/log Version ^3
The package milpa/console contains the following files
Loading the files please wait ...