@ggui-ai/protocol-conformance 0.6.3 → 0.8.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.
Files changed (65) hide show
  1. package/README.md +59 -18
  2. package/dist/binding-conformance/cases/bind-blueprint-no-contract-none.json +6 -0
  3. package/dist/binding-conformance/cases/bind-contract-without-tool-names-none.json +18 -0
  4. package/dist/binding-conformance/cases/bind-declared-gadget.json +13 -0
  5. package/dist/binding-conformance/cases/bind-declared-wins-over-contract.json +23 -0
  6. package/dist/binding-conformance/cases/bind-derived-caps-at-sixteen.json +54 -0
  7. package/dist/binding-conformance/cases/bind-derived-props-and-stream.json +36 -0
  8. package/dist/binding-conformance/cases/bind-derived-skips-invalid-names.json +40 -0
  9. package/dist/binding-conformance/cases/bind-derived-union-dedupes.json +38 -0
  10. package/dist/binding-conformance/cases/bind-gadget-undeclared-none.json +6 -0
  11. package/dist/binding-conformance/cases/bind-reject-charset.json +9 -0
  12. package/dist/binding-conformance/cases/bind-reject-duplicate-pair.json +12 -0
  13. package/dist/binding-conformance/cases/bind-reject-empty-list.json +9 -0
  14. package/dist/binding-conformance/cases/bind-reject-overlong-name.json +13 -0
  15. package/dist/binding-conformance/cases/bind-reject-server-charset.json +9 -0
  16. package/dist/binding-conformance/cases/bind-reject-too-many-entries.json +27 -0
  17. package/dist/binding-conformance/cases/filter-case-sensitive-server.json +7 -0
  18. package/dist/binding-conformance/cases/filter-case-sensitive-tool.json +7 -0
  19. package/dist/binding-conformance/cases/filter-none-passes-bound.json +7 -0
  20. package/dist/binding-conformance/cases/filter-none-passes-unbound.json +6 -0
  21. package/dist/binding-conformance/cases/filter-pair-bare-never-matches.json +7 -0
  22. package/dist/binding-conformance/cases/filter-pair-exact.json +10 -0
  23. package/dist/binding-conformance/cases/filter-pair-not-cross-entry.json +10 -0
  24. package/dist/binding-conformance/cases/filter-server-excludes-bare.json +7 -0
  25. package/dist/binding-conformance/cases/filter-server-match.json +7 -0
  26. package/dist/binding-conformance/cases/filter-tool-cross-server.json +7 -0
  27. package/dist/binding-conformance/cases/filter-tool-excludes-unbound.json +6 -0
  28. package/dist/binding-conformance/cases/filter-tool-matches-bare-entry.json +7 -0
  29. package/dist/binding-conformance/cases/filter-tool-no-match.json +7 -0
  30. package/dist/binding-conformance/index.d.ts +214 -0
  31. package/dist/binding-conformance/index.d.ts.map +1 -0
  32. package/dist/binding-conformance/index.js +153 -0
  33. package/dist/fixtures/consume-buffer/index.d.ts.map +1 -1
  34. package/dist/fixtures/consume-buffer/index.js +4 -1
  35. package/dist/fixtures/index.d.ts +42 -4
  36. package/dist/fixtures/index.d.ts.map +1 -1
  37. package/dist/fixtures/index.js +42 -4
  38. package/dist/fixtures/reserved-channel-authority/index.d.ts.map +1 -1
  39. package/dist/fixtures/reserved-channel-authority/index.js +4 -2
  40. package/dist/index.d.ts +4 -0
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +12 -0
  43. package/dist/match-behavior.d.ts.map +1 -1
  44. package/dist/match-behavior.js +4 -2
  45. package/dist/resolution-conformance/cases/resolve-bundle-host-computed.json +3 -3
  46. package/dist/resolution-conformance/cases/resolve-default-host.json +2 -2
  47. package/dist/resolution-conformance/cases/resolve-loopback-host-http-scheme.json +2 -2
  48. package/dist/resource-read-conformance/cases/all-ephemeral-substrate-fuses-like-none.json +29 -0
  49. package/dist/resource-read-conformance/cases/channel-less-read-mounts-inline.json +24 -0
  50. package/dist/resource-read-conformance/cases/evicted-row-remints-from-the-durable-record.json +26 -0
  51. package/dist/resource-read-conformance/cases/half-wired-blueprints-only-substrate-fuses-like-none.json +29 -0
  52. package/dist/resource-read-conformance/cases/half-wired-identity-only-substrate-fuses-like-none.json +29 -0
  53. package/dist/resource-read-conformance/cases/live-row-read-returns-mount-material.json +18 -0
  54. package/dist/resource-read-conformance/cases/malformed-locator-stays-outside-the-typed-set.json +19 -0
  55. package/dist/resource-read-conformance/cases/read-miss-answers-not-found.json +23 -0
  56. package/dist/resource-read-conformance/cases/read-on-a-substrate-less-server-answers-not-supported.json +22 -0
  57. package/dist/resource-read-conformance/cases/read-record-with-purged-blueprint-answers-blueprint-unresolvable.json +29 -0
  58. package/dist/resource-read-conformance/cases/read-refusal-is-indistinguishable-from-a-miss.json +47 -0
  59. package/dist/resource-read-conformance/cases/read-without-a-delivery-channel-answers-not-mountable.json +33 -0
  60. package/dist/resource-read-conformance/cases/registry-match-fuses-on-not-mountable.json +40 -0
  61. package/dist/resource-read-conformance/cases/substrate-less-fusion-of-refusal-and-miss.json +29 -0
  62. package/dist/resource-read-conformance/index.d.ts +383 -0
  63. package/dist/resource-read-conformance/index.d.ts.map +1 -0
  64. package/dist/resource-read-conformance/index.js +793 -0
  65. package/package.json +13 -3
@@ -6,7 +6,7 @@
6
6
  "version": "2.3.1"
7
7
  },
8
8
  "expect": {
9
- "bundleUrl": "https://registry.ggui.ai/bundles/@acme/leaflet-wrapper/2.3.1/bundle.js",
10
- "styleUrl": "https://registry.ggui.ai/bundles/@acme/leaflet-wrapper/2.3.1/style.css"
9
+ "bundleUrl": "https://registry.ggui.ai/bundles/public/@acme/leaflet-wrapper/2.3.1/bundle.js",
10
+ "styleUrl": "https://registry.ggui.ai/bundles/public/@acme/leaflet-wrapper/2.3.1/style.css"
11
11
  }
12
12
  }
@@ -7,7 +7,7 @@
7
7
  "bundleHost": "localhost:4873"
8
8
  },
9
9
  "expect": {
10
- "bundleUrl": "http://localhost:4873/bundles/@acme/leaflet-wrapper/2.3.1/bundle.js",
11
- "styleUrl": "http://localhost:4873/bundles/@acme/leaflet-wrapper/2.3.1/style.css"
10
+ "bundleUrl": "http://localhost:4873/bundles/public/@acme/leaflet-wrapper/2.3.1/bundle.js",
11
+ "styleUrl": "http://localhost:4873/bundles/public/@acme/leaflet-wrapper/2.3.1/style.css"
12
12
  }
13
13
  }
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "all-ephemeral-substrate-fuses-like-none",
3
+ "description": "A server binding the WHOLE substrate out of stores that declare ephemeral durability keeps no durable record — a restart erases everything — so it MUST fuse exactly like a substrate-less one (#457). Binding is not durability: deriving the NOT_SUPPORTED/NOT_FOUND split from mere binding lets an operator with three in-memory stores promise restorability the deployment cannot deliver, and the promise breaks silently, on the first restart, for every locator at once.",
4
+ "server": { "durableSubstrate": "all-ephemeral", "liveChannel": true },
5
+ "caller": "other",
6
+ "seeds": [{ "kind": "committed-render", "session": "6b2f8d13-4a5c-4e97-8f21-9d0c3b7a5e14" }],
7
+ "reads": [
8
+ {
9
+ "as": "refused",
10
+ "locator": { "kind": "render", "session": "6b2f8d13-4a5c-4e97-8f21-9d0c3b7a5e14" },
11
+ "expect": {
12
+ "kind": "typed-error",
13
+ "jsonRpcCode": -32006,
14
+ "dataCode": "NOT_SUPPORTED"
15
+ }
16
+ },
17
+ {
18
+ "as": "miss",
19
+ "locator": { "kind": "render", "session": "0c9e4f72-8b1d-4a63-95e8-2f6a7d3c1b58" },
20
+ "expect": {
21
+ "kind": "typed-error",
22
+ "jsonRpcCode": -32006,
23
+ "dataCode": "NOT_SUPPORTED"
24
+ }
25
+ }
26
+ ],
27
+ "indistinguishable": ["refused", "miss"],
28
+ "disclosesNothing": ["6b2f8d13-4a5c-4e97-8f21-9d0c3b7a5e14"]
29
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "channel-less-read-mounts-inline",
3
+ "description": "The inline static channel makes a channel-less server mountable: no static component URL is wired, no live channel is wired, but the committed component fits the inline codeB64 cap — so the read returns a shell whose projected render meta declares the inline channel, not a typed failure. This is the success half of the size split whose failure half is read-without-a-delivery-channel-answers-not-mountable: the SAME server wiring answers by component size class, which is what makes the inline channel a real delivery channel rather than a serving detail.",
4
+ "server": { "durableSubstrate": "all" },
5
+ "caller": "owner",
6
+ "seeds": [
7
+ {
8
+ "kind": "committed-render",
9
+ "session": "3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70",
10
+ "size": "under-inline-cap"
11
+ }
12
+ ],
13
+ "reads": [
14
+ {
15
+ "as": "inline",
16
+ "locator": {
17
+ "kind": "render",
18
+ "session": "3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70",
19
+ "key": { "kind": "literal", "value": "fedcba9876543210" }
20
+ },
21
+ "expect": { "kind": "live-mount" }
22
+ }
23
+ ]
24
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "evicted-row-remints-from-the-durable-record",
3
+ "description": "The success half on the path the durable substrate exists for. The render row is gone, but the record naming what it was survives, the blueprint it names is stored, and the component body behind that blueprint is still there — so the read restores it and hands back real mount material. Without this case the catalog would grade a server that answers every evicted locator with a typed error as fully conformant, which is the direction a broken re-mint fails in.",
4
+ "server": { "durableSubstrate": "all", "liveChannel": true },
5
+ "caller": "owner",
6
+ "seeds": [
7
+ {
8
+ "kind": "identity-record",
9
+ "session": "3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70",
10
+ "key": "fedcba9876543210",
11
+ "blueprint": "named"
12
+ },
13
+ { "kind": "durable-blueprint", "componentRef": "present", "body": "stored" }
14
+ ],
15
+ "reads": [
16
+ {
17
+ "as": "reminted",
18
+ "locator": {
19
+ "kind": "render",
20
+ "session": "3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70",
21
+ "key": { "kind": "literal", "value": "fedcba9876543210" }
22
+ },
23
+ "expect": { "kind": "live-mount" }
24
+ }
25
+ ]
26
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "half-wired-blueprints-only-substrate-fuses-like-none",
3
+ "description": "The other half-wired shape: blueprint and component storage bound, no record of what any render was. Without the record there is nothing to look a blueprint up BY, so this server restores nothing either and owes the same fused answer as one wired for nothing at all.",
4
+ "server": { "durableSubstrate": "blueprints-only", "liveChannel": true },
5
+ "caller": "other",
6
+ "seeds": [{ "kind": "committed-render", "session": "3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70" }],
7
+ "reads": [
8
+ {
9
+ "as": "refused",
10
+ "locator": { "kind": "render", "session": "3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70" },
11
+ "expect": {
12
+ "kind": "typed-error",
13
+ "jsonRpcCode": -32006,
14
+ "dataCode": "NOT_SUPPORTED"
15
+ }
16
+ },
17
+ {
18
+ "as": "miss",
19
+ "locator": { "kind": "render", "session": "8d5b0e41-2c96-4a7f-b3d8-1e07f9a2c645" },
20
+ "expect": {
21
+ "kind": "typed-error",
22
+ "jsonRpcCode": -32006,
23
+ "dataCode": "NOT_SUPPORTED"
24
+ }
25
+ }
26
+ ],
27
+ "indistinguishable": ["refused", "miss"],
28
+ "disclosesNothing": ["3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70"]
29
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "half-wired-identity-only-substrate-fuses-like-none",
3
+ "description": "A server holding the record store and nothing else can restore no render, so it is as substrate-less as one holding nothing. This is where the fusion is easiest to get wrong: the re-mint is consulted only when the row is absent, so a verdict derived from a partial substrate check answers NOT_FOUND for a row that exists and NOT_SUPPORTED for one that never did — the existence oracle, rebuilt out of a provisioning mistake.",
4
+ "server": { "durableSubstrate": "identity-only", "liveChannel": true },
5
+ "caller": "other",
6
+ "seeds": [{ "kind": "committed-render", "session": "3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70" }],
7
+ "reads": [
8
+ {
9
+ "as": "refused",
10
+ "locator": { "kind": "render", "session": "3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70" },
11
+ "expect": {
12
+ "kind": "typed-error",
13
+ "jsonRpcCode": -32006,
14
+ "dataCode": "NOT_SUPPORTED"
15
+ }
16
+ },
17
+ {
18
+ "as": "miss",
19
+ "locator": { "kind": "render", "session": "8d5b0e41-2c96-4a7f-b3d8-1e07f9a2c645" },
20
+ "expect": {
21
+ "kind": "typed-error",
22
+ "jsonRpcCode": -32006,
23
+ "dataCode": "NOT_SUPPORTED"
24
+ }
25
+ }
26
+ ],
27
+ "indistinguishable": ["refused", "miss"],
28
+ "disclosesNothing": ["3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70"]
29
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "live-row-read-returns-mount-material",
3
+ "description": "The success half of the invariant, on the simplest path: the render is still live and the caller owns it. The result's contents must declare a delivery channel — a component URL, a live channel carrying BOTH an endpoint and a token, or a server-emitted system card. Graded on the projected render meta, never on markup: what the shell looks like is a server's own presentation concern. Note the blueprintKey segment names nothing this server has ever stored, and the read succeeds anyway — that is deliberate, and it makes a second obligation graded here: when the row is present and readable, the ROW is what gets mounted and the supplied key is not consulted. A server that validated the key against its own records and refused the mismatch would fail this case, correctly, because a resume locator's key exists to resolve a render that is GONE.",
4
+ "server": { "durableSubstrate": "all", "liveChannel": true },
5
+ "caller": "owner",
6
+ "seeds": [{ "kind": "committed-render", "session": "3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70" }],
7
+ "reads": [
8
+ {
9
+ "as": "live",
10
+ "locator": {
11
+ "kind": "render",
12
+ "session": "3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70",
13
+ "key": { "kind": "literal", "value": "fedcba9876543210" }
14
+ },
15
+ "expect": { "kind": "live-mount" }
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "malformed-locator-stays-outside-the-typed-set",
3
+ "description": "A URI with an empty session segment names no render locator, so it is not a read of one and the four classifications do not apply. The graded law is exactly one negative: the error carries NO resource-read code on error.data.code. The NUMBER is not graded, not even negatively — MCP assigns the resource-missing number to a resources/read of a URI the server does not serve, so a framework mapping every unrecognized URI onto it is correct and must not fail here. The classification alone keeps the two apart: a genuine miss carries NOT_FOUND and the constant message, a malformed URI carries no classification at all.",
4
+ "server": { "durableSubstrate": "all", "liveChannel": true },
5
+ "caller": "owner",
6
+ "seeds": [],
7
+ "reads": [
8
+ {
9
+ "as": "empty-session",
10
+ "locator": { "kind": "raw", "uri": "ui://ggui/render/" },
11
+ "expect": { "kind": "outside-typed-set" }
12
+ },
13
+ {
14
+ "as": "empty-session-with-key",
15
+ "locator": { "kind": "raw", "uri": "ui://ggui/render//fedcba9876543210" },
16
+ "expect": { "kind": "outside-typed-set" }
17
+ }
18
+ ]
19
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "read-miss-answers-not-found",
3
+ "description": "A read of a locator that never existed, on a server that keeps durable records and could have restored one, answers NOT_FOUND on -32002 with a body carrying no detail. -32002 is the number a missing resource already rides on, and for a locator keyed by session id a missing session and a missing resource are one condition. The absent detail is what keeps this answer identical to a refusal.",
4
+ "server": { "durableSubstrate": "all", "liveChannel": true },
5
+ "caller": "owner",
6
+ "seeds": [],
7
+ "reads": [
8
+ {
9
+ "as": "miss",
10
+ "locator": {
11
+ "kind": "render",
12
+ "session": "8d5b0e41-2c96-4a7f-b3d8-1e07f9a2c645",
13
+ "key": { "kind": "literal", "value": "fedcba9876543210" }
14
+ },
15
+ "expect": {
16
+ "kind": "typed-error",
17
+ "jsonRpcCode": -32002,
18
+ "dataCode": "NOT_FOUND",
19
+ "detailAbsent": true
20
+ }
21
+ }
22
+ ]
23
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "read-on-a-substrate-less-server-answers-not-supported",
3
+ "description": "A server that keeps no durable record cannot restore an evicted render for anybody, so a read it cannot serve answers NOT_SUPPORTED on -32006. This is a property of the deployment, not of the locator — which is why the catalog does not grade WHEN the answer is produced. A substrate-less server may answer immediately, before any per-locator work.",
4
+ "server": { "durableSubstrate": "none", "liveChannel": true },
5
+ "caller": "owner",
6
+ "seeds": [],
7
+ "reads": [
8
+ {
9
+ "as": "evicted",
10
+ "locator": {
11
+ "kind": "render",
12
+ "session": "8d5b0e41-2c96-4a7f-b3d8-1e07f9a2c645",
13
+ "key": { "kind": "literal", "value": "fedcba9876543210" }
14
+ },
15
+ "expect": {
16
+ "kind": "typed-error",
17
+ "jsonRpcCode": -32006,
18
+ "dataCode": "NOT_SUPPORTED"
19
+ }
20
+ }
21
+ ]
22
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "read-record-with-purged-blueprint-answers-blueprint-unresolvable",
3
+ "description": "A durable record survives its render and names a blueprint, but the blueprint is gone. The read answers BLUEPRINT_UNRESOLVABLE on -32006 — not an internal error. Nothing malfunctioned: the record kept its promise and the thing it pointed at was reaped. A host reading -32006 knows a retry of this locator cannot succeed, which -32603 would have told it the opposite of.",
4
+ "server": { "durableSubstrate": "all", "liveChannel": true },
5
+ "caller": "owner",
6
+ "seeds": [
7
+ {
8
+ "kind": "identity-record",
9
+ "session": "3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70",
10
+ "key": "fedcba9876543210",
11
+ "blueprint": "named"
12
+ }
13
+ ],
14
+ "reads": [
15
+ {
16
+ "as": "evicted",
17
+ "locator": {
18
+ "kind": "render",
19
+ "session": "3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70",
20
+ "key": { "kind": "literal", "value": "fedcba9876543210" }
21
+ },
22
+ "expect": {
23
+ "kind": "typed-error",
24
+ "jsonRpcCode": -32006,
25
+ "dataCode": "BLUEPRINT_UNRESOLVABLE"
26
+ }
27
+ }
28
+ ]
29
+ }
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "read-refusal-is-indistinguishable-from-a-miss",
3
+ "description": "The core disclosure obligation. A caller with no claim to a render reads a locator that fully resolves for its owner, and reads one that never existed. Both answers must be the same bytes. Anything that varies — a message naming the session, a detail explaining the refusal, a different code because the access check ran late — answers 'does this render exist?' for someone with no right to ask.",
4
+ "server": { "durableSubstrate": "all", "liveChannel": true },
5
+ "caller": "other",
6
+ "seeds": [
7
+ {
8
+ "kind": "identity-record",
9
+ "session": "3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70",
10
+ "key": "fedcba9876543210",
11
+ "blueprint": "named"
12
+ },
13
+ { "kind": "durable-blueprint", "componentRef": "present", "body": "stored" }
14
+ ],
15
+ "reads": [
16
+ {
17
+ "as": "refused",
18
+ "locator": {
19
+ "kind": "render",
20
+ "session": "3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70",
21
+ "key": { "kind": "literal", "value": "fedcba9876543210" }
22
+ },
23
+ "expect": {
24
+ "kind": "typed-error",
25
+ "jsonRpcCode": -32002,
26
+ "dataCode": "NOT_FOUND",
27
+ "detailAbsent": true
28
+ }
29
+ },
30
+ {
31
+ "as": "miss",
32
+ "locator": {
33
+ "kind": "render",
34
+ "session": "8d5b0e41-2c96-4a7f-b3d8-1e07f9a2c645",
35
+ "key": { "kind": "literal", "value": "fedcba9876543210" }
36
+ },
37
+ "expect": {
38
+ "kind": "typed-error",
39
+ "jsonRpcCode": -32002,
40
+ "dataCode": "NOT_FOUND",
41
+ "detailAbsent": true
42
+ }
43
+ }
44
+ ],
45
+ "indistinguishable": ["refused", "miss"],
46
+ "disclosesNothing": ["3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70"]
47
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "read-without-a-delivery-channel-answers-not-mountable",
3
+ "description": "The locator resolves and the caller owns it, but the server wires no way to deliver the component \u2014 neither a static component URL nor a live channel, and the committed component is too large for the inline codeB64 channel (an under-cap component would mount inline; that arm has its own case). The read answers NOT_MOUNTABLE on -32006 rather than handing back a shell with nothing to mount. This is the branch that proves the invariant is about the RESULT, not the lookup: the lookup succeeded.",
4
+ "server": {
5
+ "durableSubstrate": "all"
6
+ },
7
+ "caller": "owner",
8
+ "seeds": [
9
+ {
10
+ "kind": "committed-render",
11
+ "session": "3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70",
12
+ "size": "over-inline-cap"
13
+ }
14
+ ],
15
+ "reads": [
16
+ {
17
+ "as": "resolvable",
18
+ "locator": {
19
+ "kind": "render",
20
+ "session": "3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70",
21
+ "key": {
22
+ "kind": "literal",
23
+ "value": "fedcba9876543210"
24
+ }
25
+ },
26
+ "expect": {
27
+ "kind": "typed-error",
28
+ "jsonRpcCode": -32006,
29
+ "dataCode": "NOT_MOUNTABLE"
30
+ }
31
+ }
32
+ ]
33
+ }
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "registry-match-fuses-on-not-mountable",
3
+ "description": "The one place a server keeping no durable record answers something other than NOT_SUPPORTED for a read it cannot mount: the blueprint registry MATCHED the caller's key, so what the read found is a component it has no channel to deliver. The answer is NOT_MOUNTABLE — and because the match depends on the key rather than on the row, it is still identical for a refused read and a miss. This server wires NO delivery channel at all, which is what makes undeliverability follow from the declared shape rather than from any one implementation's choice about how it serves a registry match.",
4
+ "server": { "durableSubstrate": "none", "blueprintRegistry": true },
5
+ "caller": "other",
6
+ "seeds": [
7
+ { "kind": "registered-blueprint", "as": "fallback" },
8
+ { "kind": "committed-render", "session": "3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70" }
9
+ ],
10
+ "reads": [
11
+ {
12
+ "as": "refused",
13
+ "locator": {
14
+ "kind": "render",
15
+ "session": "3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70",
16
+ "key": { "kind": "registered", "seed": "fallback" }
17
+ },
18
+ "expect": {
19
+ "kind": "typed-error",
20
+ "jsonRpcCode": -32006,
21
+ "dataCode": "NOT_MOUNTABLE"
22
+ }
23
+ },
24
+ {
25
+ "as": "miss",
26
+ "locator": {
27
+ "kind": "render",
28
+ "session": "8d5b0e41-2c96-4a7f-b3d8-1e07f9a2c645",
29
+ "key": { "kind": "registered", "seed": "fallback" }
30
+ },
31
+ "expect": {
32
+ "kind": "typed-error",
33
+ "jsonRpcCode": -32006,
34
+ "dataCode": "NOT_MOUNTABLE"
35
+ }
36
+ }
37
+ ],
38
+ "indistinguishable": ["refused", "miss"],
39
+ "disclosesNothing": ["3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70"]
40
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "substrate-less-fusion-of-refusal-and-miss",
3
+ "description": "The disclosure obligation restated for a server that keeps no durable record. NOT_SUPPORTED describes the server, so it must answer for a refused row too. A deployment that reported NOT_FOUND for rows that exist and NOT_SUPPORTED for ones that never did would have rebuilt the existence oracle out of its own wiring.",
4
+ "server": { "durableSubstrate": "none", "liveChannel": true },
5
+ "caller": "other",
6
+ "seeds": [{ "kind": "committed-render", "session": "3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70" }],
7
+ "reads": [
8
+ {
9
+ "as": "refused",
10
+ "locator": { "kind": "render", "session": "3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70" },
11
+ "expect": {
12
+ "kind": "typed-error",
13
+ "jsonRpcCode": -32006,
14
+ "dataCode": "NOT_SUPPORTED"
15
+ }
16
+ },
17
+ {
18
+ "as": "miss",
19
+ "locator": { "kind": "render", "session": "8d5b0e41-2c96-4a7f-b3d8-1e07f9a2c645" },
20
+ "expect": {
21
+ "kind": "typed-error",
22
+ "jsonRpcCode": -32006,
23
+ "dataCode": "NOT_SUPPORTED"
24
+ }
25
+ }
26
+ ],
27
+ "indistinguishable": ["refused", "miss"],
28
+ "disclosesNothing": ["3f1a9c22-7b4e-4d18-9a05-6c2e8b1d4f70"]
29
+ }