Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Account migration schemas #2170

Merged
merged 16 commits into from
Feb 21, 2024
5 changes: 5 additions & 0 deletions .changeset/slimy-games-breathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@atproto/api': minor
---

Add lexicons and methods for account migration
29 changes: 29 additions & 0 deletions lexicons/com/atproto/identity/getRecommendedDidCredentials.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"lexicon": 1,
"id": "com.atproto.identity.getRecommendedDidCredentials",
"defs": {
"main": {
"type": "query",
"description": "Describe the credentials that should be included in the DID doc of an account that is migrating to this service.",
"output": {
"encoding": "application/json",
"schema": {
"type": "object",
"properties": {
"rotationKeys": {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is a tiny bit weird having rotationKeys here. it matches the PLC operation syntax/fields, but the other fields here match DID document fields but this one doesn't. I guess it's fine? plcRotationKeys is tempting but probably not worth breaking consistency.

a description on this field (in the Lexicon schema) would be good.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I agree :/ But I think it makes most sense to return them here & keep it consistent with the other routes.

One thing we can do that may make it go down a bit easier is not return rotationKeys when this route is requested by a did:web. If we add some additional method that requires another field, we can add another property to the response this would be undefined for plc & web dids

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice! that is a good way to handle it.

"description": "Recommended rotation keys for PLC dids. Should be undefined (or ignored) for did:webs.",
"type": "array",
"items": { "type": "string" }
},
"alsoKnownAs": {
"type": "array",
"items": { "type": "string" }
},
"verificationMethods": { "type": "unknown" },
"services": { "type": "unknown" }
}
}
}
}
}
}
10 changes: 10 additions & 0 deletions lexicons/com/atproto/identity/requestPlcOperationSignature.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"lexicon": 1,
"id": "com.atproto.identity.requestPlcOperationSignature",
"defs": {
"main": {
"type": "procedure",
"description": "Request an email with a code to in order to request a signed PLC operation. Requires Auth."
}
}
}
45 changes: 45 additions & 0 deletions lexicons/com/atproto/identity/signPlcOperation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"lexicon": 1,
"id": "com.atproto.identity.signPlcOperation",
"defs": {
"main": {
"type": "procedure",
"description": "Signs a PLC operation to update some value(s) in the requesting DID's document.",
"input": {
"encoding": "application/json",
"schema": {
"type": "object",
"properties": {
"token": {
"description": "A token received through com.atproto.identity.requestPlcOperationSignature",
"type": "string"
},
"rotationKeys": {
"type": "array",
"items": { "type": "string" }
},
"alsoKnownAs": {
"type": "array",
"items": { "type": "string" }
},
"verificationMethods": { "type": "unknown" },
"services": { "type": "unknown" }
}
}
},
"output": {
"encoding": "application/json",
"schema": {
"type": "object",
"required": ["operation"],
"properties": {
"operation": {
"type": "unknown",
"description": "A signed DID PLC operation."
}
}
}
}
}
}
}
20 changes: 20 additions & 0 deletions lexicons/com/atproto/identity/submitPlcOperation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"lexicon": 1,
"id": "com.atproto.identity.submitPlcOperation",
"defs": {
"main": {
"type": "procedure",
"description": "Validates a PLC operation to ensure that it doesn't violate a service's constraints or get the identity into a bad state, then submits it to the PLC registry",
"input": {
"encoding": "application/json",
"schema": {
"type": "object",
"required": ["operation"],
"properties": {
"operation": { "type": "unknown" }
}
}
}
}
}
}
13 changes: 13 additions & 0 deletions lexicons/com/atproto/repo/importRepo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"lexicon": 1,
"id": "com.atproto.repo.importRepo",
"defs": {
"main": {
"type": "procedure",
"description": "Import a repo in the form of a CAR file. Requires Content-Length HTTP header to be set.",
"input": {
"encoding": "application/vnd.ipld.car"
}
}
}
}
44 changes: 44 additions & 0 deletions lexicons/com/atproto/repo/listMissingBlobs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"lexicon": 1,
"id": "com.atproto.repo.listMissingBlobs",
"defs": {
"main": {
"type": "query",
"description": "Returns a list of missing blobs for the requesting account. Intended to be used in the account migration flow.",
"parameters": {
"type": "params",
"properties": {
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 1000,
"default": 500
},
"cursor": { "type": "string" }
}
},
"output": {
"encoding": "application/json",
"schema": {
"type": "object",
"required": ["blobs"],
"properties": {
"cursor": { "type": "string" },
"blobs": {
"type": "array",
"items": { "type": "ref", "ref": "#recordBlob" }
}
}
}
}
},
"recordBlob": {
"type": "object",
"required": ["cid", "recordUri"],
"properties": {
"cid": { "type": "string", "format": "cid" },
"recordUri": { "type": "string", "format": "at-uri" }
}
}
}
}
10 changes: 10 additions & 0 deletions lexicons/com/atproto/server/activateAccount.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"lexicon": 1,
"id": "com.atproto.server.activateAccount",
"defs": {
"main": {
"type": "procedure",
"description": "Activates a currently deactivated account. Used to finalize account migration after the account's repo is imported and identity is setup."
}
}
}
38 changes: 38 additions & 0 deletions lexicons/com/atproto/server/checkAccountStatus.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"lexicon": 1,
"id": "com.atproto.server.checkAccountStatus",
"defs": {
"main": {
"type": "query",
"description": "Returns the status of an account, especially as pertaining to import or recovery. Can be called many times over the course of an account migration. Requires auth and can only be called pertaining to oneself.",
"output": {
"encoding": "application/json",
"schema": {
"type": "object",
"required": [
"activated",
"validDid",
"repoCommit",
"repoRev",
"repoBlocks",
"indexedRecords",
"privateStateValues",
"expectedBlobs",
"importedBlobs"
],
"properties": {
"activated": { "type": "boolean" },
"validDid": { "type": "boolean" },
"repoCommit": { "type": "string", "format": "cid" },
"repoRev": { "type": "string" },
"repoBlocks": { "type": "integer" },
"indexedRecords": { "type": "integer" },
"privateStateValues": { "type": "integer" },
"expectedBlobs": { "type": "integer" },
"importedBlobs": { "type": "integer" }
}
}
}
}
}
}
23 changes: 23 additions & 0 deletions lexicons/com/atproto/server/deactivateAccount.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"lexicon": 1,
"id": "com.atproto.server.deactivateAccount",
"defs": {
"main": {
"type": "procedure",
"description": "Deactivates a currently active account. Stops serving of repo, and future writes to repo until reactivated. Used to finalize account migration with the old host after the account has been activated on the new host.",
"input": {
"encoding": "application/json",
"schema": {
"type": "object",
"properties": {
"deleteAfter": {
"type": "string",
"format": "datetime",
"description": "A recommendation to server as to how long they should hold onto the deactivated account before deleting."
}
}
}
}
}
}
}
6 changes: 5 additions & 1 deletion lexicons/com/atproto/server/describeServer.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"encoding": "application/json",
"schema": {
"type": "object",
"required": ["availableUserDomains"],
"required": ["did", "availableUserDomains"],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh this is a sneaky little breaking change we need to be a little careful with for rollout.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup yup - just need to ensure we update all our PDSs before publishing this new agent library

thought it was important to get in before there are other PDSs out in the wild

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

funny, this bit me too, only just now realized I needed to add it. bsky.app was unhappy with my PDS just now until I did. 😆

"properties": {
"inviteCodeRequired": {
"type": "boolean",
Expand All @@ -28,6 +28,10 @@
"type": "ref",
"description": "URLs of service policy documents.",
"ref": "#links"
},
"did": {
"type": "string",
"format": "did"
}
}
}
Expand Down
33 changes: 33 additions & 0 deletions lexicons/com/atproto/server/getServiceAuth.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"lexicon": 1,
"id": "com.atproto.server.getServiceAuth",
"defs": {
"main": {
"type": "query",
"description": "Get a signed token on behalf of the requesting DID for the requested service.",
"parameters": {
"type": "params",
"required": ["aud"],
"properties": {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about expiration (exp)? should client be allowed to request longer/shorter tokens within some range?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes me a bit uneasy honestly - I don't think we want to offer long versions of these tokens. If you request one, you should really only be using it once

Copy link
Collaborator

@bnewbold bnewbold Feb 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I definitely think the returned token should have some exp; I guess we can just set it to 5-10min in the future or something like that? Single-use in addition is good, I just don't like the idea of a token floating around that could be used (for the first time) the next day or something.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh to clarify - the returned token does have an exp and it's set to 60s 👍

We just don't provide optionality around requesting a longer one

"aud": {
"type": "string",
"format": "did",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we make this format: uri it would work with DIDs and leave the door open to other audience URIs/values... but probably best to keep it DID-only.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like just leaving it DID for now until we see the need for that. I think we can upgrade into format: uri without much trouble

"description": "The DID of the service that the token will be used to authenticate with"
}
}
},
"output": {
"encoding": "application/json",
"schema": {
"type": "object",
"required": ["token"],
"properties": {
"token": {
"type": "string"
}
}
}
}
}
}
}
Loading
Loading