# ADR: an explicit boundary between input, intent and action

Status: accepted for developer API v1. September 30, 2026.

The immersive website demonstrates a future interface. It is not a sensor. The founder reports voice-to-action as fully implemented and motion-to-action in development. The founder reports smell R&D underway with several universities; institutions and agreements are not disclosed or independently verified. The external acquisition deployments still require current integration evidence.

## Decision

The shared `sense-domain` Rust crate validates caller-supplied transcripts or normalized gesture identifiers and resolves declarative rules into typed action intents. It has no network, browser, database or shell dependency. Axum and Cloudflare Workers are HTTP adapters around that same policy. The Worker exports OpenAPI from its actual handler and schema definitions; the documentation build consumes this export together with the same capability, action and template catalogs.

The Rust CLI is an independent transport client and product: it has its own Cargo workspace, lockfile, manual and documentation page, and it shares no code with any SDK. The TypeScript, Python, Go and Rust SDKs each expose a transport port and an explicit handler registry. Reading an intent does not execute it. The application registers handlers, controls permissions and decides when to dispatch. This separation supports custom navigation, text, media, scenes and workflow integrations without giving the public API an arbitrary execution primitive.

## Ports and responsibilities

| Boundary              | Responsibility                                                                                                                                                                       |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Acquisition adapter   | Obtain explicit user consent; turn audio or movement into a supplied transcript or gesture. Separate provider configuration and evidence are required.                               |
| Domain resolver       | Validate bounded requests; normalize exact matches; apply enabled and confidence rules; emit intents deterministically.                                                              |
| HTTP adapters         | JSON, CORS, request limits, rate limiting, errors and generated OpenAPI.                                                                                                             |
| SDK transport         | Base URL, timeout, cancellation, typed errors; no implicit action retries.                                                                                                           |
| Application handler   | Execute a known action under application permissions; implement confirmation and idempotency where appropriate.                                                                      |
| Documentation adapter | Generate endpoint/schema/catalog reference and per-sense artifacts from code; render the prompt-first developer pages; supplement them with reviewed narrative and proposed roadmap. |

## Alternatives and tradeoffs

Direct server-side execution of submitted shell commands or webhook URLs would introduce remote execution and SSRF risks with no authenticated ownership model. It is excluded. A separate hand-written OpenAPI file would drift from two transports; code-derived types and adapter contract tests replace it. Introducing a sensor or transcription provider without verified configuration would misrepresent acquisition; adapters remain explicit and independently testable.

The stateless public resolver intentionally stores no submitted input. Operational infrastructure may still retain request metadata. No health-information service, medical inference, SOC 2 report, ISO certification or HIPAA-ready deployment is implied. Contact capture uses its separate existing consent and persistence boundaries.

## Documentation experience

Decision, October 1, 2026: the developer site is an experience, not a manual. It is split into Live, CLI, SDK, Downloads and Reference pages under `/developers/`. Installing, updating and wiring are prompts the visitor hands to a coding agent; no page asks a person to type a command. Prompts read the published download manifest, verify SHA-256 before running anything, and end by showing a live 200. Every 200 on the Live, CLI and SDK pages is a real same-origin API call: a pulse travels to the API, the HTTP status rolls into place and the actual JSON payload unfolds. Reduced motion shows the same final state without animation. Commands, flags, method signatures and the error catalogue remain available, collapsed under "Under the hood" and on the Reference page, because agents still need them.

`developer/experience.js` holds the prompt and language catalog at build time; `scripts/developer-docs.js` renders pages; `developer/signal.js` (live stage), `developer/downloads.js` (manifest interpretation) and `developer/docs.js` (page wiring) run in the browser. Prompts contain live slots for the serving origin and the chosen language.

October 15 navigation refinement: `developer/navigation.js` keeps language/return URL policy separate from page rendering and applies the embedded navigation catalog through a DOM adapter. All five destinations, including Reference, share one navigation group; the mobile group wraps to keep every destination visible. Every page has a prominent same-tab experience return to `/site/?lang=en|fr`, and internal navigation carries that language forward. Only the navigation and existing bilingual entrance are localized; authored API prose and external client contracts are unchanged.

Four SDKs are maintained, tested and packaged here: TypeScript, Python, Go (standard library) and Rust (rustls, optional reqwest adapter). For any other language, the SDK page offers a prompt that has the visitor's agent generate a client from the published OpenAPI and reference. The page and the prompt label such code as generated, not an Ursly package. Ursly does not test those clients.

## Contract and evolution

The API prefix is `/api/v1`. Clients must use the published schema and handle structured errors and unavailable senses. Changes to action types, matching semantics or payload validation require domain, adapter and SDK contract tests. Breaking changes require a new major API or SDK version. Confidence is supplied by the acquisition adapter, not measured or inferred by this resolver. Rule order determines intent order; application handlers own deduplication and safeguards for irreversible actions.

October 15 product-stage correction: the code-derived capability catalog describes Motion as `development`, following the owner's latest status. `apiAvailable: true` and `acquisition: client_gesture` continue to describe only supplied-identifier intent resolution. TypeScript, Python, Go and Rust source validators/types add `development` and retain `beta` for earlier responses; invalid values are still rejected. This does not retrofit immutable 0.1.0 SDK archives, whose closed validators may reject the new catalog value. Distribution and compatibility of a separately versioned new client release require their own checks. The metadata update neither changes acquisition capability nor hand-maintains an OpenAPI artifact.

## Reproduction and evidence

Run the Docker Compose stack for the Axum adapter and static docs. Run the Worker host tests and WASM lint for deployment compatibility. The developer release workflow packages checked binaries and SDK archives, records the exact source SHA and SHA-256 checksums, retains GitHub artifacts and publishes the same archives through the website. The first release and custom documentation domain each require their own verification; configuration alone is not publication evidence.

Official sources and version checks are recorded in developer-api-evidence.md, developer-release-evidence.md, the CLI/SDK documentation and evidence.md. Proposed compliance work and sources are maintained in `developer/roadmap.json`.

## Documentation origin and public name

Ursly is the public brand; existing CLI/SDK import names remain stable. `DOCS_HOST` configures the separate developer origin. A pure path policy in `cloudflare-worker/src/docs_routing.rs` maps only GET/HEAD requests on that exact hostname to bundled documentation; API, experience, downloads and main-host paths retain their existing adapters. The generated agent references consume the same exported schema/catalogs as the HTML documentation. The animated entrance is progressive enhancement: direct anchors, machine references and readable documentation require no animation or identity check. Deployment verification compares the generated document at root and all relative asset aliases byte for byte.
