full diff

dev.cocore.devicePair.start

cocore.dev +40 −1
From
bafyreibupusaow3u5mg7pikgsaarvnfn5u2xuvizwofshi7c4hanob6pnu indexed 2026-06-21 00:58 UTC View this version
To
bafyreifujrh63pgqjy7ycyr3p3vifv2l6j4xgepxoayne2d73jktw3nc4i indexed 2026-10-29 21:53 UTC View this version

Compatibility

backward compatible Backward compatible. 10 non-breaking changes.

Non-breaking changes (10)
  • AddedVertex AddedVertex { vertex_id: "dev.cocore.devicePair.start:input" }
  • AddedVertex AddedVertex { vertex_id: "dev.cocore.devicePair.start:input.appDid" }
  • AddedVertex AddedVertex { vertex_id: "dev.cocore.devicePair.start:input.appName" }
  • AddedVertex AddedVertex { vertex_id: "dev.cocore.devicePair.start:input.keyName" }
  • AddedVertex AddedVertex { vertex_id: "dev.cocore.devicePair.start:input.returnUrl" }
  • AddedEdge AddedEdge { src: "dev.cocore.devicePair.start", tgt: "dev.cocore.devicePair.start:input", kind: "prop", name: Some("input") }
  • AddedEdge AddedEdge { src: "dev.cocore.devicePair.start:input", tgt: "dev.cocore.devicePair.start:input.appDid", kind: "prop", name: Some("appDid") }
  • AddedEdge AddedEdge { src: "dev.cocore.devicePair.start:input", tgt: "dev.cocore.devicePair.start:input.appName", kind: "prop", name: Some("appName") }
  • AddedEdge AddedEdge { src: "dev.cocore.devicePair.start:input", tgt: "dev.cocore.devicePair.start:input.keyName", kind: "prop", name: Some("keyName") }
  • AddedEdge AddedEdge { src: "dev.cocore.devicePair.start:input", tgt: "dev.cocore.devicePair.start:input.returnUrl", kind: "prop", name: Some("returnUrl") }

Migration guidance

Added

  • AddedVertex { vertex_id: "dev.cocore.devicePair.start:input" }
  • AddedVertex { vertex_id: "dev.cocore.devicePair.start:input.appDid" }
  • AddedVertex { vertex_id: "dev.cocore.devicePair.start:input.appName" }
  • AddedVertex { vertex_id: "dev.cocore.devicePair.start:input.keyName" }
  • AddedVertex { vertex_id: "dev.cocore.devicePair.start:input.returnUrl" }

Notes

  • Non-breaking: AddedEdge { src: "dev.cocore.devicePair.start", tgt: "dev.cocore.devicePair.start:input", kind: "prop", name: Some("input") }
  • Non-breaking: AddedEdge { src: "dev.cocore.devicePair.start:input", tgt: "dev.cocore.devicePair.start:input.appDid", kind: "prop", name: Some("appDid") }
  • Non-breaking: AddedEdge { src: "dev.cocore.devicePair.start:input", tgt: "dev.cocore.devicePair.start:input.appName", kind: "prop", name: Some("appName") }
  • Non-breaking: AddedEdge { src: "dev.cocore.devicePair.start:input", tgt: "dev.cocore.devicePair.start:input.keyName", kind: "prop", name: Some("keyName") }
  • Non-breaking: AddedEdge { src: "dev.cocore.devicePair.start:input", tgt: "dev.cocore.devicePair.start:input.returnUrl", kind: "prop", name: Some("returnUrl") }

Changes

11{
22 "$type": "com.atproto.lexicon.schema",
33 "defs": {
44 "main": {
5 "description": "Begin a device-pairing flow (OAuth 2.0 device-authorization style). Returns a `deviceId` plus a short human-typable `userCode` and the `verificationUri` where a signed-in user approves the pairing. The caller then polls `dev.cocore.devicePair.poll` until approval.",
5 "description": "Begin a device-pairing flow (OAuth 2.0 device-authorization style). Returns a `deviceId` plus a short human-typable `userCode` and the `verificationUri` where a signed-in user approves the pairing. The caller then polls `dev.cocore.devicePair.poll` until approval. The optional input lets an application (rather than a provider machine) say who it is: `appName` is shown on the approve screen, `keyName` names the minted API key so the user can recognise and revoke it, and `returnUrl` is where the approve screen sends the browser afterwards. `returnUrl` is honoured only for hosts the deployment allowlists; anything else is dropped silently, never rejected.",
6 "errors": [
7 {
8 "description": "Too many pairing attempts from this client; retry later.",
9 "name": "RateLimited"
10 },
11 {
12 "description": "`appDid` is not a DID, or has no `dev.cocore.app.registration` record (message begins `AppNotRegistered`).",
13 "name": "InvalidRequest"
14 }
15 ],
16 "input": {
17 "encoding": "application/json",
18 "schema": {
19 "properties": {
20 "appDid": {
21 "description": "The requesting application's DID. When present the AppView reads the app's `dev.cocore.app.registration` record: the approve screen shows that record's `name` (the `appName` field is ignored) and `returnUrl` is honoured only if it matches one of the record's `returnUrls` AND the return host proves ownership via `/.well-known/cocore-app.json`. A DID with no registration record is rejected with InvalidRequest (AppNotRegistered).",
22 "format": "did",
23 "type": "string"
24 },
25 "appName": {
26 "description": "Human name of the requesting application, shown on the approve screen.",
27 "maxLength": 40,
28 "type": "string"
29 },
30 "keyName": {
31 "description": "Name for the API key minted on approval.",
32 "maxLength": 100,
33 "type": "string"
34 },
35 "returnUrl": {
36 "description": "Where to send the browser after approval. Must be https and on an allowlisted host.",
37 "format": "uri",
38 "maxLength": 2000,
39 "type": "string"
40 }
41 },
42 "type": "object"
43 }
44 },
645 "output": {
746 "encoding": "application/json",
847 "schema": {
948 "properties": {
1049 "deviceId": {
1150 "type": "string"
1251 },
1352 "expiresInSecs": {
1453 "description": "Seconds until this pairing attempt expires.",
1554 "type": "integer"
1655 },
1756 "pollIntervalSecs": {
1857 "description": "Minimum seconds between poll calls.",
1958 "type": "integer"
2059 },
2160 "userCode": {
2261 "description": "Short code the user types at the verification URI.",
2362 "type": "string"
2463 },
2564 "verificationUri": {
2665 "format": "uri",
2766 "type": "string"
2867 }
2968 },
3069 "required": [
3170 "deviceId",
3271 "userCode",
3372 "verificationUri",
3473 "pollIntervalSecs",
3574 "expiresInSecs"
3675 ],
3776 "type": "object"
3877 }
3978 },
4079 "type": "procedure"
4180 }
4281 },
4382 "id": "dev.cocore.devicePair.start",
4483 "lexicon": 1
4584}

Compare other versions