at.happyproto.registry.publishRelease

happyproto.at

Schema Diff

+74 -24

From

CID
bafyreih5q5yjgn7...
Indexed At
2026-10-19 18:20 UTC
View this version

To

CID
bafyreidl4d7esak...
Indexed At
2026-10-26 21:34 UTC
View this version

Compatibility Analysis

Breaking Changes Detected

10 breaking changes, 23 non-breaking changes.

Breaking Changes (10)
  • RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "at.happyproto.registry.publishRelease:input", src: "at.happyproto.registry.publishRelease:input", tgt: "at.happyproto.registry.publishRelease:input.version", kind: "prop", name: Some("version") }
  • RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "at.happyproto.registry.publishRelease:input", src: "at.happyproto.registry.publishRelease:input", tgt: "at.happyproto.registry.publishRelease:input.track", kind: "prop", name: Some("track") }
  • RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "at.happyproto.registry.publishRelease:input", src: "at.happyproto.registry.publishRelease:input", tgt: "at.happyproto.registry.publishRelease:input.name", kind: "prop", name: Some("name") }
  • RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "at.happyproto.registry.publishRelease:input", src: "at.happyproto.registry.publishRelease:input", tgt: "at.happyproto.registry.publishRelease:input.artifact", kind: "prop", name: Some("artifact") }
  • RequiredEdgeRemoved RequiredEdgeRemoved { vertex_id: "at.happyproto.registry.publishRelease:input", src: "at.happyproto.registry.publishRelease:input", tgt: "at.happyproto.registry.publishRelease:input.record", kind: "prop", name: Some("record") }
  • RemovedVertex RemovedVertex { vertex_id: "at.happyproto.registry.publishRelease:input.record" }
  • RemovedVertex RemovedVertex { vertex_id: "at.happyproto.registry.publishRelease:output.cid" }
  • RemovedVertex RemovedVertex { vertex_id: "at.happyproto.registry.publishRelease:output.uri" }
  • RemovedEdge RemovedEdge { src: "at.happyproto.registry.publishRelease:output", tgt: "at.happyproto.registry.publishRelease:output.cid", kind: "prop", name: Some("cid") }
  • RemovedEdge RemovedEdge { src: "at.happyproto.registry.publishRelease:output", tgt: "at.happyproto.registry.publishRelease:output.uri", kind: "prop", name: Some("uri") }
Non-Breaking Changes (23)
  • AddedVertex AddedVertex { vertex_id: "at.happyproto.plugin.v1" }
  • AddedVertex AddedVertex { vertex_id: "at.happyproto.registry.defs#ref" }
  • AddedVertex AddedVertex { vertex_id: "at.happyproto.registry.publishRelease:input.artifact" }
  • AddedVertex AddedVertex { vertex_id: "at.happyproto.registry.publishRelease:input.changelog" }
  • AddedVertex AddedVertex { vertex_id: "at.happyproto.registry.publishRelease:input.name" }
  • AddedVertex AddedVertex { vertex_id: "at.happyproto.registry.publishRelease:input.track" }
  • AddedVertex AddedVertex { vertex_id: "at.happyproto.registry.publishRelease:input.version" }
  • AddedVertex AddedVertex { vertex_id: "at.happyproto.registry.publishRelease:output.changelog" }
  • AddedVertex AddedVertex { vertex_id: "at.happyproto.registry.publishRelease:output.channel" }
  • AddedVertex AddedVertex { vertex_id: "at.happyproto.registry.publishRelease:output.manifest" }
  • AddedVertex AddedVertex { vertex_id: "at.happyproto.registry.publishRelease:output.resumed" }
  • AddedVertex AddedVertex { vertex_id: "at.happyproto.registry.publishRelease:output.version" }
  • AddedEdge AddedEdge { src: "at.happyproto.registry.publishRelease:input", tgt: "at.happyproto.registry.publishRelease:input.changelog", kind: "prop", name: Some("changelog") }
  • AddedEdge AddedEdge { src: "at.happyproto.registry.publishRelease:input.artifact", tgt: "at.happyproto.plugin.v1", kind: "ref", name: None }
  • AddedEdge AddedEdge { src: "at.happyproto.registry.publishRelease:output", tgt: "at.happyproto.registry.publishRelease:output.changelog", kind: "prop", name: Some("changelog") }
  • AddedEdge AddedEdge { src: "at.happyproto.registry.publishRelease:output", tgt: "at.happyproto.registry.publishRelease:output.channel", kind: "prop", name: Some("channel") }
  • AddedEdge AddedEdge { src: "at.happyproto.registry.publishRelease:output", tgt: "at.happyproto.registry.publishRelease:output.manifest", kind: "prop", name: Some("manifest") }
  • AddedEdge AddedEdge { src: "at.happyproto.registry.publishRelease:output", tgt: "at.happyproto.registry.publishRelease:output.resumed", kind: "prop", name: Some("resumed") }
  • AddedEdge AddedEdge { src: "at.happyproto.registry.publishRelease:output", tgt: "at.happyproto.registry.publishRelease:output.version", kind: "prop", name: Some("version") }
  • AddedEdge AddedEdge { src: "at.happyproto.registry.publishRelease:output.changelog", tgt: "at.happyproto.registry.defs#ref", kind: "ref", name: None }
  • AddedEdge AddedEdge { src: "at.happyproto.registry.publishRelease:output.channel", tgt: "at.happyproto.registry.defs#ref", kind: "ref", name: None }
  • AddedEdge AddedEdge { src: "at.happyproto.registry.publishRelease:output.manifest", tgt: "at.happyproto.registry.defs#ref", kind: "ref", name: None }
  • AddedEdge AddedEdge { src: "at.happyproto.registry.publishRelease:output.version", tgt: "at.happyproto.registry.defs#ref", kind: "ref", name: None }

Migration Guidance

Removed Elements

  • RemovedVertex { vertex_id: "at.happyproto.registry.publishRelease:input.record" }
  • RemovedVertex { vertex_id: "at.happyproto.registry.publishRelease:output.cid" }
  • RemovedVertex { vertex_id: "at.happyproto.registry.publishRelease:output.uri" }

Added Elements

  • AddedVertex { vertex_id: "at.happyproto.plugin.v1" }
  • AddedVertex { vertex_id: "at.happyproto.registry.defs#ref" }
  • AddedVertex { vertex_id: "at.happyproto.registry.publishRelease:input.artifact" }
  • AddedVertex { vertex_id: "at.happyproto.registry.publishRelease:input.changelog" }
  • AddedVertex { vertex_id: "at.happyproto.registry.publishRelease:input.name" }
  • AddedVertex { vertex_id: "at.happyproto.registry.publishRelease:input.track" }
  • AddedVertex { vertex_id: "at.happyproto.registry.publishRelease:input.version" }
  • AddedVertex { vertex_id: "at.happyproto.registry.publishRelease:output.changelog" }
  • AddedVertex { vertex_id: "at.happyproto.registry.publishRelease:output.channel" }
  • AddedVertex { vertex_id: "at.happyproto.registry.publishRelease:output.manifest" }
  • AddedVertex { vertex_id: "at.happyproto.registry.publishRelease:output.resumed" }
  • AddedVertex { vertex_id: "at.happyproto.registry.publishRelease:output.version" }

Additional Notes

  • Breaking: RequiredEdgeAdded { vertex_id: "at.happyproto.registry.publishRelease:input", src: "at.happyproto.registry.publishRelease:input", tgt: "at.happyproto.registry.publishRelease:input.version", kind: "prop", name: Some("version") }
  • Breaking: RequiredEdgeAdded { vertex_id: "at.happyproto.registry.publishRelease:input", src: "at.happyproto.registry.publishRelease:input", tgt: "at.happyproto.registry.publishRelease:input.track", kind: "prop", name: Some("track") }
  • Breaking: RequiredEdgeAdded { vertex_id: "at.happyproto.registry.publishRelease:input", src: "at.happyproto.registry.publishRelease:input", tgt: "at.happyproto.registry.publishRelease:input.name", kind: "prop", name: Some("name") }
  • Breaking: RequiredEdgeAdded { vertex_id: "at.happyproto.registry.publishRelease:input", src: "at.happyproto.registry.publishRelease:input", tgt: "at.happyproto.registry.publishRelease:input.artifact", kind: "prop", name: Some("artifact") }
  • Breaking: RequiredEdgeRemoved { vertex_id: "at.happyproto.registry.publishRelease:input", src: "at.happyproto.registry.publishRelease:input", tgt: "at.happyproto.registry.publishRelease:input.record", kind: "prop", name: Some("record") }
  • Breaking: RemovedEdge { src: "at.happyproto.registry.publishRelease:output", tgt: "at.happyproto.registry.publishRelease:output.cid", kind: "prop", name: Some("cid") }
  • Breaking: RemovedEdge { src: "at.happyproto.registry.publishRelease:output", tgt: "at.happyproto.registry.publishRelease:output.uri", kind: "prop", name: Some("uri") }
  • Non-breaking: AddedEdge { src: "at.happyproto.registry.publishRelease:input", tgt: "at.happyproto.registry.publishRelease:input.changelog", kind: "prop", name: Some("changelog") }
  • Non-breaking: AddedEdge { src: "at.happyproto.registry.publishRelease:input.artifact", tgt: "at.happyproto.plugin.v1", kind: "ref", name: None }
  • Non-breaking: AddedEdge { src: "at.happyproto.registry.publishRelease:output", tgt: "at.happyproto.registry.publishRelease:output.changelog", kind: "prop", name: Some("changelog") }
  • Non-breaking: AddedEdge { src: "at.happyproto.registry.publishRelease:output", tgt: "at.happyproto.registry.publishRelease:output.channel", kind: "prop", name: Some("channel") }
  • Non-breaking: AddedEdge { src: "at.happyproto.registry.publishRelease:output", tgt: "at.happyproto.registry.publishRelease:output.manifest", kind: "prop", name: Some("manifest") }
  • Non-breaking: AddedEdge { src: "at.happyproto.registry.publishRelease:output", tgt: "at.happyproto.registry.publishRelease:output.resumed", kind: "prop", name: Some("resumed") }
  • Non-breaking: AddedEdge { src: "at.happyproto.registry.publishRelease:output", tgt: "at.happyproto.registry.publishRelease:output.version", kind: "prop", name: Some("version") }
  • Non-breaking: AddedEdge { src: "at.happyproto.registry.publishRelease:output.changelog", tgt: "at.happyproto.registry.defs#ref", kind: "ref", name: None }
  • Non-breaking: AddedEdge { src: "at.happyproto.registry.publishRelease:output.channel", tgt: "at.happyproto.registry.defs#ref", kind: "ref", name: None }
  • Non-breaking: AddedEdge { src: "at.happyproto.registry.publishRelease:output.manifest", tgt: "at.happyproto.registry.defs#ref", kind: "ref", name: None }
  • Non-breaking: AddedEdge { src: "at.happyproto.registry.publishRelease:output.version", tgt: "at.happyproto.registry.defs#ref", kind: "ref", name: None }
1 1
{
2 2
  "$type": "com.atproto.lexicon.schema",
3 3
  "defs": {
4 4
    "main": {
5 -
      "description": "Check a release against the rules the indexer applies, and optionally write it to the caller's repo. The indexer validates a record only after it is published and skips an invalid one quietly, so a publisher writing the record itself gets no feedback; this answers the same refusal before the record exists. Pass validateOnly to check a record without writing it. Like every XRPC procedure this needs an authenticated caller, so validateOnly is a dry run rather than an anonymous one.",
5 +
      "description": "Publish a version of a plugin to the caller's repo. Writes a software.release.manifest carrying the artifact, the changelog as a site.standard.document when one is given, the software.release.version, and the channel named by track, moved to the new version, in that order. A record is written only once everything it points at exists, so a failure part-way leaves no dangling reference. Calling again with the same input after such a failure finishes the release rather than refusing it.",
6 6
      "errors": [
7 7
        {
8 -
          "description": "The caller's identity could not be determined, so there is no publisher to check the profile against and no repo to write to.",
8 +
          "description": "The caller's identity could not be determined, so there is no repo to write to.",
9 9
          "name": "AuthRequired"
10 10
        },
11 11
        {
12 -
          "description": "The record is not a release the indexer would accept. The message names the reason.",
12 +
          "description": "The registry has no identity configured. An operator problem, not a caller's.",
13 +
          "name": "NotConfigured"
14 +
        },
15 +
        {
16 +
          "description": "The input breaks a rule the registry applies, so it would refuse the records. The message names the field.",
13 17
          "name": "InvalidRecord"
14 18
        },
15 19
        {
16 -
          "description": "That version is already published, or was withdrawn. A version is immutable once released and never reusable; publish a new one.",
17 -
          "name": "VersionExists"
20 +
          "description": "A record could not be written to the caller's repo. Records written before the failure stay, and the same call can be made again.",
21 +
          "name": "Upstream"
18 22
        },
19 23
        {
20 -
          "description": "No profile is indexed at that slug, so the release would index against nothing.",
21 -
          "name": "ProfileMissing"
24 +
          "description": "The caller has no project of that name, or the registry has not indexed its at.happyproto.registry.project record. Call putProject first.",
25 +
          "name": "ProjectMissing"
22 26
        },
23 27
        {
24 -
          "description": "The record could not be written to the caller's repo.",
25 -
          "name": "Upstream"
28 +
          "description": "That version is already published with a different artifact. A version never changes once published; publish a new one.",
29 +
          "name": "VersionExists"
26 30
        },
27 31
        {
28 -
          "description": "The registry has no identity configured.",
29 -
          "name": "NotConfigured"
32 +
          "description": "The project is unavailable or retired, so the channel cannot be moved to a new version.",
33 +
          "name": "NotInstallable"
30 34
        }
31 35
      ],
32 36
      "input": {
33 37
        "encoding": "application/json",
34 38
        "schema": {
35 39
          "properties": {
36 -
            "record": {
37 -
              "description": "An at.happyproto.plugin.release record. Its package and version decide the record key, as the record lexicon requires of them.",
38 -
              "type": "unknown"
40 +
            "artifact": {
41 +
              "description": "The plugin. Every blob it references must already be uploaded to the caller's repo.",
42 +
              "ref": "at.happyproto.plugin.v1",
43 +
              "type": "ref"
44 +
            },
45 +
            "changelog": {
46 +
              "description": "Release notes as CommonMark. The registry writes them to the caller's repo as a site.standard.document and links it from the version.",
47 +
              "maxGraphemes": 20000,
48 +
              "maxLength": 200000,
49 +
              "type": "string"
50 +
            },
51 +
            "name": {
52 +
              "description": "The project's name, which is the record key of its software.release.project: 1 to 64 lowercase letters, digits and interior hyphens.",
53 +
              "maxLength": 64,
54 +
              "minLength": 1,
55 +
              "type": "string"
56 +
            },
57 +
            "track": {
58 +
              "description": "The channel to move to the new version.",
59 +
              "knownValues": [
60 +
                "latest",
61 +
                "beta",
62 +
                "alpha"
63 +
              ],
64 +
              "type": "string"
39 65
            },
40 66
            "validateOnly": {
41 67
              "default": false,
42 -
              "description": "Check the record and write nothing. Still requires authentication, as every procedure does.",
68 +
              "description": "Check the input against every rule the registry applies, and write nothing. Works without authentication, but only a signed-in call is also checked against the caller's existing records.",
43 69
              "type": "boolean"
70 +
            },
71 +
            "version": {
72 +
              "description": "A semver version without build metadata, with an optional lowercase prerelease, such as `1.2.0` or `1.2.0-beta.1`.",
73 +
              "maxLength": 64,
74 +
              "minLength": 1,
75 +
              "type": "string"
44 76
            }
45 77
          },
46 78
          "required": [
47 -
            "record"
79 +
            "name",
80 +
            "version",
81 +
            "track",
82 +
            "artifact"
48 83
          ],
49 84
          "type": "object"
50 85
        }
51 86
      },
52 87
      "output": {
53 88
        "encoding": "application/json",
54 89
        "schema": {
55 90
          "properties": {
56 -
            "cid": {
57 -
              "format": "cid",
58 -
              "type": "string"
91 +
            "changelog": {
92 +
              "description": "The changelog's site.standard.document, when a changelog was given.",
93 +
              "ref": "at.happyproto.registry.defs#ref",
94 +
              "type": "ref"
59 95
            },
60 -
            "uri": {
61 -
              "description": "The record written. Absent when validateOnly was set.",
62 -
              "format": "at-uri",
63 -
              "type": "string"
96 +
            "channel": {
97 +
              "description": "The software.release.channel. Absent when validateOnly was set.",
98 +
              "ref": "at.happyproto.registry.defs#ref",
99 +
              "type": "ref"
100 +
            },
101 +
            "manifest": {
102 +
              "description": "The software.release.manifest. Absent when validateOnly was set.",
103 +
              "ref": "at.happyproto.registry.defs#ref",
104 +
              "type": "ref"
105 +
            },
106 +
            "resumed": {
107 +
              "description": "True when the version already existed with this artifact, so this call only finished what an earlier one started.",
108 +
              "type": "boolean"
64 109
            },
65 110
            "valid": {
66 -
              "description": "Always true; an invalid record is an error, not a result.",
111 +
              "description": "Always true; invalid input is an error, not a result.",
67 112
              "type": "boolean"
113 +
            },
114 +
            "version": {
115 +
              "description": "The software.release.version. Absent when validateOnly was set.",
116 +
              "ref": "at.happyproto.registry.defs#ref",
117 +
              "type": "ref"
68 118
            }
69 119
          },
70 120
          "required": [
71 121
            "valid"
72 122
          ],
73 123
          "type": "object"
74 124
        }
75 125
      },
76 126
      "type": "procedure"
77 127
    }
78 128
  },
79 129
  "id": "at.happyproto.registry.publishRelease",
80 130
  "lexicon": 1
81 131
}

Compare Other Versions

Lexicon Garden

@