Skip to content

docs: record the intent architecture (venue adapters, egress guard)#132

Draft
mfw78 wants to merge 5 commits into
dev/m1from
docs/intent-architecture
Draft

docs: record the intent architecture (venue adapters, egress guard)#132
mfw78 wants to merge 5 commits into
dev/m1from
docs/intent-architecture

Conversation

@mfw78

@mfw78 mfw78 commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

What

Adds docs/09-intent-architecture.md plus ADR-0010 (venues as dynamically installed adapter components; CoW becomes the first adapter) and ADR-0011 (one egress guard pipeline for intent submissions, EIP-712 signing, and transaction signing, with analysers as installable components and simulate as a pluggable host primitive).

A second commit folds in the red-team amendments: authorisation-source classification in the guard (pre-authorised EIP-1271 flows are audit-plus-advisory, never prompted or blocked, with the limits-are-observability caveat stated plainly), chain routing carried in venue bodies with settlement exposed in the derived header, appData travelling as the on-chain hash with no venue read path (see #133 for the corresponding 0.2 code cleanup), a read-only query verb deferred to open questions, and a full SDK-surfaces section: the two authoring personas and crate map, the one-crate-per-venue rule, borsh as the body codec with venue schemas as language-neutral specifications (golden vectors, classification tables as data), the no-composition rule (module to host to adapter, for policy interposition, fuel attribution, and fault isolation), metering attribution including router-level per-caller quotas, and the non-Rust module path via componentize-py.

Why

Closes #131. Records the July 2026 architecture review outcome: the CoW integration generalizes into a venue-adapter layer over a shared nexum:value value-flow vocabulary, venues become user-installable without host releases, and the wallet embedding's signing analysis unifies with intent policy in a single guard pipeline. ADR-0010 supersedes the compiled-in backend framing of ADR-0005; the strategy-vs-protocol boundary of ADR-0006 is preserved.

Testing

Documentation only; no code paths changed. Checked for style conformance (no em-dashes, no hard-wrapped paragraphs, no issue references inside the docs).

AI Assistance: Claude Code used for drafting the design doc and ADRs from the architecture review discussion.

@mfw78

mfw78 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Required action to land as M1 train step 0 (design gate for #137). This PR is the intent-architecture design authority (docs/09-intent-architecture.md, docs/adr/0010-venues-as-adapter-components.md, egress-guard ADR).

  1. Rebase onto train HEAD 502175c (currently based on develop, below the M0/mock/fault stack).
  2. Renumber the egress-guard ADR 0011 -> 0012 — the train already added docs/adr/0011-per-interface-typed-errors.md, so the current number collides.
  3. Merge first, ahead of the WIT/router work — intent: WIT packages, venue-adapter world, pool router #137's venue-adapter world (runtime: venue-adapter world, manifest module-kind, and [[adapters]] engine config with scoped transport grants #228) and pool-router (host: implement the nexum:intent pool-router (derive-header -> guard-seam -> submit, serialization, quotas) #229) are gated on this design being ratified.

Closes #131 on merge.

Comment thread docs/09-intent-architecture.md Outdated
}

variant intent-status { pending, open, settled(option<list<u8>>), failed(fail-reason), expired, cancelled }
type receipt = list<u8>; // venue-scoped stable id (CoW: the 56-byte order UID)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A list<u8> receipt is hashable, but the WIT sketch does not specify an encoding, and different venues may produce receipts that differ in length, encoding, and uniqueness scope. For the CoW case (56-byte order UID), this is fine, but the "venue-scoped stable id" needs to be more precisely specified -- stable within a session? Across restarts? Globally? The SDK conformance kit (golden vectors, classification tables) is where this belongs, but the doc should name the stability requirements the host relies on.

offchain(offchain-desc), // RWA: deed, chattel, ...
}

record asset-amount { asset: asset, amount: list<u8> } // big-endian unsigned

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

There is no length constraint and no maximum on "amount: list". For the purposes of WIT, this is correct (WIT has no fixed-size integer arrays), but downstream code parsing this will need to bound-check and handle values that overflow any native integer type.

Suggestion: a one-sentence note in the vocabulary section: "policy implementations must treat any amount exceeding the precision of the native type as exceeding any configured limit."


### No direct module-to-adapter linking

Component-model composition (linking the module's `pool` import straight to the adapter's exports) looks like an optimisation and is a correctness bug three ways: the host must interpose policy between `derive-header` and `submit`; wasmtime fuel is per-store, so host-in-the-middle is what keeps module work on the module's meter and adapter work on the adapter's; and an adapter trap must not poison the calling module (separate stores, separate restart policies). Every hop is module to host to adapter, and the SDK's job is to make that feel like a typed function call.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The rule does not address the case where a strategy module needs to use multiple venues in a single logical operation (e.g., a cross-venue arbitrage that must submit to venue A and venue B atomically, or fail gracefully). With the current pool interface, the module submits twice and handles partial failure. That is probably the right answer, but the atomicity story is silently delegated to the strategy author.

interface types {
variant settlement {
evm-chain(u64),
offchain(string), // jurisdiction / venue-defined domain

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This offchain(string) is likely to become a registry of venue-specific domain identifiers, and the guard will likely accumulate pattern-matching on it. A structured type (even just an enum with an other(string) arm) would be easier to extend safely.

- Interactive signing acquires a latency budget shared by simulation and analysers. Deadlines are enforced with the existing metering machinery (fuel, epoch interruption); partial verdicts render as "analysis incomplete" per profile.
- The engine grows three surfaces: the `simulate` primitive with a backend seam, the fact-bundle assembly, and the analyser host-call path with deadline scheduling. The analyser world finally gives the experimental `query-module` lineage a shipping consumer.
- Verdict aggregation across multiple analysers starts as max-severity-wins; contradictions and reputation are open questions recorded in the design doc.
- Every embedder profile (server, wallet, super-app) must declare its fail-open/fail-closed matrix; the embedding API exposes verdicts and consent hooks so wallets render them natively.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Before the guard ships, that API needs a concrete WIT sketch -- even a rough one -- because it is the surface wallets depend on, and "explicit configuration" without an API shape is an extensibility promise that cannot be verified.

native-token(settlement),
erc20(tuple<u64, list<u8>>), // (chain, address)
erc721(tuple<u64, list<u8>, list<u8>>), // (chain, address, id)
erc1155(tuple<u64, list<u8>, list<u8>>),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
erc1155(tuple<u64, list<u8>, list<u8>>),
erc1155(tuple<u64, list<u8>, list<u8>>), // (chain, address, id)

Comment thread docs/09-intent-architecture.md Outdated
// narrow, manifest-declared, per-adapter-scoped imports:
import http; // e.g. the CoW adapter: api.cow.fi only
import messaging; // e.g. a Waku venue: its content topics only
import chain; // read-only lookups where needed

@lgahdl lgahdl Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nitpick: for more clarity

Suggested change
import chain; // read-only lookups where needed
import chain; // on-chain state reads; no signing, no send

interface types {
variant settlement {
evm-chain(u64),
offchain(string), // jurisdiction / venue-defined domain

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A separator makes confusing when each one applies and when, removing jurisdiction.
Note: The prose section already says venues define this string, so the "why a string" question is answered elsewhere.

Suggested change
offchain(string), // jurisdiction / venue-defined domain
offchain(string), // venue-defined domain

Comment thread docs/09-intent-architecture.md Outdated
wants: list<asset-amount>,
valid-until: option<u64>,
settlement: settlement,
authorisation: auth-scheme, // eip712 | eip1271 | presign | offchain-sig | unsigned

@lgahdl lgahdl Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Accuracy risk: auth-scheme is not defined anywhere in the snippet or in the PR. If auth-scheme gains or loses arms, the comment will silently drift.

Suggested change
authorisation: auth-scheme, // eip712 | eip1271 | presign | offchain-sig | unsigned
authorisation: auth-scheme, // see auth-scheme variant;

interface pool {
submit: func(venue: string, body: list<u8>) -> result<receipt, venue-error>;
status: func(venue: string, receipt: receipt) -> result<intent-status, venue-error>;
cancel: func(venue: string, receipt: receipt) -> result<_, venue-error>;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

venue-error is not defined

@lgahdl lgahdl left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Adding a few observations

@mfw78 mfw78 added the base: develop Open PR targets develop — merge FIRST, before the dev/m1 integration PRs. label Jul 15, 2026
mfw78 and others added 5 commits July 15, 2026 07:22
The M0 train adds ADR-0011 (per-interface typed errors), which collides
with the egress-guard record this branch introduced at the same number.
Renumber it to 0012 and update the two cross-references so both records
land with distinct numbers.
…sions

Updates docs/09 + ADR-0010 + ADR-0012 against the shipped M1 tree and the
seven platform decisions (2026-07-14): marks the shipped surfaces as
shipped (venue-adapter kind, nexum:intent/pool, nexum-venue-sdk,
#[nexum::venue], echo-venue, cow-venue, ADR-0013 Verdict seam), reframes
the egress-guard pipeline as target design deferred to the egress-guard
epic (M1 ships an advisory AllowAllGuard no-op, R3), corrects the
world-composition category error (an adapter targets one world + wasi:http;
there is no "cow-protocol WASI"), and folds in transport-only adapters (Q1),
opaque host status (Q2/R6), install-time schema handshake (R7), EVM-only 0.1
(Q5), and #[venue] as the blessed path (Q6).
@mfw78 mfw78 force-pushed the docs/intent-architecture branch from 2a49526 to 23aa95d Compare July 15, 2026 07:35
@mfw78 mfw78 changed the base branch from develop to dev/m1 July 15, 2026 07:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

base: develop Open PR targets develop — merge FIRST, before the dev/m1 integration PRs.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: record the intent architecture (venue adapters, egress guard)

2 participants