@ggui-ai/protocol-conformance 0.2.0-alpha.3 → 0.3.0-rc.0
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/README.md +32 -13
- package/dist/cli.d.ts +11 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +48 -20
- package/dist/conformance-host.d.ts +81 -76
- package/dist/conformance-host.d.ts.map +1 -1
- package/dist/conformance-host.js +0 -44
- package/dist/fixtures/bootstrap-protocol/bootstrap-bundle-fetch-failed.json +3 -3
- package/dist/fixtures/bootstrap-protocol/bootstrap-meta-missing.json +3 -3
- package/dist/fixtures/bootstrap-protocol/bootstrap-success.json +3 -3
- package/dist/fixtures/consume-buffer/action-ack-sequence.json +28 -0
- package/dist/fixtures/consume-buffer/action-payload-schema-violation.json +37 -0
- package/dist/fixtures/consume-buffer/index.d.ts +6 -0
- package/dist/fixtures/consume-buffer/index.d.ts.map +1 -0
- package/dist/fixtures/consume-buffer/index.js +41 -0
- package/dist/fixtures/consume-buffer/undeclared-action-rejected.json +29 -0
- package/dist/fixtures/host-context/host-context-observed-persists.json +34 -0
- package/dist/fixtures/host-context/index.d.ts +5 -0
- package/dist/fixtures/host-context/index.d.ts.map +1 -0
- package/dist/fixtures/host-context/index.js +40 -0
- package/dist/fixtures/index.d.ts +28 -9
- package/dist/fixtures/index.d.ts.map +1 -1
- package/dist/fixtures/index.js +33 -14
- package/dist/fixtures/reserved-channel-authority/index.d.ts.map +1 -1
- package/dist/fixtures/reserved-channel-authority/index.js +17 -7
- package/dist/fixtures/reserved-channel-authority/props-update-roundtrip.json +4 -4
- package/dist/fixtures/schema-version-handshake/index.d.ts.map +1 -1
- package/dist/fixtures/schema-version-handshake/index.js +12 -4
- package/dist/fixtures/schema-version-handshake/version-match.json +7 -5
- package/dist/fixtures/schema-version-handshake/version-mismatch.json +9 -10
- package/dist/fixtures/subscribe-tenancy/absent-appid-defaults.json +18 -0
- package/dist/fixtures/subscribe-tenancy/app-mismatch.json +20 -0
- package/dist/fixtures/subscribe-tenancy/index.d.ts +6 -0
- package/dist/fixtures/subscribe-tenancy/index.d.ts.map +1 -0
- package/dist/fixtures/subscribe-tenancy/index.js +62 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/match-behavior.d.ts +19 -100
- package/dist/match-behavior.d.ts.map +1 -1
- package/dist/match-behavior.js +289 -246
- package/dist/registration-conformance/cases/gate-duplicate-hook.json +26 -0
- package/dist/registration-conformance/cases/gate-export-not-registered.json +1 -0
- package/dist/registration-conformance/cases/gate-multi-package-distinct-names-accept.json +26 -0
- package/dist/registration-conformance/cases/gate-no-gadgets-accept.json +1 -0
- package/dist/registration-conformance/cases/gate-package-mismatch.json +1 -0
- package/dist/registration-conformance/cases/gate-priority-not-registered-outranks-mismatch.json +1 -0
- package/dist/registration-conformance/cases/gate-priority-registry-outranks-public-env.json +22 -0
- package/dist/registration-conformance/cases/gate-public-env-missing.json +21 -0
- package/dist/registration-conformance/cases/gate-public-env-satisfied-accept.json +21 -0
- package/dist/registration-conformance/cases/gate-public-env-undeclared-wrapper-accept.json +26 -0
- package/dist/registration-conformance/cases/gate-registered-resolves-accept.json +1 -0
- package/dist/registration-conformance/cases/gate-stdlib-hook-accept.json +1 -0
- package/dist/registration-conformance/cases/gate-typo-classifies-as-not-registered.json +1 -0
- package/dist/registration-conformance/index.d.ts +64 -33
- package/dist/registration-conformance/index.d.ts.map +1 -1
- package/dist/registration-conformance/index.js +24 -8
- package/dist/run-conformance.d.ts +145 -6
- package/dist/run-conformance.d.ts.map +1 -1
- package/dist/run-conformance.js +531 -93
- package/dist/types.d.ts +319 -165
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +27 -23
- package/dist/ws-transport.d.ts.map +1 -1
- package/dist/ws-transport.js +3 -2
- package/package.json +3 -3
- package/dist/fixtures/observability-events/index.d.ts +0 -5
- package/dist/fixtures/observability-events/index.d.ts.map +0 -1
- package/dist/fixtures/observability-events/index.js +0 -22
- package/dist/fixtures/observability-events/observability-contract-error-emitted.json +0 -28
- package/dist/fixtures/observability-events/observability-wired-tool-invoked.json +0 -27
- package/dist/fixtures/refresh-semantics/index.d.ts +0 -5
- package/dist/fixtures/refresh-semantics/index.d.ts.map +0 -1
- package/dist/fixtures/refresh-semantics/index.js +0 -19
- package/dist/fixtures/refresh-semantics/stream-refresh-success.json +0 -39
- package/dist/fixtures/reserved-channel-authority/stream-schema-violation.json +0 -44
- package/dist/fixtures/wired-action-dispatch/index.d.ts +0 -5
- package/dist/fixtures/wired-action-dispatch/index.d.ts.map +0 -1
- package/dist/fixtures/wired-action-dispatch/index.js +0 -29
- package/dist/fixtures/wired-action-dispatch/wired-action-success.json +0 -35
- package/dist/fixtures/wired-action-dispatch/wired-action-tool-not-found.json +0 -30
- package/dist/fixtures/wired-action-dispatch/wired-action-tool-threw.json +0 -31
- package/dist/fixtures/wired-action-dispatch/wired-action-tool-timeout.json +0 -31
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gate-multi-package-distinct-names-accept",
|
|
3
|
+
"description": "The duplicate-hook check fires on the same export NAME across packages — not on multi-package contracts per se. The contract declares two DIFFERENT export names from two different packages (`useCheckout` under `@stripe/ggui-checkout`, `useShippingEstimate` under `@acme/shipping`); both `(package, export)` pairs are registered and neither descriptor has `requires`. The composed gate MUST accept. Guards against an over-eager duplicate check that rejects any contract spanning more than one gadget package.",
|
|
4
|
+
"contract": {
|
|
5
|
+
"clientCapabilities": {
|
|
6
|
+
"gadgets": {
|
|
7
|
+
"@stripe/ggui-checkout": { "useCheckout": {} },
|
|
8
|
+
"@acme/shipping": { "useShippingEstimate": {} }
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"appGadgets": [
|
|
13
|
+
{
|
|
14
|
+
"package": "@stripe/ggui-checkout",
|
|
15
|
+
"version": "1.0.0",
|
|
16
|
+
"exports": [{ "hook": "useCheckout" }]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"package": "@acme/shipping",
|
|
20
|
+
"version": "1.0.0",
|
|
21
|
+
"exports": [{ "hook": "useShippingEstimate" }]
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"appPublicEnv": {},
|
|
25
|
+
"expect": { "outcome": "accept" }
|
|
26
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gate-priority-registry-outranks-public-env",
|
|
3
|
+
"description": "A single push that fails BOTH gadget gates: it references an export absent from every registered package (`useTurnstile` under `@acme/turnstile`) AND a registered wrapper whose `requires` is unsatisfied (`useMapboxMap` under `@acme/mapbox`, requiring `GGUI_PUBLIC_APP_MAPBOX_TOKEN` while `App.publicEnv` is empty). SPEC §7.7.3 pins the order: the registry gate runs FIRST so the operator gets the right diagnostic when both fail — an author who referenced an unknown export needs the registration miss, not a downstream env complaint. The composed gate MUST reject with `gadget_not_registered`.",
|
|
4
|
+
"contract": {
|
|
5
|
+
"clientCapabilities": {
|
|
6
|
+
"gadgets": {
|
|
7
|
+
"@acme/turnstile": { "useTurnstile": {} },
|
|
8
|
+
"@acme/mapbox": { "useMapboxMap": {} }
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"appGadgets": [
|
|
13
|
+
{
|
|
14
|
+
"package": "@acme/mapbox",
|
|
15
|
+
"version": "1.0.0",
|
|
16
|
+
"exports": [{ "hook": "useMapboxMap" }],
|
|
17
|
+
"requires": ["GGUI_PUBLIC_APP_MAPBOX_TOKEN"]
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"appPublicEnv": {},
|
|
21
|
+
"expect": { "outcome": "reject", "code": "gadget_not_registered" }
|
|
22
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gate-public-env-missing",
|
|
3
|
+
"description": "The contract references `useMapboxMap` under `@acme/mapbox`, and the app registers that exact `(package, export)` pair — registry membership passes — but the registered descriptor's `requires` lists the public env key `GGUI_PUBLIC_APP_MAPBOX_TOKEN` and `App.publicEnv` carries no keys at all. The render-time env gate (SPEC §7.7.3 — `assertPublicEnvSatisfied`) MUST reject with code `gadget_public_env_missing`: without the key, the wrapper's `getPublicEnv()` would throw at hook-mount inside the iframe, so the gate surfaces the misconfiguration as a recoverable author/operator-time error instead. Recovery: stamp the key on the app's public env, or drop the wrapper binding from the contract.",
|
|
4
|
+
"contract": {
|
|
5
|
+
"clientCapabilities": {
|
|
6
|
+
"gadgets": {
|
|
7
|
+
"@acme/mapbox": { "useMapboxMap": {} }
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"appGadgets": [
|
|
12
|
+
{
|
|
13
|
+
"package": "@acme/mapbox",
|
|
14
|
+
"version": "1.0.0",
|
|
15
|
+
"exports": [{ "hook": "useMapboxMap" }],
|
|
16
|
+
"requires": ["GGUI_PUBLIC_APP_MAPBOX_TOKEN"]
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"appPublicEnv": {},
|
|
20
|
+
"expect": { "outcome": "reject", "code": "gadget_public_env_missing" }
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gate-public-env-satisfied-accept",
|
|
3
|
+
"description": "The positive counterpart of `gate-public-env-missing`. The contract references `useMapboxMap` under `@acme/mapbox`; the registered descriptor requires `GGUI_PUBLIC_APP_MAPBOX_TOKEN`; and `App.publicEnv` carries that exact key. Every declared wrapper's `requires` is satisfied, so the composed gate MUST accept. Paired with the reject case, this also proves the gate actually reads `appPublicEnv` — an env-blind gate passes one of the pair but never both.",
|
|
4
|
+
"contract": {
|
|
5
|
+
"clientCapabilities": {
|
|
6
|
+
"gadgets": {
|
|
7
|
+
"@acme/mapbox": { "useMapboxMap": {} }
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"appGadgets": [
|
|
12
|
+
{
|
|
13
|
+
"package": "@acme/mapbox",
|
|
14
|
+
"version": "1.0.0",
|
|
15
|
+
"exports": [{ "hook": "useMapboxMap" }],
|
|
16
|
+
"requires": ["GGUI_PUBLIC_APP_MAPBOX_TOKEN"]
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"appPublicEnv": { "GGUI_PUBLIC_APP_MAPBOX_TOKEN": "pk.conformance-fixture-value" },
|
|
20
|
+
"expect": { "outcome": "accept" }
|
|
21
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gate-public-env-undeclared-wrapper-accept",
|
|
3
|
+
"description": "The env gate is scoped to wrappers the CONTRACT references, not the whole catalog. The contract declares only `useLeafletMap` under `@ggui-samples/leaflet` (registered, no `requires`). The app catalog ALSO registers `@acme/mapbox`, whose `requires` lists `GGUI_PUBLIC_APP_MAPBOX_TOKEN` — unsatisfied, since `App.publicEnv` is empty — but the contract never references that wrapper, so it cannot affect this render's iframe. SPEC §7.7.3 walks `requires` for every wrapper the contract references; registered-but-undeclared wrappers MUST NOT fail the push. The gate MUST accept. Guards against a gate that validates the operator's entire catalog instead of the declared subset.",
|
|
4
|
+
"contract": {
|
|
5
|
+
"clientCapabilities": {
|
|
6
|
+
"gadgets": {
|
|
7
|
+
"@ggui-samples/leaflet": { "useLeafletMap": {} }
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"appGadgets": [
|
|
12
|
+
{
|
|
13
|
+
"package": "@ggui-samples/leaflet",
|
|
14
|
+
"version": "2.3.1",
|
|
15
|
+
"exports": [{ "hook": "useLeafletMap" }]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"package": "@acme/mapbox",
|
|
19
|
+
"version": "1.0.0",
|
|
20
|
+
"exports": [{ "hook": "useMapboxMap" }],
|
|
21
|
+
"requires": ["GGUI_PUBLIC_APP_MAPBOX_TOKEN"]
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"appPublicEnv": {},
|
|
25
|
+
"expect": { "outcome": "accept" }
|
|
26
|
+
}
|
|
@@ -1,51 +1,72 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Registration-conformance catalog — accept / reject cases for the
|
|
3
|
-
*
|
|
3
|
+
* render-time gadget gate stack:
|
|
4
|
+
*
|
|
5
|
+
* - registry membership (SPEC §7.7.2 — `assertGadgetsRegistered`):
|
|
6
|
+
* every `(package, export)` the contract references resolves in
|
|
7
|
+
* `App.gadgets`, with the miss classified into a precise reject
|
|
8
|
+
* code (`gadget_not_registered` ▸ `gadget_package_mismatch`);
|
|
9
|
+
* - public-env satisfaction (SPEC §7.7.3 —
|
|
10
|
+
* `assertPublicEnvSatisfied`): every declared wrapper's
|
|
11
|
+
* `requires[]` key is present in `App.publicEnv`
|
|
12
|
+
* (`gadget_public_env_missing`). §7.7.3 pins the registry gate
|
|
13
|
+
* FIRST when both fail;
|
|
14
|
+
* - duplicate export names (SPEC §7.9 —
|
|
15
|
+
* `assertNoDuplicateGadgetHooks`): the same export name declared
|
|
16
|
+
* under two packages collides in the generated module scope
|
|
17
|
+
* (`duplicate_gadget_hook`). The catalog deliberately authors its
|
|
18
|
+
* duplicate cases so every pair resolves cleanly — this check's
|
|
19
|
+
* priority relative to the other two is NOT pinned.
|
|
4
20
|
*
|
|
5
21
|
* ## Why this is a pure-function catalog, not a behavioral fixture
|
|
6
22
|
*
|
|
7
|
-
* The
|
|
8
|
-
*
|
|
9
|
-
* `
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
23
|
+
* The gadget gate stack answers a pure question: given a contract,
|
|
24
|
+
* the app's registered `App.gadgets` catalog, and the app's
|
|
25
|
+
* `App.publicEnv` map, does the push commit — and if not, which
|
|
26
|
+
* precise reject code applies? There is no render, no transport, no
|
|
27
|
+
* wire frame in that question — it is a deterministic classification,
|
|
28
|
+
* exactly like the `clientCapabilities` schema check in
|
|
29
|
+
* `../schema-conformance`.
|
|
14
30
|
*
|
|
15
31
|
* Modeling it as a WebSocket behavioral fixture would mean inventing a
|
|
16
|
-
* wire frame the real protocol never emits (the
|
|
32
|
+
* wire frame the real protocol never emits (the gates run at MCP-push
|
|
17
33
|
* time, before any live channel exists) — the dishonest modeling the
|
|
18
|
-
* kit's Path-A / Path-B partition exists to forbid. So the gate
|
|
19
|
-
* the same treatment as the wire schema: a catalog of cases
|
|
20
|
-
* against a caller-supplied gate function.
|
|
34
|
+
* kit's Path-A / Path-B partition exists to forbid. So the gate stack
|
|
35
|
+
* gets the same treatment as the wire schema: a catalog of cases
|
|
36
|
+
* graded against a caller-supplied gate function.
|
|
21
37
|
*
|
|
22
38
|
* ## Polyglot, decoupled
|
|
23
39
|
*
|
|
24
40
|
* Each case ships as raw JSON under `./cases/`. {@link runRegistrationConformance}
|
|
25
41
|
* takes the gate as a callback — the kit never imports a concrete gate
|
|
26
|
-
* implementation
|
|
27
|
-
*
|
|
28
|
-
*
|
|
42
|
+
* implementation, so adopters drive their OWN gate. The kit's
|
|
43
|
+
* meta-test (`./registration-conformance.test.ts`) grades a kit-local
|
|
44
|
+
* gate built from the SPEC, proving catalog coherence while keeping
|
|
45
|
+
* the vendor-neutral kit free of any server implementation; the
|
|
46
|
+
* drift-catch against a SHIPPING gate lives implementation-side (the
|
|
47
|
+
* first-party one is `assert-gadgets.conformance.test.ts` in
|
|
48
|
+
* `@ggui-ai/mcp-server-handlers`) so the dependency edge stays
|
|
49
|
+
* implementation → kit.
|
|
29
50
|
*
|
|
30
51
|
* The `DataContract` / `GadgetDescriptor` types ARE imported (type-only)
|
|
31
52
|
* from `@ggui-ai/protocol` — unlike the behavioral fixture vocabulary
|
|
32
53
|
* in `../types.ts`, these are the gate's actual input contract, not a
|
|
33
54
|
* frozen authored union; the runner's `gate` signature MUST match the
|
|
34
|
-
* real function for
|
|
55
|
+
* real function for an implementation binding to be cast-free.
|
|
35
56
|
*/
|
|
36
57
|
import type { DataContract, GadgetDescriptor } from '@ggui-ai/protocol';
|
|
37
58
|
/**
|
|
38
|
-
* The precise reject codes the gadget gate classifies a
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
59
|
+
* The precise reject codes the gadget gate stack classifies a failing
|
|
60
|
+
* push into — the SPEC §7.9 Plane-2 slugs for the four gadget gate
|
|
61
|
+
* rejections. Extensibly-closed `(string & {})` tail so a later
|
|
62
|
+
* protocol revision's code rides through without a kit bump — same
|
|
63
|
+
* discipline as `BootstrapFailureReason` in `../types.ts`.
|
|
43
64
|
*/
|
|
44
|
-
export type GadgetGateRejectCode = 'gadget_not_registered' | 'gadget_package_mismatch' | (string & {});
|
|
65
|
+
export type GadgetGateRejectCode = 'gadget_not_registered' | 'gadget_package_mismatch' | 'gadget_public_env_missing' | 'duplicate_gadget_hook' | (string & {});
|
|
45
66
|
/**
|
|
46
|
-
* The outcome of running the gate against one
|
|
47
|
-
*
|
|
48
|
-
* one classified code.
|
|
67
|
+
* The outcome of running the gate stack against one
|
|
68
|
+
* `(contract, appGadgets, appPublicEnv)` triple. A conformant gate
|
|
69
|
+
* either accepts the push or rejects it with one classified code.
|
|
49
70
|
*/
|
|
50
71
|
export type GateOutcome = {
|
|
51
72
|
readonly outcome: 'accept';
|
|
@@ -70,6 +91,12 @@ export interface RegistrationConformanceCase {
|
|
|
70
91
|
readonly contract: DataContract;
|
|
71
92
|
/** The app's registered gadget catalog the gate resolves against. */
|
|
72
93
|
readonly appGadgets: readonly GadgetDescriptor[];
|
|
94
|
+
/**
|
|
95
|
+
* The app's operator-stamped public-env map the gate checks declared
|
|
96
|
+
* wrappers' `requires[]` against (SPEC §7.7.3). Always present on a
|
|
97
|
+
* case — `{}` models an app with no public env configured.
|
|
98
|
+
*/
|
|
99
|
+
readonly appPublicEnv: Readonly<Record<string, string>>;
|
|
73
100
|
/** The outcome a spec-conformant gate MUST produce. */
|
|
74
101
|
readonly expect: GateOutcome;
|
|
75
102
|
}
|
|
@@ -97,18 +124,22 @@ export interface RegistrationConformanceResult {
|
|
|
97
124
|
/**
|
|
98
125
|
* Grade a gadget registration gate against the catalog.
|
|
99
126
|
*
|
|
100
|
-
* `gate` MUST be a pure classification of
|
|
101
|
-
* return `{outcome:'accept'}`
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
127
|
+
* `gate` MUST be a pure classification of
|
|
128
|
+
* `(contract, appGadgets, appPublicEnv)` — return `{outcome:'accept'}`
|
|
129
|
+
* when the push commits (every referenced `(package, export)`
|
|
130
|
+
* resolves, every declared wrapper's `requires[]` is satisfied, no
|
|
131
|
+
* export name repeats across packages), or `{outcome:'reject', code}`
|
|
132
|
+
* with the precise reject code otherwise. Implementations that compose
|
|
133
|
+
* separate checks wrap the composition. The kit deliberately does NOT
|
|
134
|
+
* import a concrete gate — adopters pass their own (the first-party
|
|
135
|
+
* drift-catch wraps `@ggui-ai/mcp-server-handlers`'s gate trio in its
|
|
136
|
+
* own package; see the module doc). A conformant gate produces an
|
|
137
|
+
* empty `failed` array.
|
|
107
138
|
*
|
|
108
139
|
* `gate` is invoked exactly once per case, in {@link gadgetRegistrationCases}
|
|
109
140
|
* order; it MUST be pure and MUST NOT throw (a throwing gate is itself
|
|
110
141
|
* non-conformant — wrap it so a classified rejection becomes a
|
|
111
142
|
* returned `GateOutcome`).
|
|
112
143
|
*/
|
|
113
|
-
export declare function runRegistrationConformance(gate: (contract: DataContract, appGadgets: readonly GadgetDescriptor[]) => GateOutcome): RegistrationConformanceResult;
|
|
144
|
+
export declare function runRegistrationConformance(gate: (contract: DataContract, appGadgets: readonly GadgetDescriptor[], appPublicEnv: Readonly<Record<string, string>>) => GateOutcome): RegistrationConformanceResult;
|
|
114
145
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registration-conformance/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registration-conformance/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAgBxE;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAC5B,uBAAuB,GACvB,yBAAyB,GACzB,2BAA2B,GAC3B,uBAAuB,GACvB,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAElB;;;;GAIG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,GAC9B;IAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAA;CAAE,CAAC;AAExE;;;;;;;GAOG;AACH,MAAM,WAAW,2BAA2B;IAC1C,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,qEAAqE;IACrE,QAAQ,CAAC,UAAU,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACjD;;;;OAIG;IACH,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACxD,uDAAuD;IACvD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;CAC9B;AAED;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,SAAS,2BAA2B,EAczE,CAAC;AAEF,iDAAiD;AACjD,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,yDAAyD;IACzD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;CAC9B;AAED,qDAAqD;AACrD,MAAM,WAAW,6BAA6B;IAC5C,gDAAgD;IAChD,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,SAAS,+BAA+B,EAAE,CAAC;CAC7D;AAUD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,CACJ,QAAQ,EAAE,YAAY,EACtB,UAAU,EAAE,SAAS,gBAAgB,EAAE,EACvC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAC3C,WAAW,GACf,6BAA6B,CAoB/B"}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
import gateDuplicateHook from './cases/gate-duplicate-hook.json' with { type: 'json' };
|
|
1
2
|
import gateExportNotRegistered from './cases/gate-export-not-registered.json' with { type: 'json' };
|
|
3
|
+
import gateMultiPackageDistinctNamesAccept from './cases/gate-multi-package-distinct-names-accept.json' with { type: 'json' };
|
|
2
4
|
import gateNoGadgetsAccept from './cases/gate-no-gadgets-accept.json' with { type: 'json' };
|
|
3
5
|
import gatePackageMismatch from './cases/gate-package-mismatch.json' with { type: 'json' };
|
|
4
6
|
import gatePriorityNotRegisteredOutranksMismatch from './cases/gate-priority-not-registered-outranks-mismatch.json' with { type: 'json' };
|
|
7
|
+
import gatePriorityRegistryOutranksPublicEnv from './cases/gate-priority-registry-outranks-public-env.json' with { type: 'json' };
|
|
8
|
+
import gatePublicEnvMissing from './cases/gate-public-env-missing.json' with { type: 'json' };
|
|
9
|
+
import gatePublicEnvSatisfiedAccept from './cases/gate-public-env-satisfied-accept.json' with { type: 'json' };
|
|
10
|
+
import gatePublicEnvUndeclaredWrapperAccept from './cases/gate-public-env-undeclared-wrapper-accept.json' with { type: 'json' };
|
|
5
11
|
import gateRegisteredResolvesAccept from './cases/gate-registered-resolves-accept.json' with { type: 'json' };
|
|
6
12
|
import gateStdlibHookAccept from './cases/gate-stdlib-hook-accept.json' with { type: 'json' };
|
|
7
13
|
import gateTypoClassifiesAsNotRegistered from './cases/gate-typo-classifies-as-not-registered.json' with { type: 'json' };
|
|
@@ -15,9 +21,15 @@ export const gadgetRegistrationCases = [
|
|
|
15
21
|
gatePackageMismatch,
|
|
16
22
|
gatePriorityNotRegisteredOutranksMismatch,
|
|
17
23
|
gateTypoClassifiesAsNotRegistered,
|
|
24
|
+
gatePublicEnvMissing,
|
|
25
|
+
gatePriorityRegistryOutranksPublicEnv,
|
|
26
|
+
gateDuplicateHook,
|
|
18
27
|
gateStdlibHookAccept,
|
|
19
28
|
gateRegisteredResolvesAccept,
|
|
20
29
|
gateNoGadgetsAccept,
|
|
30
|
+
gatePublicEnvSatisfiedAccept,
|
|
31
|
+
gatePublicEnvUndeclaredWrapperAccept,
|
|
32
|
+
gateMultiPackageDistinctNamesAccept,
|
|
21
33
|
];
|
|
22
34
|
function gateOutcomeEquals(a, b) {
|
|
23
35
|
if (a.outcome !== b.outcome)
|
|
@@ -30,13 +42,17 @@ function gateOutcomeEquals(a, b) {
|
|
|
30
42
|
/**
|
|
31
43
|
* Grade a gadget registration gate against the catalog.
|
|
32
44
|
*
|
|
33
|
-
* `gate` MUST be a pure classification of
|
|
34
|
-
* return `{outcome:'accept'}`
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
45
|
+
* `gate` MUST be a pure classification of
|
|
46
|
+
* `(contract, appGadgets, appPublicEnv)` — return `{outcome:'accept'}`
|
|
47
|
+
* when the push commits (every referenced `(package, export)`
|
|
48
|
+
* resolves, every declared wrapper's `requires[]` is satisfied, no
|
|
49
|
+
* export name repeats across packages), or `{outcome:'reject', code}`
|
|
50
|
+
* with the precise reject code otherwise. Implementations that compose
|
|
51
|
+
* separate checks wrap the composition. The kit deliberately does NOT
|
|
52
|
+
* import a concrete gate — adopters pass their own (the first-party
|
|
53
|
+
* drift-catch wraps `@ggui-ai/mcp-server-handlers`'s gate trio in its
|
|
54
|
+
* own package; see the module doc). A conformant gate produces an
|
|
55
|
+
* empty `failed` array.
|
|
40
56
|
*
|
|
41
57
|
* `gate` is invoked exactly once per case, in {@link gadgetRegistrationCases}
|
|
42
58
|
* order; it MUST be pure and MUST NOT throw (a throwing gate is itself
|
|
@@ -47,7 +63,7 @@ export function runRegistrationConformance(gate) {
|
|
|
47
63
|
const passed = [];
|
|
48
64
|
const failed = [];
|
|
49
65
|
for (const testCase of gadgetRegistrationCases) {
|
|
50
|
-
const actual = gate(testCase.contract, testCase.appGadgets);
|
|
66
|
+
const actual = gate(testCase.contract, testCase.appGadgets, testCase.appPublicEnv);
|
|
51
67
|
if (gateOutcomeEquals(actual, testCase.expect)) {
|
|
52
68
|
passed.push(testCase.name);
|
|
53
69
|
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { HostContextObservedPayload } from '@ggui-ai/protocol';
|
|
2
|
+
import type { ConformanceHost, SetupStep as HostSetupStep } from './conformance-host.js';
|
|
3
|
+
import { type MatchResult } from './match-behavior.js';
|
|
4
|
+
import type { AuthConfig, SessionStateBehavior, StreamUpdateBehavior, VersionMismatchBehavior } from './types.js';
|
|
3
5
|
export interface RunConformanceConfig {
|
|
4
6
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
7
|
+
* URL of the implementation under test. `http://` / `https://`
|
|
8
|
+
* schemes derive `ws://` / `wss://`. A bare origin (no path, e.g.
|
|
9
|
+
* `http://localhost:3000`) gets the default live-channel path `/ws`
|
|
10
|
+
* appended; a URL that already carries a path (e.g.
|
|
11
|
+
* `ws://localhost:3000/ws`, or a non-default mount point) is used
|
|
12
|
+
* exactly as given — the runner never appends to an explicit path.
|
|
8
13
|
*/
|
|
9
14
|
readonly serverUrl: string;
|
|
10
15
|
/** Auth carried on the WS upgrade. See {@link AuthConfig}. */
|
|
@@ -54,5 +59,139 @@ export interface ConformanceReporter {
|
|
|
54
59
|
onComplete?(result: ConformanceResult): void;
|
|
55
60
|
}
|
|
56
61
|
export declare function runConformance(config: RunConformanceConfig): Promise<ConformanceResult>;
|
|
57
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Resolve the WS endpoint from `config.serverUrl`:
|
|
64
|
+
* - `http://` / `https://` schemes become `ws://` / `wss://`; a
|
|
65
|
+
* scheme-less value is assumed `ws://`.
|
|
66
|
+
* - A bare origin (no path) gets the default live-channel path
|
|
67
|
+
* `/ws` appended.
|
|
68
|
+
* - A URL that already carries a path is used exactly as given —
|
|
69
|
+
* the runner never appends to an explicit path, so
|
|
70
|
+
* `ws://host:3000/ws` (or a non-default mount point) works
|
|
71
|
+
* without double-appending.
|
|
72
|
+
*
|
|
73
|
+
* Exported for unit tests; not part of the package's public API.
|
|
74
|
+
*/
|
|
75
|
+
export declare function deriveWsUrl(serverUrl: string): string;
|
|
76
|
+
/**
|
|
77
|
+
* Fixture-authored `host_context_observed` Client→Server frame — the
|
|
78
|
+
* wire shape from `@ggui-ai/protocol` (`transport/websocket`):
|
|
79
|
+
* `{type: 'host_context_observed', payload: {sessionId, hostContext}}`.
|
|
80
|
+
* The iframe-runtime emits it after `ui/initialize` resolves (and on
|
|
81
|
+
* every `host-context-changed` notification); the server's obligation
|
|
82
|
+
* is to persist `payload.hostContext` onto `GguiSession.hostContext`
|
|
83
|
+
* with no synchronous response — which is why fixtures authoring this
|
|
84
|
+
* envelope pair it with a `session-state` expectation, not a frame
|
|
85
|
+
* expectation.
|
|
86
|
+
*/
|
|
87
|
+
export interface HostContextObservedInputEnvelope {
|
|
88
|
+
readonly type: 'host_context_observed';
|
|
89
|
+
readonly requestId?: string;
|
|
90
|
+
readonly payload: HostContextObservedPayload;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Classification of a fixture's `inputEnvelope` into the CLOSED
|
|
94
|
+
* dispatch vocabulary — exactly the C→S frame types the shipped
|
|
95
|
+
* fixture catalog authors for explicit post-subscribe dispatch.
|
|
96
|
+
*
|
|
97
|
+
* - `action` — the live-channel action dispatch shape, sent
|
|
98
|
+
* VERBATIM. Deliberately untyped beyond the discriminator: action
|
|
99
|
+
* fixtures may author adversarial payloads (undeclared action
|
|
100
|
+
* names, malformed bodies) precisely because the server's
|
|
101
|
+
* rejection path is what's under test — the kit MUST NOT
|
|
102
|
+
* pre-validate away the inputs the contract is graded on.
|
|
103
|
+
* - `host_context_observed` — the validated typed arm
|
|
104
|
+
* ({@link HostContextObservedInputEnvelope}). The kit authors this
|
|
105
|
+
* frame as a well-formed client, so a malformed one is a
|
|
106
|
+
* fixture-authoring error, not a server probe.
|
|
107
|
+
* - `none` — every other authored envelope (`render`, `handshake`,
|
|
108
|
+
* `props-update`) is driven by the subscribe itself or by a
|
|
109
|
+
* Path-B host harness; the explicit send is skipped.
|
|
110
|
+
*/
|
|
111
|
+
export type InputEnvelopeDispatch = {
|
|
112
|
+
readonly kind: 'action';
|
|
113
|
+
readonly envelope: unknown;
|
|
114
|
+
} | {
|
|
115
|
+
readonly kind: 'host_context_observed';
|
|
116
|
+
readonly envelope: HostContextObservedInputEnvelope;
|
|
117
|
+
} | {
|
|
118
|
+
readonly kind: 'none';
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* Validating classifier for the fixture's `inputEnvelope`. The fixture
|
|
122
|
+
* JSON enters the type system through a compile-time cast, so —
|
|
123
|
+
* exactly like {@link parseSetupStep} — the dispatchable arms are
|
|
124
|
+
* re-validated structurally here, and a malformed
|
|
125
|
+
* `host_context_observed` frame throws a descriptive fixture-authoring
|
|
126
|
+
* error (never a skip, never a fail of the implementation under test).
|
|
127
|
+
*
|
|
128
|
+
* Exported for unit tests; not part of the package's public API.
|
|
129
|
+
*/
|
|
130
|
+
export declare function parseInputEnvelope(fixtureName: string, envelope: unknown): InputEnvelopeDispatch;
|
|
131
|
+
/**
|
|
132
|
+
* Grade a `session-state` expectation — the input message left no wire
|
|
133
|
+
* trace, so the honest verdict is a post-observation-window read-back
|
|
134
|
+
* of the mutated GguiSession field via
|
|
135
|
+
* {@link ConformanceHost.readSessionField}, compared with the SAME
|
|
136
|
+
* exact {@link deepEqual} the frame matchers use.
|
|
137
|
+
*
|
|
138
|
+
* A missing host, a host without `readSessionField`, or a read that
|
|
139
|
+
* throws all yield `unmatchable-on-ws` — the runner records a SKIP
|
|
140
|
+
* with the reason. The kit refuses to grade a stateful obligation it
|
|
141
|
+
* has no introspection seam for (a host that cannot read state cannot
|
|
142
|
+
* grade it); it never converts that gap into a pass or a fail.
|
|
143
|
+
*
|
|
144
|
+
* Exported for unit tests; not part of the package's public API.
|
|
145
|
+
*/
|
|
146
|
+
export declare function matchSessionState(behavior: SessionStateBehavior, sessionId: string, host: ConformanceHost | undefined): Promise<MatchResult>;
|
|
147
|
+
/**
|
|
148
|
+
* Resolved, runner-ready form of `SubscribeFrameShaping`: the
|
|
149
|
+
* `'current'` sentinel is already replaced by the kit's compiled
|
|
150
|
+
* `PROTOCOL_SCHEMA_VERSION`, so the subscribe-send site only ever
|
|
151
|
+
* sees a concrete declaration (or none).
|
|
152
|
+
*/
|
|
153
|
+
export interface ResolvedSubscribeShaping {
|
|
154
|
+
readonly omitAppId: boolean;
|
|
155
|
+
readonly supportedVersions?: readonly string[];
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Validating narrower for the fixture-authored `subscribe` knob
|
|
159
|
+
* (`SubscribeFrameShaping`, types.ts). Same trust-boundary posture as
|
|
160
|
+
* {@link parseSetupStep}: the fixture JSON enters the type system
|
|
161
|
+
* through a compile-time cast, so the shape is re-validated
|
|
162
|
+
* structurally here and any malformed or unknown shaping is a
|
|
163
|
+
* fixture-authoring error the runner throws on — never a skip, never
|
|
164
|
+
* a fail of the implementation under test.
|
|
165
|
+
*
|
|
166
|
+
* The vocabulary is CLOSED — exactly the shaping fields the shipped
|
|
167
|
+
* catalog authors (`omitAppId`, `supportedVersions`); an unknown key
|
|
168
|
+
* is rejected so a typo'd knob can never silently no-op into a
|
|
169
|
+
* vacuous grade. `supportedVersions: 'current'` resolves to
|
|
170
|
+
* `[PROTOCOL_SCHEMA_VERSION]` (the kit's compiled canonical), keeping
|
|
171
|
+
* fixtures evergreen across protocol version bumps.
|
|
172
|
+
*
|
|
173
|
+
* Exported for unit tests; not part of the package's public API.
|
|
174
|
+
*/
|
|
175
|
+
export declare function parseSubscribeShaping(fixtureName: string, shaping: unknown): ResolvedSubscribeShaping;
|
|
176
|
+
/**
|
|
177
|
+
* Validating narrower from the fixture-JSON `SetupStep` (discriminated
|
|
178
|
+
* on `type`) to the host's runtime `SetupStep` (discriminated on
|
|
179
|
+
* `kind`). The fixture JSON enters the type system through a
|
|
180
|
+
* compile-time cast (tsc widens JSON-module string literals), so the
|
|
181
|
+
* static union cannot be trusted at runtime — every directive is
|
|
182
|
+
* re-validated structurally here.
|
|
183
|
+
*
|
|
184
|
+
* The setup vocabulary is CLOSED: an unknown or malformed directive is
|
|
185
|
+
* a fixture-authoring error, thrown with a descriptive message. It is
|
|
186
|
+
* never mapped to a skip or a fail — those verdicts describe the
|
|
187
|
+
* implementation under test, not the fixture catalog.
|
|
188
|
+
*
|
|
189
|
+
* The input is `unknown` by design — this function IS the trust
|
|
190
|
+
* boundary, so it never leans on the static union it produces
|
|
191
|
+
* evidence for.
|
|
192
|
+
*
|
|
193
|
+
* Exported for unit tests; not part of the package's public API.
|
|
194
|
+
*/
|
|
195
|
+
export declare function parseSetupStep(fixtureName: string, step: unknown): HostSetupStep;
|
|
196
|
+
export type { StreamUpdateBehavior, VersionMismatchBehavior };
|
|
58
197
|
//# sourceMappingURL=run-conformance.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-conformance.d.ts","sourceRoot":"","sources":["../src/run-conformance.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run-conformance.d.ts","sourceRoot":"","sources":["../src/run-conformance.ts"],"names":[],"mappings":"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"}
|