dev.cocore.inference.dispatch

cocore.dev

Schema Diff

+15 -1

From

CID
bafyreifr55vvhyq...
Indexed At
2026-06-21 00:58 UTC
View this version

To

CID
bafyreie2gz2hieb...
Indexed At
2026-06-25 16:59 UTC
View this version

Compatibility Analysis

Breaking Changes Detected

2 breaking changes, 4 non-breaking changes.

Breaking Changes (2)
  • ConstraintAdded ConstraintAdded { vertex_id: "dev.cocore.inference.dispatch:input.nonce", sort: "maxLength", value: "64" }
  • ConstraintAdded ConstraintAdded { vertex_id: "dev.cocore.inference.dispatch:input.nonce", sort: "minLength", value: "32" }
Non-Breaking Changes (4)
  • AddedVertex AddedVertex { vertex_id: "dev.cocore.inference.dispatch:input.nonce" }
  • AddedVertex AddedVertex { vertex_id: "dev.cocore.inference.dispatch:input.requireConfidential" }
  • AddedEdge AddedEdge { src: "dev.cocore.inference.dispatch:input", tgt: "dev.cocore.inference.dispatch:input.nonce", kind: "prop", name: Some("nonce") }
  • AddedEdge AddedEdge { src: "dev.cocore.inference.dispatch:input", tgt: "dev.cocore.inference.dispatch:input.requireConfidential", kind: "prop", name: Some("requireConfidential") }

Migration Guidance

Added Elements

  • AddedVertex { vertex_id: "dev.cocore.inference.dispatch:input.nonce" }
  • AddedVertex { vertex_id: "dev.cocore.inference.dispatch:input.requireConfidential" }

Constraint Changes

  • ConstraintAdded ConstraintAdded { vertex_id: "dev.cocore.inference.dispatch:input.nonce", sort: "maxLength", value: "64" }
  • ConstraintAdded ConstraintAdded { vertex_id: "dev.cocore.inference.dispatch:input.nonce", sort: "minLength", value: "32" }

Additional Notes

  • Non-breaking: AddedEdge { src: "dev.cocore.inference.dispatch:input", tgt: "dev.cocore.inference.dispatch:input.nonce", kind: "prop", name: Some("nonce") }
  • Non-breaking: AddedEdge { src: "dev.cocore.inference.dispatch:input", tgt: "dev.cocore.inference.dispatch:input.requireConfidential", kind: "prop", name: Some("requireConfidential") }
1 1
{
2 2
  "id": "dev.cocore.inference.dispatch",
3 3
  "defs": {
4 4
    "main": {
5 5
      "type": "procedure",
6 6
      "input": {
7 7
        "schema": {
8 8
          "type": "object",
9 9
          "required": [
10 10
            "model",
11 11
            "prompt",
12 12
            "maxTokensOut",
13 13
            "priceCeiling"
14 14
          ],
15 15
          "properties": {
16 16
            "model": {
17 17
              "type": "string",
18 18
              "minLength": 1
19 19
            },
20 +
            "nonce": {
21 +
              "type": "string",
22 +
              "maxLength": 64,
23 +
              "minLength": 32,
24 +
              "description": "Fresh lowercase-hex freshness challenge (>=16 random bytes) supplied by the caller when `requireConfidential` is set. The provider's enclave signs (ephemeralPubKey || nonce || attestationCid) so the caller can prove the ephemeral seal key was minted for THIS request and is not replayed. Required when requireConfidential is true; ignored otherwise."
25 +
            },
20 26
            "prompt": {
21 27
              "type": "string",
22 28
              "minLength": 1
23 29
            },
24 30
            "maxTokensOut": {
25 31
              "type": "integer",
26 32
              "minimum": 1
27 33
            },
28 34
            "priceCeiling": {
29 35
              "type": "object",
30 36
              "required": [
31 37
                "amount",
32 38
                "currency"
33 39
              ],
34 40
              "properties": {
35 41
                "amount": {
36 42
                  "type": "integer",
37 43
                  "minimum": 0
38 44
                },
39 45
                "currency": {
40 46
                  "type": "string",
41 47
                  "minLength": 1
42 48
                }
43 49
              }
44 50
            },
45 51
            "targetProviderDid": {
46 52
              "type": "string",
47 53
              "format": "did",
48 54
              "description": "Pin dispatch to a specific provider DID instead of letting the advisor route."
55 +
            },
56 +
            "requireConfidential": {
57 +
              "type": "boolean",
58 +
              "description": "Demand the `attested-confidential` tier: the chosen provider must present a verified, signing-key-bound Apple MDA chain, a known-good measured cdHash, the hardened-runtime posture, and a fresh enclave-signed ephemeral session key bound to `nonce`. If no eligible provider is available the request fails closed with `ConfidentialUnavailable` rather than silently downgrading to best-effort. Optional / additive; absent or false means best-effort."
49 59
            }
50 60
          }
51 61
        },
52 62
        "encoding": "application/json"
53 63
      },
54 64
      "errors": [
55 65
        {
56 66
          "name": "AuthRequired",
57 67
          "description": "The caller is not authenticated."
58 68
        },
59 69
        {
60 70
          "name": "InvalidRequest",
61 71
          "description": "The body failed validation."
72 +
        },
73 +
        {
74 +
          "name": "ConfidentialUnavailable",
75 +
          "description": "requireConfidential was set but no provider could satisfy the attested-confidential tier (no verified+bound MDA chain, cdHash not in the known-good set, posture failed, or the ephemeral session handshake did not verify). The request was NOT downgraded; no prompt was sealed."
62 76
        }
63 77
      ],
64 78
      "output": {
65 79
        "encoding": "text/event-stream",
66 80
        "description": "A Server-Sent Events stream of `meta`, `chunk`, `complete`, and `error` frames (see the method description for payloads)."
67 81
      },
68 -
      "description": "Submit an inference request and stream the result back as Server-Sent Events. Authenticates the requester, runs the dispatch core, and emits typed SSE frames. Unlike `submit` (which returns URIs to poll), `dispatch` drives the full request and streams plaintext output chunks until completion.\n\nSSE events:\n  * `meta`     — { jobUri, jobCid, authUri, inputCommitment, providerDid, sessionId }\n  * `chunk`    — { seq, text }   (plaintext, decrypted)\n  * `complete` — { tokensIn, tokensOut, receiptUri, providerCredit? }\n  * `error`    — { reason, code }"
82 +
      "description": "Submit an inference request and stream the result back as Server-Sent Events. Authenticates the requester, runs the dispatch core, and emits typed SSE frames. Unlike `submit` (which returns URIs to poll), `dispatch` drives the full request and streams plaintext output chunks until completion.\n\nConfidentiality: by default the AppView seals the prompt to the chosen provider on the caller's behalf (`best-effort` tier) — convenient, but the AppView is in the plaintext path. A caller that needs privacy FROM the provider sets `requireConfidential` and supplies a fresh `nonce`; the AppView then runs the verified, enclave-bound ephemeral handshake and either confirms an `attested-confidential` session or fails closed with the `ConfidentialUnavailable` error. For genuine end-to-end confidentiality the prompt is sealed at the client edge (SDK/browser) and the AppView forwards ciphertext only; this method's server-side seal path is always `best-effort`.\n\nSSE events:\n  * `meta`       — { jobUri, jobCid, authUri, inputCommitment, providerDid, sessionId, tier }\n  * `sessionKey` — { ephemeralPubKey, nonce, attestationCid, signature }   (only when `requireConfidential`; the enclave-signed fresh key the requester verifies before sealing)\n  * `chunk`      — { seq, text }   (plaintext, decrypted)\n  * `complete`   — { tokensIn, tokensOut, receiptUri, tier, providerCredit? }\n  * `error`      — { reason, code }"
69 83
    }
70 84
  },
71 85
  "$type": "com.atproto.lexicon.schema",
72 86
  "lexicon": 1
73 87
}

Compare Other Versions

Lexicon Garden

@