@mhome/app-facade-protocol 1.126.0 → 1.127.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/contract/agent-llm-v1.md +56 -0
- package/contract/agent-profile-media-v1.md +39 -0
- package/contract/authorization-v1.md +57 -0
- package/contract/client-appearance-v1.md +32 -0
- package/contract/client-page-v1.md +42 -0
- package/contract/host-directory-v1.md +18 -0
- package/contract/host-management-v1.md +54 -0
- package/contract/nfc-v1.md +48 -0
- package/contract/wave-v1.md +33 -0
- package/manifest/app-facade.v1.json +13 -2
- package/manifest/authorization.v1.json +6 -2
- package/manifest/host-provision-targets.v1.json +1 -1
- package/manifest/hub-targets.v1.json +1 -1
- package/manifest/pod-targets.v1.json +1 -1
- package/manifest/routing.v1.json +3 -2
- package/manifest/targets.v1.json +1 -1
- package/package.json +1 -1
- package/protocol.json +1 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Agent LLM settings
|
|
2
|
+
|
|
3
|
+
`agent_llm` and `schema/agent-llm.v1.schema.json` own the public business DTOs.
|
|
4
|
+
The standard Facade response envelope carries these values in `data` for Full;
|
|
5
|
+
Essential uses the shared Agent projection and YAML presentation.
|
|
6
|
+
|
|
7
|
+
## Read ownership
|
|
8
|
+
|
|
9
|
+
| Target | Input | Result |
|
|
10
|
+
| --- | --- | --- |
|
|
11
|
+
| `/app/agent/llm/summary` | Empty | `Summary` for the active `llmMode` |
|
|
12
|
+
| `/app/agent/llm/provider/list` | Optional `llmMode`; defaults to active mode | `ProviderList` for the requested mode |
|
|
13
|
+
| `/app/agent/llm/provider/get` | `provider`, `llmMode` | `ProviderDetail`, used by UI Operations and native Agent verification |
|
|
14
|
+
| `/app/agent/llm/mapping/list` | Empty | `MappingList` for the active `llmMode` |
|
|
15
|
+
|
|
16
|
+
Reading a mode does not activate it. Provider reads do not initialize mappings.
|
|
17
|
+
The summary has no embedded inactive Local settings. A local Space's UI can read
|
|
18
|
+
Local providers explicitly while its active LLM mode is Cloud. A cloud Space
|
|
19
|
+
cannot hold Local provider configuration.
|
|
20
|
+
|
|
21
|
+
Provider catalog facts and saved configuration are distinct. `configuration` is
|
|
22
|
+
present for Local providers and null for platform-managed Cloud providers.
|
|
23
|
+
`hasCredential` means a stored credential exists; it is not a remote authentication
|
|
24
|
+
check. `ready` and `readinessByUseCase` describe discovery and runtime availability.
|
|
25
|
+
Public credential settings contain only region, credential profile and workspace
|
|
26
|
+
ID. Keys, tokens, transport settings and provider model aliases remain private.
|
|
27
|
+
|
|
28
|
+
Models appear once in `providerModels`, or in `models` for a single provider.
|
|
29
|
+
`contextWindowTokens` preserves catalog information; unknown values remain null.
|
|
30
|
+
`generationControls` describes controls supported by both model and execution
|
|
31
|
+
backend. Metadata source is independent of LLM mode: Local provider catalog
|
|
32
|
+
metadata can be supplied by the cloud.
|
|
33
|
+
|
|
34
|
+
## Writes and mode selection
|
|
35
|
+
|
|
36
|
+
Mode selection changes the active configuration. It does not delete or overwrite
|
|
37
|
+
Cloud mappings, Local mappings or Local provider credentials. Mapping writes use
|
|
38
|
+
the active mode. Credential changes always target Local configuration, require a
|
|
39
|
+
local Space and a human UI/CLI caller, and do not switch modes. Native Agent
|
|
40
|
+
UserActions hand off to the Provider Operation; MCP and external Skills cannot
|
|
41
|
+
mutate provider credentials.
|
|
42
|
+
|
|
43
|
+
The frontend settings controller owns the authoritative loaded snapshot. A failed
|
|
44
|
+
mode write retains it. A successful write clears the previous mode's snapshot
|
|
45
|
+
before reloading; reload failure reports that the write succeeded and offers retry.
|
|
46
|
+
Provider Operations own a separate single-provider controller and never fetch the
|
|
47
|
+
whole summary or session policy.
|
|
48
|
+
|
|
49
|
+
## Presentation
|
|
50
|
+
|
|
51
|
+
Full preserves the public business DTO, including nullable fields. Essential
|
|
52
|
+
omits absent values and internal catalog/configuration metadata while retaining
|
|
53
|
+
mode, provider identity, configuration/readiness, model choices and actionable
|
|
54
|
+
model controls. Both surfaces preserve result status, warnings and errors.
|
|
55
|
+
|
|
56
|
+
Each use case has one `requirements` object and one effective provider/model selection. Mapping writes accept `useCase`, `provider`, `model` and generation preferences. Requests and execution snapshots carry no model tier. Local/Cloud execution selection remains independent.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Agent Profile media
|
|
2
|
+
|
|
3
|
+
Memory and Identity stay Space-shared Markdown strings. Public get responses use
|
|
4
|
+
`{ content }`; save keeps its completion-only success envelope. The same Facades
|
|
5
|
+
serve UI, CLI, MCP and native Agent workflows; only the native update tool merges
|
|
6
|
+
new facts before calling save. There is no separate image-profile DTO.
|
|
7
|
+
|
|
8
|
+
An actual CommonMark image node `` is a retained
|
|
9
|
+
reference. Reference-style images are supported and canonicalized inline. Prose,
|
|
10
|
+
plain links and fenced/inline code are not image ownership declarations. Image
|
|
11
|
+
labels are descriptive; adjacent prose records the approved identity or fact.
|
|
12
|
+
No XML tag, signed delivery URL, local path or embedded binary is persisted.
|
|
13
|
+
|
|
14
|
+
The authoritative Space owner validates each reference's tenant, Space and Image
|
|
15
|
+
kind, reads its source bytes and creates an independent manual/standard Artifact
|
|
16
|
+
with a random Profile creation identity. Each document keeps its own reference
|
|
17
|
+
set. Existing references owned by that same document are reused. New references
|
|
18
|
+
from another document are copied, so deleting one document's reference cannot
|
|
19
|
+
invalidate another's. Source expiration/deletion does not affect committed copies.
|
|
20
|
+
|
|
21
|
+
Text, owned URIs, pending retired URIs and a new internal revision publish in one
|
|
22
|
+
conditional write. A stale save fails and requires a new read/reconciliation. A
|
|
23
|
+
known rejection cleans newly created copies only; an uncertain publication error
|
|
24
|
+
never deletes potentially committed content. This revision is not a public merge
|
|
25
|
+
protocol and does not prevent a caller from submitting already-stale text.
|
|
26
|
+
|
|
27
|
+
After publication, context is invalidated and removed owned images are deleted.
|
|
28
|
+
Failed retired deletions remain recorded and are retried on the next save. The
|
|
29
|
+
save worker completes publication/cleanup after caller cancellation. Process
|
|
30
|
+
termination before publication or failed cleanup of unpublished copies can leave
|
|
31
|
+
unreferenced Artifacts; there is no global reference collector or cross-store
|
|
32
|
+
transaction. Storage failures never justify deleting possibly committed content.
|
|
33
|
+
|
|
34
|
+
Callers re-read after saving to obtain canonical rewritten URIs. Full reads return
|
|
35
|
+
structured `{content}` and essential reads serialize the same complete text,
|
|
36
|
+
including multiline Markdown. Neither mode embeds image bytes. Native `media`
|
|
37
|
+
Skill `artifact_resolve` attaches actual Image content to the next model request;
|
|
38
|
+
CLI hosts must resolve and view an output file or supported expiring image URL;
|
|
39
|
+
MCP returns its existing image content block. Resolving is scoped, not public access.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Business authorization
|
|
2
|
+
|
|
3
|
+
`manifest/authorization.v1.json` is the sole operation policy catalog consumed
|
|
4
|
+
by MeowCore and Lion. Rust uses `authorization::required`; Lion loads this same
|
|
5
|
+
file from the checksum-pinned protocol package into its runtime resources.
|
|
6
|
+
Both run `fixtures/authorization/decisions.json`. There is no permissive default.
|
|
7
|
+
|
|
8
|
+
The verified principal is either User or Space. User operations require a User
|
|
9
|
+
and retain their domain ownership checks. Space operations use READ, WRITE and
|
|
10
|
+
MANAGE: current members have WRITE, owners have MANAGE, and a Space principal
|
|
11
|
+
has WRITE only in its exact tenant and Space. A supplied owner role never
|
|
12
|
+
promotes a Space principal. Personal credentials, enrolling users and billing
|
|
13
|
+
accounts cannot substitute for the principal.
|
|
14
|
+
|
|
15
|
+
The `nodePrefix` is explicit delegation, not a wildcard execution grant. Static
|
|
16
|
+
operations take precedence. The authoritative Core must also enforce the exact
|
|
17
|
+
operation policy from the currently authenticated Node registration before
|
|
18
|
+
forwarding. MCP grants and Agent tool allowlists are additional restrictions.
|
|
19
|
+
|
|
20
|
+
User and Agent entrypoints use the same policies. Agent execution retains its
|
|
21
|
+
verified originating principal, including through cloud forwarding, prepared
|
|
22
|
+
actions and retries. Each execution rechecks current membership; confirmation
|
|
23
|
+
does not freeze or elevate permissions. Core durable actions store a typed
|
|
24
|
+
principal; cloud personal actions bind the verified User. Core records missing
|
|
25
|
+
their principal are rejected without legacy conversion.
|
|
26
|
+
|
|
27
|
+
`DelegatedCall` is private to the authenticated Lion-to-Core bridge. Its
|
|
28
|
+
`authority` is either `caller` with the original principal, or `service` for
|
|
29
|
+
the exact `serviceOperations` allowlist. Client input never accepts this
|
|
30
|
+
envelope, and Agent forwarding cannot select service authority. `MwsClientInfo`
|
|
31
|
+
is routing metadata, not the authority for these business calls.
|
|
32
|
+
Internal `/dispatch/app/*` calls accept direct domain execution only. Public
|
|
33
|
+
`/invoke/app/*` forwarding instead carries the complete `ForwardedCall` and enters
|
|
34
|
+
the same Core action orchestration as LAN calls. These are distinct private
|
|
35
|
+
operations, not compatibility formats. The latter preserves Client identity or
|
|
36
|
+
trusted MCP/Agent invocation binding and returns a tagged JSON response containing the complete Facade result.
|
|
37
|
+
User Client cloud ingress and MCP require a User principal. A verified Agent run
|
|
38
|
+
may carry its original Space principal only back to that bound Space; it does
|
|
39
|
+
not issue a cloud credential to a Space Client or invent an acting User.
|
|
40
|
+
|
|
41
|
+
Prepared state belongs to the operation's business executor. Changing Client
|
|
42
|
+
transport does not create a second action record. MCP's cloud continuation owns
|
|
43
|
+
its interaction/grant lifecycle, not a copy of Core business state. Agent adapters
|
|
44
|
+
carry the executor's prepared reference rather than querying a cloud action table.
|
|
45
|
+
Deploy this contract and its consumers together. Drain or expire pending
|
|
46
|
+
interactions before cutover; do not translate old references, migrate action rows,
|
|
47
|
+
or automatically replay operations after uncertain delivery.
|
|
48
|
+
|
|
49
|
+
Host administration retains its independent authentication and ownership checks;
|
|
50
|
+
the User policies on Host operations do not grant Host administration. Space Pod
|
|
51
|
+
enrollment requires the current Space owner, as defined by its commissioning
|
|
52
|
+
contract. User Pod approval uses the current personal login.
|
|
53
|
+
|
|
54
|
+
Old cloud dispatch envelopes and duplicated per-runtime policy tables are not
|
|
55
|
+
supported. Publish the Foundation package and synchronize consumers before a
|
|
56
|
+
runtime deployment. A Gradle source override is available only for explicit
|
|
57
|
+
joint source validation, never as an automatic production fallback.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Client appearance
|
|
2
|
+
|
|
3
|
+
`/app/client/appearance/report` uses the canonical FacadeCall envelope and the
|
|
4
|
+
normal Space-mode execution rule. User Client reports may enter directly or
|
|
5
|
+
through authenticated Cloud forwarding, preserving the original live Client identity. Its input is the six-field snapshot in
|
|
6
|
+
`schema/client-appearance.v1.schema.json`; success returns `{}`.
|
|
7
|
+
|
|
8
|
+
Only the authenticated, live UI Client may report its own snapshot in the Space
|
|
9
|
+
it is displaying. The installation and transport identity come from ingress,
|
|
10
|
+
never from input. Both User and Space Clients use the existing Space admission.
|
|
11
|
+
The report forwards to `basic.app.state.appearance` subscribers; it does not
|
|
12
|
+
create backend preference storage. Clients report after local settings or
|
|
13
|
+
capability changes, system appearance changes, and connection/focus restoration.
|
|
14
|
+
|
|
15
|
+
The public capabilities are `basic.app.state.appearance` and
|
|
16
|
+
`basic.app.command.setAppearance`. Discovery is part of those schemas. Backend
|
|
17
|
+
native functions invoke `/app/invoke/discovery.appearance`,
|
|
18
|
+
`/app/invoke/state.appearance`, or `/app/invoke/command.setAppearance` with a
|
|
19
|
+
Space-scoped server request. The Client replies once over the original connection
|
|
20
|
+
with the original target, signature, Space, and source peer. An error payload is
|
|
21
|
+
an invocation failure, including for commands without response data.
|
|
22
|
+
|
|
23
|
+
Changes validate the entire patch before applying it to the Client's persisted
|
|
24
|
+
Space preferences. Omitted settings are unchanged; no reset or separate options
|
|
25
|
+
operation is provided. `background` is the public name; opacity is retained for
|
|
26
|
+
Classic backgrounds while `cardOpacityApplied` is false. Presets come from the
|
|
27
|
+
target Client's discovery rather than a second backend catalog.
|
|
28
|
+
|
|
29
|
+
A persistent appearance subscription resolves `a:current` before calculating its
|
|
30
|
+
endpoint and storing its request. The first resolution is retained in condition
|
|
31
|
+
memory, so both re-evaluation and recovery reuse the concrete Client identity
|
|
32
|
+
without requiring the creator's transient connection context.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Client page navigation
|
|
2
|
+
|
|
3
|
+
`/app/client/page/report` forwards the authenticated Client's observed navigation
|
|
4
|
+
snapshot to `basic.app.state.page` subscriptions in its focused Space. It uses
|
|
5
|
+
the FacadeCall envelope and spaceRead authorization, accepts no caller-selected
|
|
6
|
+
Client identity, and stores no second navigation state. The canonical payload
|
|
7
|
+
is `schema/client-page.v1.schema.json`; success returns `{}`.
|
|
8
|
+
|
|
9
|
+
`current` describes the topmost registered navigation view. A drawer requires
|
|
10
|
+
`base`, the underlying full page. Page-specific navigation identifiers belong
|
|
11
|
+
in Dynamic `payload`; drafts, page contents, transient menus and dialogs are
|
|
12
|
+
excluded. Unregistered views use `page: unknown`.
|
|
13
|
+
|
|
14
|
+
`basic.app.state.page` and `basic.app.command.openPage` use client-dependent
|
|
15
|
+
page discovery. Native functions request `/app/invoke/discovery.page`,
|
|
16
|
+
`/app/invoke/state.page` and `/app/invoke/command.openPage`. Commands reply only
|
|
17
|
+
when the target is observed active; timeout does not prove navigation was
|
|
18
|
+
cancelled. State reporting converges to the latest snapshot after reconnect;
|
|
19
|
+
it is not a durable log of every intermediate transition.
|
|
20
|
+
|
|
21
|
+
Persistent subscriptions bind `a:current` to a concrete Client before endpoint
|
|
22
|
+
hashing. Deploy the manifest, both runtimes and Client page host together.
|
|
23
|
+
|
|
24
|
+
## Current-client operations
|
|
25
|
+
|
|
26
|
+
| Target | Input definition | Output definition | Admission |
|
|
27
|
+
| --- | --- | --- | --- |
|
|
28
|
+
| `/app/client/page/list` | `emptyRequest` | `catalogResponse` | spaceRead |
|
|
29
|
+
| `/app/client/page/current` | `emptyRequest` | `navigationResponse` | spaceRead |
|
|
30
|
+
| `/app/client/page/open` | `openRequest` | `navigationResponse` | spaceWrite |
|
|
31
|
+
|
|
32
|
+
These direct-only operations use the trusted invocation's current Client and Space.
|
|
33
|
+
Input never selects a Client or Space, a transport target, a URL, or a raw app route.
|
|
34
|
+
Missing/offline Client context fails without selecting another Client. The executor
|
|
35
|
+
follows Space mode and reuses AppInvoke's scoped request/reply transport. Page
|
|
36
|
+
availability and payload validation belong to the Client's single page registry.
|
|
37
|
+
A successful open returns the observed navigation state, not just delivery acceptance.
|
|
38
|
+
Navigation blockers, redirects and errors propagate. No HITL, persisted operation,
|
|
39
|
+
extra navigation state or automatic retry is introduced.
|
|
40
|
+
|
|
41
|
+
The native Agent exposes these operations through its bundled `app` Skill. There
|
|
42
|
+
are no dedicated MCP tools or CLI commands for them.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Host registration directory
|
|
2
|
+
|
|
3
|
+
`/app/host/directory/list` takes empty input and reads the caller's Admin Host registrations
|
|
4
|
+
and the current Space's Host registrations (Space member required). The result is
|
|
5
|
+
`{hosts, observedAtMs}`. Each row contains `hostId`, `hostName`, `env`, `mode`,
|
|
6
|
+
`registered: true`, `reachability: "unknown"`, `authorizationState: "unknown"`.
|
|
7
|
+
|
|
8
|
+
These are historical successful registrations, including offline Hosts. They do
|
|
9
|
+
not grant current access or attest that an administrator remains in the Host ACL.
|
|
10
|
+
Names are registration snapshots. No keys, tokens, signed challenges or ACLs leave
|
|
11
|
+
this directory. Native list composition adds current observations using existing
|
|
12
|
+
Host authentication; only authenticated live results establish current access.
|
|
13
|
+
|
|
14
|
+
A signed-in personal Client may omit the Space envelope to read only its Admin
|
|
15
|
+
registrations, including before its first Space exists. With a Space envelope,
|
|
16
|
+
Space membership is required before that Space's directory is read.
|
|
17
|
+
Commissioning, claims, permission prompts and runtime installation are unchanged
|
|
18
|
+
by this directory contract.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Host management
|
|
2
|
+
|
|
3
|
+
All operations require a personal User principal. They accept business input only;
|
|
4
|
+
Host authentication, identity pinning and transport selection remain internal.
|
|
5
|
+
The request schemas are in `schema/host-management.v1.schema.json` and the public
|
|
6
|
+
targets in the `hostManagement` manifest section.
|
|
7
|
+
|
|
8
|
+
`/app/host/list` returns registrations together with current observations and an
|
|
9
|
+
individual `detail` observation. Offline records remain. Each observation has
|
|
10
|
+
`status`, `data`, `stale` and an error on failure. Host metadata never grants
|
|
11
|
+
management access. Native list implementations use `/app/host/directory/list` as
|
|
12
|
+
the historical input, avoiding a request back into the public list composition.
|
|
13
|
+
|
|
14
|
+
Business execution follows Space mode, independently of LLM placement:
|
|
15
|
+
|
|
16
|
+
- Local Space: Core composes the list and sends Host commands through its existing
|
|
17
|
+
authenticated LAN transport. Remote App/MCP requests reach that same Core via
|
|
18
|
+
cloud forwarding. Core obtains cloud-owned directory metadata and user grants
|
|
19
|
+
through the private `/bridge/management/control` endpoint; this endpoint neither
|
|
20
|
+
dispatches Host commands nor impersonates a Client.
|
|
21
|
+
- Cloud Space: cloud executes business through the initiating personal desktop
|
|
22
|
+
Client. No other online App is selected. MCP, web and mobile have no such
|
|
23
|
+
transport and management calls fail if no suitable route exists. List still
|
|
24
|
+
returns registrations with unavailable observations.
|
|
25
|
+
|
|
26
|
+
Host mode, ACL and Space ownership remain authoritative. The private bridge is
|
|
27
|
+
bound to its authenticated tenant/Space and rechecks personal User read access;
|
|
28
|
+
existing grant issuers check Host authorization. The fixed operations are Host
|
|
29
|
+
and personal Pod directory reads, Host access issuance, administrator application
|
|
30
|
+
preparation and signed receipt confirmation. It accepts no arbitrary target.
|
|
31
|
+
Public signing endpoints remain Client-only and are not Agent/MCP tools.
|
|
32
|
+
|
|
33
|
+
The private `/app/host/execute` Client request is a fixed management transport,
|
|
34
|
+
not a capability or public Facade. It accepts no service switch or admin removal.
|
|
35
|
+
A missing route fails; a mutation is never replayed through another transport.
|
|
36
|
+
If a cloud entrypoint cannot reach a local Space's Core, list alone may return
|
|
37
|
+
cloud registrations with unavailable observations and `sourceErrors.hub`.
|
|
38
|
+
Authorization errors and registration read failures remain errors.
|
|
39
|
+
|
|
40
|
+
Administrator request/approval credentials and signed receipts remain internal.
|
|
41
|
+
A successful approval receipt must be confirmed before `complete: true`; pending
|
|
42
|
+
requests do not grant access. Results exclude credentials, including nested ones.
|
|
43
|
+
|
|
44
|
+
Service install prepares exactly the selected service and submits its existing
|
|
45
|
+
Host operation. Restart uses a stable invocation-derived operation identity.
|
|
46
|
+
The returned Host operation state is `queued`, `running`, `succeeded` or `failed`;
|
|
47
|
+
acceptance is not completion. List details include current operations. There is
|
|
48
|
+
no public plan, start or operation-polling tool. The local CLI waits internally.
|
|
49
|
+
|
|
50
|
+
Permission reads never prompt. Permission requests belong to the target's local
|
|
51
|
+
UI/CLI. Native Agent UserAction opens the existing desktop permission UI, then
|
|
52
|
+
reads actual Host state on continuation. MCP cannot invoke that local interaction.
|
|
53
|
+
Service enable/disable is reserved for human UI/CLI. These management entrypoints
|
|
54
|
+
do not alter commissioning, claim proofs, Admin, SpaceSelf or SpaceDep semantics.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# NFC management v1
|
|
2
|
+
|
|
3
|
+
The six shared App Facades use the canonical `control`/`input` request and
|
|
4
|
+
`status`/`data`/`error`/`warnings` result. Identity and Space authorization come
|
|
5
|
+
from transport context, never input. Source directory is cloud-owned; all other
|
|
6
|
+
operations use the Space's authoritative Core or cloud executor. The schema is
|
|
7
|
+
`schema/nfc.v1.schema.json`; Rust DTOs and the Lion Java binding are checked against
|
|
8
|
+
`fixtures/nfc.conformance.json`. Schema validates structural shape; normalization
|
|
9
|
+
also checks whitespace, source identity uniqueness and merged policy constraints.
|
|
10
|
+
|
|
11
|
+
| Target | Input | Full success data | Mode |
|
|
12
|
+
| --- | --- | --- | --- |
|
|
13
|
+
| `/app/nfc/list` | optional `createState`: active (default), pending, all | `{nfcTags:[{tagId,spaceId,name,description,policy,trustedSources,createState,createdAt,lastUsedAt}]}` | direct, Space read |
|
|
14
|
+
| `/app/nfc/sources/list` | `{}` | `{sources:[{sourceType,sourceId,sourceName}]}` | direct, Space read, cloud |
|
|
15
|
+
| `/app/nfc/create` | required name, policy; optional description, trustedSources | `{tagId,createState:"pending",writePayload}` | direct, Space write |
|
|
16
|
+
| `/app/nfc/activate` | `{tagId}` | no data; `{status:"success"}` | direct, Space write |
|
|
17
|
+
| `/app/nfc/update` | tagId and at least one of name, description, policy, trustedSources | no data | direct, Space write |
|
|
18
|
+
| `/app/nfc/delete` | `{tagIds:[...]}`, 1–100 unique IDs | no data | direct or prepared, Space write |
|
|
19
|
+
|
|
20
|
+
Name is trimmed, nonempty and unique case-insensitively within the tenant/Space,
|
|
21
|
+
including pending records. Duplicate create never removes or replaces pending.
|
|
22
|
+
Description defaults to empty; update omission preserves, empty clears, null fails.
|
|
23
|
+
Unknown fields and client-supplied lifecycle/timestamps fail.
|
|
24
|
+
Policy is ALL_PHONE or CUSTOM_PHONE. Sources have type phone and a nonempty unique
|
|
25
|
+
sourceId, plus optional sourceName (default empty). ALL_PHONE clears sources;
|
|
26
|
+
CUSTOM_PHONE requires at least one after patching. Source directory only includes
|
|
27
|
+
enabled registered phones advertising event.nfc. It is a discovery snapshot,
|
|
28
|
+
not an online status or runtime permission guarantee.
|
|
29
|
+
|
|
30
|
+
Create only creates a record. `writePayload` is `mhomeai://nfc/{spaceId}:{tagId}`.
|
|
31
|
+
A phone writes that exact content; activate is called only on physical success.
|
|
32
|
+
Only activation changes pending to active and sets createdAt. Repeating activation
|
|
33
|
+
preserves createdAt and lastUsedAt. Cancelled/failed physical writes explicitly
|
|
34
|
+
delete pending; read/list/sync do not clean it up. No TTL or background cleanup.
|
|
35
|
+
Update patches configuration without activating or resetting metadata.
|
|
36
|
+
Delete missing IDs is idempotent, has no deleted-count guarantee, does not erase
|
|
37
|
+
physical tags, and does not promise cross-record atomicity on cloud storage.
|
|
38
|
+
Prepared preview includes requested IDs, found state, name and creation state;
|
|
39
|
+
last-use observations do not invalidate a preview.
|
|
40
|
+
|
|
41
|
+
Full list timestamps are Unix milliseconds. Essential retains all business fields
|
|
42
|
+
in YAML, localizes positive timestamps, and preserves zero as unknown. Mutations
|
|
43
|
+
with no business result return only canonical status in either detail mode.
|
|
44
|
+
|
|
45
|
+
Physical tap (`/nfc/tap` on Core, `/api/v1/nfc/tap` on cloud/mobile) remains an
|
|
46
|
+
authenticated native ingress, not a management Facade or CLI/MCP tool. It checks
|
|
47
|
+
Space, active state and source policy. Successful acceptance observes lastUsedAt
|
|
48
|
+
best effort; persistence failure does not reject the tap. List and sync are read-only.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Native Wave LAN admission
|
|
2
|
+
|
|
3
|
+
These Hub-routed App Facades require current-Space Manage access and an active
|
|
4
|
+
local Hub. They do not make Wave devices Hosts, Nodes or Plugins. No device URL,
|
|
5
|
+
Space/Hub selector, grant, certificate or private key is an input/output.
|
|
6
|
+
|
|
7
|
+
- `/app/wave/discover`: `{}` -> `{candidates:[{candidateId,deviceId,proof,purpose}]}`.
|
|
8
|
+
Core browses `_meow-wave._tcp.local.` and identifies bounded LAN candidates.
|
|
9
|
+
Results are untrusted location hints, scoped to this caller, Space and Hub
|
|
10
|
+
generation, expiring after two minutes. They never grant operation authority.
|
|
11
|
+
- `/app/wave/pair`: `{candidateId,pin?}` -> AdmissionResult below. This is a direct
|
|
12
|
+
authenticated App interaction; Agent/MCP/cloud delegation cannot submit PINs.
|
|
13
|
+
PIN6 is required when the selected device requires it. Omitting it is allowed
|
|
14
|
+
only for an explicitly opened initial local-claim window. No fallback occurs.
|
|
15
|
+
Retry reconciles an existing candidate; an uncertain result never rotates a key.
|
|
16
|
+
- `/app/wave/list`: `{}` -> `{bindings:[{deviceId,grantState}]}`. States are
|
|
17
|
+
`candidate` or `committed`; this is authorization bookkeeping, not Device/Twin
|
|
18
|
+
inventory, online state or evidence that a candidate committed on the device.
|
|
19
|
+
- `/app/wave/refresh`: `{deviceId}` -> AdmissionResult. Reconcile the same saved
|
|
20
|
+
credential, validate full Entity self-description against installed contracts,
|
|
21
|
+
then use ordinary Twin source synchronization. It cannot open a pairing window.
|
|
22
|
+
|
|
23
|
+
AdmissionResult is `{deviceId,grantState,inventoryState,entityIds,reason?}`.
|
|
24
|
+
`inventoryState:ready` means existing inventory synchronization completed;
|
|
25
|
+
`unavailable` with a committed grant is a partial result. Authorization may have
|
|
26
|
+
committed even when metadata/contract acquisition or inventory synchronization
|
|
27
|
+
fails. A later refresh uses the existing grant, without consuming another slot.
|
|
28
|
+
Missing/uninstalled or incompatible contracts never install code automatically.
|
|
29
|
+
Normal Device/capability APIs own subsequent observations, control and subscriptions.
|
|
30
|
+
|
|
31
|
+
Credentials remain Core-local, outside ordinary Connection/privateData/Twin/sync.
|
|
32
|
+
Explicit Hub migration is outside this increment. Removal/invitation UI, BLE and
|
|
33
|
+
physical target acceptance remain separate increments. Commands are never replayed.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest": "mhome.app-facade.v1",
|
|
3
|
-
"contractVersion": "1.
|
|
3
|
+
"contractVersion": "1.127.1",
|
|
4
4
|
"callSchema": "schema/facade-call.v1.schema.json",
|
|
5
5
|
"routing": "manifest/routing.v1.json",
|
|
6
6
|
"routingSchema": "schema/routing.v1.schema.json",
|
|
@@ -443,7 +443,9 @@
|
|
|
443
443
|
},
|
|
444
444
|
"deviceSources": {
|
|
445
445
|
"contract": "contract/entity-v1.md",
|
|
446
|
-
"uiRequestTargets": [
|
|
446
|
+
"uiRequestTargets": [
|
|
447
|
+
"/app/device/source/resolve"
|
|
448
|
+
]
|
|
447
449
|
},
|
|
448
450
|
"entity": {
|
|
449
451
|
"contract": "contract/entity-v1.md",
|
|
@@ -473,6 +475,15 @@
|
|
|
473
475
|
"eventTargets": [
|
|
474
476
|
"/user/navigation/changed"
|
|
475
477
|
]
|
|
478
|
+
},
|
|
479
|
+
"wave": {
|
|
480
|
+
"contract": "contract/wave-v1.md",
|
|
481
|
+
"requestTargets": [
|
|
482
|
+
"/app/wave/discover",
|
|
483
|
+
"/app/wave/pair",
|
|
484
|
+
"/app/wave/list",
|
|
485
|
+
"/app/wave/refresh"
|
|
486
|
+
]
|
|
476
487
|
}
|
|
477
488
|
},
|
|
478
489
|
"authorization": "manifest/authorization.v1.json",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"contractVersion": "1.
|
|
2
|
+
"contractVersion": "1.127.1",
|
|
3
3
|
"operations": {
|
|
4
4
|
"/app/agent/context/get": "spaceRead",
|
|
5
5
|
"/app/agent/credit/usage": "spaceRead",
|
|
@@ -368,7 +368,11 @@
|
|
|
368
368
|
"/pod/talk/speech/prepare": "spaceWrite",
|
|
369
369
|
"/pod/talk/turn/submit": "spaceWrite",
|
|
370
370
|
"/pod/talk/view/get": "spaceRead",
|
|
371
|
-
"/app/entity/state/get": "spaceRead"
|
|
371
|
+
"/app/entity/state/get": "spaceRead",
|
|
372
|
+
"/app/wave/discover": "spaceManage",
|
|
373
|
+
"/app/wave/pair": "spaceManage",
|
|
374
|
+
"/app/wave/list": "spaceManage",
|
|
375
|
+
"/app/wave/refresh": "spaceManage"
|
|
372
376
|
},
|
|
373
377
|
"nodePrefix": "/app/plugin/",
|
|
374
378
|
"serviceOperations": [
|
package/manifest/routing.v1.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest": "mhome.app-facade.routing.v1",
|
|
3
|
-
"contractVersion": "1.
|
|
3
|
+
"contractVersion": "1.127.1",
|
|
4
4
|
"targetPrefix": "/app/",
|
|
5
5
|
"default": {
|
|
6
6
|
"execution": "spaceMode"
|
|
@@ -82,7 +82,8 @@
|
|
|
82
82
|
"/app/object-storage/",
|
|
83
83
|
"/app/runtime/",
|
|
84
84
|
"/app/system/hosts/",
|
|
85
|
-
"/app/person/"
|
|
85
|
+
"/app/person/",
|
|
86
|
+
"/app/wave/"
|
|
86
87
|
],
|
|
87
88
|
"requestPlacementPrefixes": [
|
|
88
89
|
"/app/messaging/"
|
package/manifest/targets.v1.json
CHANGED
package/package.json
CHANGED