{"action":"created","comment":{"url":"https://api.github.com/repos/keybase/client/pulls/comments/60060189","id":60060189,"diff_hunk":"@@ -0,0 +1,272 @@\n+// Copyright 2015 Keybase, Inc. All rights reserved. Use of\n+// this source code is governed by the included BSD license.\n+\n+package engine\n+\n+import (\n+\t\"errors\"\n+\t\"fmt\"\n+\n+\t\"github.com/keybase/client/go/libkb\"\n+\tkeybase1 \"github.com/keybase/client/go/protocol\"\n+)\n+\n+type PaperProvisionEngine struct {\n+\tlibkb.Contextified\n+\tUsername   string\n+\tDeviceName string\n+\tPaperKey   string\n+\tresult     error\n+\tlks        *libkb.LKSec\n+\tUser       *libkb.User\n+}\n+\n+func NewPaperProvisionEngine(g *libkb.GlobalContext, Username string, DeviceName string, PaperKey string) *PaperProvisionEngine {\n+\treturn &PaperProvisionEngine{\n+\t\tContextified: libkb.NewContextified(g),\n+\t\tUsername:     Username,\n+\t\tDeviceName:   DeviceName,\n+\t\tPaperKey:     PaperKey,\n+\t}\n+}\n+\n+func (e *PaperProvisionEngine) Name() string {\n+\treturn \"PaperProvision\"\n+}\n+\n+func (e *PaperProvisionEngine) Prereqs() Prereqs {\n+\treturn Prereqs{}\n+}\n+\n+func (e *PaperProvisionEngine) RequiredUIs() []libkb.UIKind {\n+\treturn []libkb.UIKind{\n+\t\tlibkb.ProvisionUIKind,\n+\t\tlibkb.LogUIKind,\n+\t\tlibkb.SecretUIKind,\n+\t\tlibkb.LoginUIKind,\n+\t}\n+}\n+\n+func (e *PaperProvisionEngine) Run(ctx *Context) (err error) {\n+\te.G().Log.Debug(\"+ PaperProvisionEngine Run\")\n+\n+\te.G().Log.Debug(\"attempting device provisioning\")\n+\n+\t// clear out any existing session:\n+\te.G().Logout()\n+\n+\t// transaction around config file\n+\ttx, err := e.G().Env.GetConfigWriter().BeginTransaction()\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\n+\t// From this point on, if there's an error, we abort the\n+\t// transaction.\n+\tdefer func() {\n+\t\tif tx != nil {\n+\t\t\ttx.Abort()\n+\t\t}\n+\t}()\n+\n+\t// run the LoginLoadUser sub-engine to load a user\n+\tueng := newLoginLoadUser(e.G(), e.Username)\n+\tif err = RunEngine(ueng, ctx); err != nil {\n+\t\treturn err\n+\t}\n+\n+\t// make sure the user isn't already provisioned (can\n+\t// get here if usernameOrEmail is an email address\n+\t// for an already provisioned on this device user).\n+\tif ueng.User().HasCurrentDeviceInCurrentInstall() {\n+\t\treturn libkb.DeviceAlreadyProvisionedError{}\n+\t}\n+\te.User = ueng.User()\n+\n+\t// Transform the paper key phrase into a key pair\n+\tbkarg := &PaperKeyGenArg{\n+\t\tPassphrase: libkb.PaperKeyPhrase(e.PaperKey),\n+\t\tSkipPush:   true,\n+\t}\n+\tbkeng := NewPaperKeyGen(bkarg, e.G())\n+\tif err := RunEngine(bkeng, ctx); err != nil {\n+\t\treturn err\n+\t}\n+\n+\tkp := &keypair{sigKey: bkeng.SigKey(), encKey: bkeng.EncKey()}\n+\n+\t// Make sure the key matches the logged in user\n+\t// use the KID to find the uid\n+\tuid, err := e.uidByKID(kp.sigKey.GetKID())\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\n+\tif uid.NotEqual(e.User.GetUID()) {\n+\t\te.G().Log.Debug(\"paper key entered was for a different user\")\n+\t\treturn fmt.Errorf(\"paper key valid, but for %s, not %s\", uid, e.User.GetUID())\n+\t}\n+\n+\t// Make new device keys and sign them with this paper key\n+\terr = e.paper(ctx, kp)\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\n+\t// commit the config changes\n+\tif err := tx.Commit(); err != nil {\n+\t\treturn err\n+\t}\n+\n+\t// Zero out the TX so that we don't abort it in the defer()\n+\t// exit.\n+\ttx = nil\n+\n+\te.sendNotification()\n+\treturn nil\n+\n+}\n+\n+// Copied from login_provision.go\n+func (e *PaperProvisionEngine) uidByKID(kid keybase1.KID) (keybase1.UID, error) {\n+\tvar nilUID keybase1.UID\n+\targ := libkb.APIArg{\n+\t\tEndpoint:     \"key/owner\",\n+\t\tNeedSession:  false,\n+\t\tContextified: libkb.NewContextified(e.G()),\n+\t\tArgs:         libkb.HTTPArgs{\"kid\": libkb.S{Val: kid.String()}},\n+\t}\n+\tres, err := e.G().API.Get(arg)\n+\tif err != nil {\n+\t\treturn nilUID, err\n+\t}\n+\tsuid, err := res.Body.AtPath(\"uid\").GetString()\n+\tif err != nil {\n+\t\treturn nilUID, err\n+\t}\n+\treturn keybase1.UIDFromString(suid)\n+}\n+\n+// copied more or less from loginProvision.paper()\n+func (e *PaperProvisionEngine) paper(ctx *Context, kp *keypair) error {\n+\t// After obtaining login session, this will be called before the login state is released.\n+\t// It signs this new device with the paper key.\n+\tvar afterLogin = func(lctx libkb.LoginContext) error {\n+\t\tctx.LoginContext = lctx\n+\n+\t\t// need lksec to store device keys locally\n+\t\tif err := e.fetchLKS(ctx, kp.encKey); err != nil {\n+\t\t\treturn err\n+\t\t}\n+\n+\t\tif err := e.makeDeviceKeysWithSigner(ctx, kp.sigKey); err != nil {\n+\t\t\treturn err\n+\t\t}\n+\t\tif err := lctx.LocalSession().SetDeviceProvisioned(e.G().Env.GetDeviceID()); err != nil {\n+\t\t\t// not a fatal error, session will stay in memory\n+\t\t\te.G().Log.Warning(\"error saving session file: %s\", err)\n+\t\t}\n+\t\treturn nil\n+\t}\n+\n+\t// need a session to continue to provision, login with paper sigKey\n+\treturn e.G().LoginState().LoginWithKey(ctx.LoginContext, e.User, kp.sigKey, afterLogin)\n+}\n+\n+func (e *PaperProvisionEngine) sendNotification() {\n+\te.G().NotifyRouter.HandleLogin(string(e.G().Env.GetUsername()))\n+}\n+\n+func (e *PaperProvisionEngine) SubConsumers() []libkb.UIConsumer {\n+\treturn []libkb.UIConsumer{}\n+}\n+\n+func (e *PaperProvisionEngine) Result() error {\n+\treturn e.result\n+}\n+\n+// copied from loginProvision\n+func (e *PaperProvisionEngine) fetchLKS(ctx *Context, encKey libkb.GenericKey) error {\n+\tgen, clientLKS, err := fetchLKS(ctx, e.G(), encKey)\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\te.lks = libkb.NewLKSecWithClientHalf(clientLKS, gen, e.User.GetUID(), e.G())\n+\treturn nil\n+}\n+\n+// copied from loginProvision\n+// makeDeviceKeysWithSigner creates device keys given a signing\n+// key.\n+func (e *PaperProvisionEngine) makeDeviceKeysWithSigner(ctx *Context, signer libkb.GenericKey) error {\n+\targs, err := e.makeDeviceWrapArgs(ctx)\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\targs.Signer = signer\n+\targs.IsEldest = false // just to be explicit\n+\targs.EldestKID = e.User.GetEldestKID()\n+\n+\treturn e.makeDeviceKeys(ctx, args)\n+}\n+\n+// copied from loginProvision\n+// makeDeviceWrapArgs creates a base set of args for DeviceWrap.\n+// It ensures that LKSec is created.  It also gets a new device\n+// name for this device.\n+func (e *PaperProvisionEngine) makeDeviceWrapArgs(ctx *Context) (*DeviceWrapArgs, error) {\n+\tif err := e.ensureLKSec(ctx); err != nil {\n+\t\treturn nil, err\n+\t}\n+\n+\treturn &DeviceWrapArgs{\n+\t\tMe:         e.User,\n+\t\tDeviceName: e.DeviceName,\n+\t\tDeviceType: \"desktop\",\n+\t\tLks:        e.lks,\n+\t}, nil\n+}\n+\n+// copied from loginProvision\n+// makeDeviceKeys uses DeviceWrap to generate device keys.\n+func (e *PaperProvisionEngine) makeDeviceKeys(ctx *Context, args *DeviceWrapArgs) error {\n+\teng := NewDeviceWrap(args, e.G())\n+\tif err := RunEngine(eng, ctx); err != nil {\n+\t\treturn err\n+\t}\n+\n+\t// TODO: do we need these?","path":"go/engine/paperprovision.go","position":238,"original_position":238,"commit_id":"c12ebe2f27ed7479c8fd1f38086c5f147eba7a81","original_commit_id":"c12ebe2f27ed7479c8fd1f38086c5f147eba7a81","user":{"login":"maxtaco","id":866815,"avatar_url":"https://avatars.githubusercontent.com/u/866815?v=3","gravatar_id":"","url":"https://api.github.com/users/maxtaco","html_url":"https://github.com/maxtaco","followers_url":"https://api.github.com/users/maxtaco/followers","following_url":"https://api.github.com/users/maxtaco/following{/other_user}","gists_url":"https://api.github.com/users/maxtaco/gists{/gist_id}","starred_url":"https://api.github.com/users/maxtaco/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/maxtaco/subscriptions","organizations_url":"https://api.github.com/users/maxtaco/orgs","repos_url":"https://api.github.com/users/maxtaco/repos","events_url":"https://api.github.com/users/maxtaco/events{/privacy}","received_events_url":"https://api.github.com/users/maxtaco/received_events","type":"User","site_admin":false},"body":"cam you clear out this TODO?","created_at":"2016-04-18T13:46:57Z","updated_at":"2016-04-18T13:46:57Z","html_url":"https://github.com/keybase/client/pull/2627#discussion_r60060189","pull_request_url":"https://api.github.com/repos/keybase/client/pulls/2627","_links":{"self":{"href":"https://api.github.com/repos/keybase/client/pulls/comments/60060189"},"html":{"href":"https://github.com/keybase/client/pull/2627#discussion_r60060189"},"pull_request":{"href":"https://api.github.com/repos/keybase/client/pulls/2627"}}},"pull_request":{"url":"https://api.github.com/repos/keybase/client/pulls/2627","id":66701251,"html_url":"https://github.com/keybase/client/pull/2627","diff_url":"https://github.com/keybase/client/pull/2627.diff","patch_url":"https://github.com/keybase/client/pull/2627.patch","issue_url":"https://api.github.com/repos/keybase/client/issues/2627","number":2627,"state":"open","locked":false,"title":"paperprovision command line option","user":{"login":"zanderz","id":862397,"avatar_url":"https://avatars.githubusercontent.com/u/862397?v=3","gravatar_id":"","url":"https://api.github.com/users/zanderz","html_url":"https://github.com/zanderz","followers_url":"https://api.github.com/users/zanderz/followers","following_url":"https://api.github.com/users/zanderz/following{/other_user}","gists_url":"https://api.github.com/users/zanderz/gists{/gist_id}","starred_url":"https://api.github.com/users/zanderz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zanderz/subscriptions","organizations_url":"https://api.github.com/users/zanderz/orgs","repos_url":"https://api.github.com/users/zanderz/repos","events_url":"https://api.github.com/users/zanderz/events{/privacy}","received_events_url":"https://api.github.com/users/zanderz/received_events","type":"User","site_admin":false},"body":"I followed Patrick's advice to add a new RPC, engine, command and protocol, and copy part of the login engine.\r\n@maxtaco @patrickxb ","created_at":"2016-04-15T20:36:52Z","updated_at":"2016-04-18T13:46:57Z","closed_at":null,"merged_at":null,"merge_commit_sha":"19e56faea1d9ddcbd4518213d2c0620d55dd4d74","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/keybase/client/pulls/2627/commits","review_comments_url":"https://api.github.com/repos/keybase/client/pulls/2627/comments","review_comment_url":"https://api.github.com/repos/keybase/client/pulls/comments{/number}","comments_url":"https://api.github.com/repos/keybase/client/issues/2627/comments","statuses_url":"https://api.github.com/repos/keybase/client/statuses/c12ebe2f27ed7479c8fd1f38086c5f147eba7a81","head":{"label":"keybase:zanderz/CORE-2507","ref":"zanderz/CORE-2507","sha":"c12ebe2f27ed7479c8fd1f38086c5f147eba7a81","user":{"login":"keybase","id":5400834,"avatar_url":"https://avatars.githubusercontent.com/u/5400834?v=3","gravatar_id":"","url":"https://api.github.com/users/keybase","html_url":"https://github.com/keybase","followers_url":"https://api.github.com/users/keybase/followers","following_url":"https://api.github.com/users/keybase/following{/other_user}","gists_url":"https://api.github.com/users/keybase/gists{/gist_id}","starred_url":"https://api.github.com/users/keybase/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/keybase/subscriptions","organizations_url":"https://api.github.com/users/keybase/orgs","repos_url":"https://api.github.com/users/keybase/repos","events_url":"https://api.github.com/users/keybase/events{/privacy}","received_events_url":"https://api.github.com/users/keybase/received_events","type":"Organization","site_admin":false},"repo":{"id":29099181,"name":"client","full_name":"keybase/client","owner":{"login":"keybase","id":5400834,"avatar_url":"https://avatars.githubusercontent.com/u/5400834?v=3","gravatar_id":"","url":"https://api.github.com/users/keybase","html_url":"https://github.com/keybase","followers_url":"https://api.github.com/users/keybase/followers","following_url":"https://api.github.com/users/keybase/following{/other_user}","gists_url":"https://api.github.com/users/keybase/gists{/gist_id}","starred_url":"https://api.github.com/users/keybase/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/keybase/subscriptions","organizations_url":"https://api.github.com/users/keybase/orgs","repos_url":"https://api.github.com/users/keybase/repos","events_url":"https://api.github.com/users/keybase/events{/privacy}","received_events_url":"https://api.github.com/users/keybase/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/keybase/client","description":"Keybase Go Library, Client, Service, OS X, iOS, Android, Electron","fork":false,"url":"https://api.github.com/repos/keybase/client","forks_url":"https://api.github.com/repos/keybase/client/forks","keys_url":"https://api.github.com/repos/keybase/client/keys{/key_id}","collaborators_url":"https://api.github.com/repos/keybase/client/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/keybase/client/teams","hooks_url":"https://api.github.com/repos/keybase/client/hooks","issue_events_url":"https://api.github.com/repos/keybase/client/issues/events{/number}","events_url":"https://api.github.com/repos/keybase/client/events","assignees_url":"https://api.github.com/repos/keybase/client/assignees{/user}","branches_url":"https://api.github.com/repos/keybase/client/branches{/branch}","tags_url":"https://api.github.com/repos/keybase/client/tags","blobs_url":"https://api.github.com/repos/keybase/client/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/keybase/client/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/keybase/client/git/refs{/sha}","trees_url":"https://api.github.com/repos/keybase/client/git/trees{/sha}","statuses_url":"https://api.github.com/repos/keybase/client/statuses/{sha}","languages_url":"https://api.github.com/repos/keybase/client/languages","stargazers_url":"https://api.github.com/repos/keybase/client/stargazers","contributors_url":"https://api.github.com/repos/keybase/client/contributors","subscribers_url":"https://api.github.com/repos/keybase/client/subscribers","subscription_url":"https://api.github.com/repos/keybase/client/subscription","commits_url":"https://api.github.com/repos/keybase/client/commits{/sha}","git_commits_url":"https://api.github.com/repos/keybase/client/git/commits{/sha}","comments_url":"https://api.github.com/repos/keybase/client/comments{/number}","issue_comment_url":"https://api.github.com/repos/keybase/client/issues/comments{/number}","contents_url":"https://api.github.com/repos/keybase/client/contents/{+path}","compare_url":"https://api.github.com/repos/keybase/client/compare/{base}...{head}","merges_url":"https://api.github.com/repos/keybase/client/merges","archive_url":"https://api.github.com/repos/keybase/client/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/keybase/client/downloads","issues_url":"https://api.github.com/repos/keybase/client/issues{/number}","pulls_url":"https://api.github.com/repos/keybase/client/pulls{/number}","milestones_url":"https://api.github.com/repos/keybase/client/milestones{/number}","notifications_url":"https://api.github.com/repos/keybase/client/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/keybase/client/labels{/name}","releases_url":"https://api.github.com/repos/keybase/client/releases{/id}","deployments_url":"https://api.github.com/repos/keybase/client/deployments","created_at":"2015-01-11T17:17:12Z","updated_at":"2016-04-18T01:22:57Z","pushed_at":"2016-04-18T06:27:01Z","git_url":"git://github.com/keybase/client.git","ssh_url":"git@github.com:keybase/client.git","clone_url":"https://github.com/keybase/client.git","svn_url":"https://github.com/keybase/client","homepage":"","size":148907,"stargazers_count":449,"watchers_count":449,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":31,"mirror_url":null,"open_issues_count":158,"forks":31,"open_issues":158,"watchers":449,"default_branch":"master"}},"base":{"label":"keybase:master","ref":"master","sha":"8c84b53aa4a11a5949a434529f64eab72981015b","user":{"login":"keybase","id":5400834,"avatar_url":"https://avatars.githubusercontent.com/u/5400834?v=3","gravatar_id":"","url":"https://api.github.com/users/keybase","html_url":"https://github.com/keybase","followers_url":"https://api.github.com/users/keybase/followers","following_url":"https://api.github.com/users/keybase/following{/other_user}","gists_url":"https://api.github.com/users/keybase/gists{/gist_id}","starred_url":"https://api.github.com/users/keybase/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/keybase/subscriptions","organizations_url":"https://api.github.com/users/keybase/orgs","repos_url":"https://api.github.com/users/keybase/repos","events_url":"https://api.github.com/users/keybase/events{/privacy}","received_events_url":"https://api.github.com/users/keybase/received_events","type":"Organization","site_admin":false},"repo":{"id":29099181,"name":"client","full_name":"keybase/client","owner":{"login":"keybase","id":5400834,"avatar_url":"https://avatars.githubusercontent.com/u/5400834?v=3","gravatar_id":"","url":"https://api.github.com/users/keybase","html_url":"https://github.com/keybase","followers_url":"https://api.github.com/users/keybase/followers","following_url":"https://api.github.com/users/keybase/following{/other_user}","gists_url":"https://api.github.com/users/keybase/gists{/gist_id}","starred_url":"https://api.github.com/users/keybase/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/keybase/subscriptions","organizations_url":"https://api.github.com/users/keybase/orgs","repos_url":"https://api.github.com/users/keybase/repos","events_url":"https://api.github.com/users/keybase/events{/privacy}","received_events_url":"https://api.github.com/users/keybase/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/keybase/client","description":"Keybase Go Library, Client, Service, OS X, iOS, Android, Electron","fork":false,"url":"https://api.github.com/repos/keybase/client","forks_url":"https://api.github.com/repos/keybase/client/forks","keys_url":"https://api.github.com/repos/keybase/client/keys{/key_id}","collaborators_url":"https://api.github.com/repos/keybase/client/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/keybase/client/teams","hooks_url":"https://api.github.com/repos/keybase/client/hooks","issue_events_url":"https://api.github.com/repos/keybase/client/issues/events{/number}","events_url":"https://api.github.com/repos/keybase/client/events","assignees_url":"https://api.github.com/repos/keybase/client/assignees{/user}","branches_url":"https://api.github.com/repos/keybase/client/branches{/branch}","tags_url":"https://api.github.com/repos/keybase/client/tags","blobs_url":"https://api.github.com/repos/keybase/client/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/keybase/client/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/keybase/client/git/refs{/sha}","trees_url":"https://api.github.com/repos/keybase/client/git/trees{/sha}","statuses_url":"https://api.github.com/repos/keybase/client/statuses/{sha}","languages_url":"https://api.github.com/repos/keybase/client/languages","stargazers_url":"https://api.github.com/repos/keybase/client/stargazers","contributors_url":"https://api.github.com/repos/keybase/client/contributors","subscribers_url":"https://api.github.com/repos/keybase/client/subscribers","subscription_url":"https://api.github.com/repos/keybase/client/subscription","commits_url":"https://api.github.com/repos/keybase/client/commits{/sha}","git_commits_url":"https://api.github.com/repos/keybase/client/git/commits{/sha}","comments_url":"https://api.github.com/repos/keybase/client/comments{/number}","issue_comment_url":"https://api.github.com/repos/keybase/client/issues/comments{/number}","contents_url":"https://api.github.com/repos/keybase/client/contents/{+path}","compare_url":"https://api.github.com/repos/keybase/client/compare/{base}...{head}","merges_url":"https://api.github.com/repos/keybase/client/merges","archive_url":"https://api.github.com/repos/keybase/client/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/keybase/client/downloads","issues_url":"https://api.github.com/repos/keybase/client/issues{/number}","pulls_url":"https://api.github.com/repos/keybase/client/pulls{/number}","milestones_url":"https://api.github.com/repos/keybase/client/milestones{/number}","notifications_url":"https://api.github.com/repos/keybase/client/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/keybase/client/labels{/name}","releases_url":"https://api.github.com/repos/keybase/client/releases{/id}","deployments_url":"https://api.github.com/repos/keybase/client/deployments","created_at":"2015-01-11T17:17:12Z","updated_at":"2016-04-18T01:22:57Z","pushed_at":"2016-04-18T06:27:01Z","git_url":"git://github.com/keybase/client.git","ssh_url":"git@github.com:keybase/client.git","clone_url":"https://github.com/keybase/client.git","svn_url":"https://github.com/keybase/client","homepage":"","size":148907,"stargazers_count":449,"watchers_count":449,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":31,"mirror_url":null,"open_issues_count":158,"forks":31,"open_issues":158,"watchers":449,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/keybase/client/pulls/2627"},"html":{"href":"https://github.com/keybase/client/pull/2627"},"issue":{"href":"https://api.github.com/repos/keybase/client/issues/2627"},"comments":{"href":"https://api.github.com/repos/keybase/client/issues/2627/comments"},"review_comments":{"href":"https://api.github.com/repos/keybase/client/pulls/2627/comments"},"review_comment":{"href":"https://api.github.com/repos/keybase/client/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/keybase/client/pulls/2627/commits"},"statuses":{"href":"https://api.github.com/repos/keybase/client/statuses/c12ebe2f27ed7479c8fd1f38086c5f147eba7a81"}}}}