Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
Remove need to pass public key in cob store
Alexis Sellier committed 3 years ago
commit 8c22012d61597e39e05342bf36b450bae4b7d341
parent 44f3984159e630b3b6be1cc159c7a00b099086a6
22 files changed +69 -93
modified radicle-cli/src/commands/assign.rs
@@ -80,7 +80,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
    let storage = &profile.storage;
    let (_, id) = radicle::rad::cwd()?;
    let repo = storage.repository_mut(id)?;
-
    let mut issues = issue::Issues::open(*signer.public_key(), &repo)?;
+
    let mut issues = issue::Issues::open(&repo)?;

    let mut issue = issues.get_mut(&options.id).map_err(|err| match err {
        cob::store::Error::NotFound(_, _) => anyhow!("issue not found '{}'", options.id),
modified radicle-cli/src/commands/comment.rs
@@ -102,7 +102,7 @@ fn comment(
        return Ok(());
    }

-
    let mut issues = Issues::open(*signer.public_key(), repo)?;
+
    let mut issues = Issues::open(repo)?;
    match issues.get_mut(&options.id) {
        Ok(mut issue) => {
            let comment_id = options.reply_to.unwrap_or_else(|| {
@@ -118,7 +118,7 @@ fn comment(
        Err(e) => return Err(e.into()),
    }

-
    let mut patches = Patches::open(*signer.public_key(), repo)?;
+
    let mut patches = Patches::open(repo)?;
    match patches.get_mut(&options.id) {
        Ok(mut patch) => {
            let (revision_id, _) = patch.revisions().last().expect("patch has a revision");
modified radicle-cli/src/commands/id.rs
@@ -238,7 +238,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
    let storage = &profile.storage;
    let (_, id) = radicle::rad::cwd()?;
    let repo = storage.repository(id)?;
-
    let mut proposals = Proposals::open(*signer.public_key(), &repo)?;
+
    let mut proposals = Proposals::open(&repo)?;
    let previous = Identity::load(signer.public_key(), &repo)?;

    let interactive = &options.interactive;
modified radicle-cli/src/commands/issue.rs
@@ -197,7 +197,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
    let storage = &profile.storage;
    let (_, id) = radicle::rad::cwd()?;
    let repo = storage.repository_mut(id)?;
-
    let mut issues = Issues::open(*signer.public_key(), &repo)?;
+
    let mut issues = Issues::open(&repo)?;

    match options.op {
        Operation::Open {
modified radicle-cli/src/commands/merge.rs
@@ -140,7 +140,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
        .identity_doc_of(profile.id())
        .context(format!("couldn't load project {id} from local state"))?;
    let repository = profile.storage.repository(id)?;
-
    let mut patches = Patches::open(*profile.id(), &repository)?;
+
    let mut patches = Patches::open(&repository)?;

    if repo.head_detached()? {
        anyhow::bail!("HEAD is in a detached state; can't merge");
modified radicle-cli/src/commands/patch.rs
@@ -215,7 +215,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
            list::run(&repository, &profile, Some(workdir))?;
        }
        Operation::Show { ref patch_id } => {
-
            show::run(&repository, &profile, &workdir, patch_id)?;
+
            show::run(&repository, &workdir, patch_id)?;
        }
        Operation::Update {
            patch_id,
@@ -231,7 +231,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
            )?;
        }
        Operation::Checkout { ref patch_id } => {
-
            checkout::run(&repository, &profile, &workdir, patch_id)?;
+
            checkout::run(&repository, &workdir, patch_id)?;
        }
    }
    Ok(())
modified radicle-cli/src/commands/patch/checkout.rs
@@ -2,16 +2,14 @@ use crate::terminal as term;
use anyhow::anyhow;
use radicle::cob::patch::{self, PatchId};
use radicle::git::{self, RefString};
-
use radicle::profile::Profile;
use radicle::storage::git::Repository;

pub fn run(
    storage: &Repository,
-
    profile: &Profile,
    git_workdir: &git::raw::Repository,
    patch_id: &PatchId,
) -> anyhow::Result<()> {
-
    let patches = patch::Patches::open(profile.public_key, storage)?;
+
    let patches = patch::Patches::open(storage)?;
    let patch = patches
        .get(patch_id)?
        .ok_or_else(|| anyhow!("Patch `{patch_id}` not found"))?;
modified radicle-cli/src/commands/patch/common.rs
@@ -232,9 +232,10 @@ pub fn find_unmerged_with_base(
    merge_base: Oid,
    patches: &Patches,
    workdir: &git::raw::Repository,
+
    whoami: &Did,
) -> anyhow::Result<Vec<(PatchId, Patch, Clock)>> {
    // My patches.
-
    let proposed: Vec<_> = patches.proposed_by(&patches.public_key().into())?.collect();
+
    let proposed: Vec<_> = patches.proposed_by(whoami)?.collect();
    let mut matches = Vec::new();

    for (id, patch, clock) in proposed {
modified radicle-cli/src/commands/patch/create.rs
@@ -94,7 +94,7 @@ pub fn run(
    message: term::patch::Message,
    options: Options,
) -> anyhow::Result<()> {
-
    let mut patches = patch::Patches::open(profile.public_key, storage)?;
+
    let mut patches = patch::Patches::open(storage)?;
    let project = storage.project_of(&profile.public_key).context(format!(
        "couldn't load project {} from local state",
        storage.id
@@ -117,7 +117,7 @@ pub fn run(
    show_patch_commit_info(
        &project,
        workdir,
-
        patches.public_key(),
+
        profile.id(),
        &head_branch,
        &target_peer,
        target_oid,
modified radicle-cli/src/commands/patch/list.rs
@@ -18,7 +18,7 @@ pub fn run(
    workdir: Option<git::raw::Repository>,
) -> anyhow::Result<()> {
    let me = *profile.id();
-
    let patches = Patches::open(*profile.id(), repository)?;
+
    let patches = Patches::open(repository)?;
    let proposed = patches.proposed()?;

    // Patches the user authored.
@@ -56,7 +56,7 @@ pub fn run(
        for (id, patch) in &mut other {
            term::blank();

-
            print(patches.public_key(), id, patch, &workdir, repository)?;
+
            print(profile.id(), id, patch, &workdir, repository)?;
        }
    }
    term::blank();
modified radicle-cli/src/commands/patch/show.rs
@@ -1,12 +1,12 @@
use super::common::*;
use super::*;

-
use crate::terminal as term;
use radicle::cob::patch;
use radicle::git;
-
use radicle::prelude::*;
use radicle::storage::git::Repository;

+
use crate::terminal as term;
+

fn show_patch_diff(
    patch: &patch::Patch,
    storage: &Repository,
@@ -23,11 +23,10 @@ fn show_patch_diff(

pub fn run(
    storage: &Repository,
-
    profile: &Profile,
    workdir: &git::raw::Repository,
    patch_id: &PatchId,
) -> anyhow::Result<()> {
-
    let patches = patch::Patches::open(profile.public_key, storage)?;
+
    let patches = patch::Patches::open(storage)?;
    let Some(patch) = patches.get(patch_id)? else {
        anyhow::bail!("Patch `{patch_id}` not found");
    };
modified radicle-cli/src/commands/patch/update.rs
@@ -21,12 +21,14 @@ fn select_patch(
    workdir: &git::raw::Repository,
    head_branch: &git::raw::Branch,
    target_oid: git::Oid,
+
    whoami: &Did,
) -> anyhow::Result<patch::PatchId> {
    let head_oid = branch_oid(head_branch)?;
    let base_oid = workdir.merge_base(*target_oid, *head_oid)?;

    let mut spinner = term::spinner("Finding patches to update...");
-
    let mut result = find_unmerged_with_base(*head_oid, *target_oid, base_oid, patches, workdir)?;
+
    let mut result =
+
        find_unmerged_with_base(*head_oid, *target_oid, base_oid, patches, workdir, whoami)?;

    let Some((id, patch, _)) = result.pop() else {
        spinner.failed();
@@ -103,11 +105,11 @@ pub fn run(
    push_to_storage(storage, &head_branch, options)?;

    let (_, target_oid) = get_merge_target(&project, storage, &head_branch)?;
-
    let mut patches = patch::Patches::open(profile.public_key, storage)?;
+
    let mut patches = patch::Patches::open(storage)?;

    let patch_id = match patch_id {
        Some(patch_id) => patch_id,
-
        None => select_patch(&patches, workdir, &head_branch, target_oid)?,
+
        None => select_patch(&patches, workdir, &head_branch, target_oid, &profile.did())?,
    };
    let Ok(mut patch) = patches.get_mut(&patch_id) else {
        anyhow::bail!("Patch `{patch_id}` not found");
modified radicle-cli/src/commands/review.rs
@@ -139,7 +139,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
    let _project = repository
        .identity_doc_of(profile.id())
        .context(format!("couldn't load project {id} from local state"))?;
-
    let mut patches = Patches::open(*profile.id(), &repository)?;
+
    let mut patches = Patches::open(&repository)?;

    let patch_id = options.id;
    let mut patch = patches
modified radicle-cli/src/commands/unassign.rs
@@ -80,7 +80,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
    let storage = &profile.storage;
    let (_, id) = radicle::rad::cwd()?;
    let repo = storage.repository_mut(id)?;
-
    let mut issues = issue::Issues::open(*signer.public_key(), &repo)?;
+
    let mut issues = issue::Issues::open(&repo)?;

    let mut issue = issues.get_mut(&options.id).map_err(|err| match err {
        cob::store::Error::NotFound(_, _) => anyhow!("issue '{}' not found", options.id),
modified radicle-httpd/src/api.rs
@@ -51,8 +51,8 @@ impl Context {
        let doc = repo.identity_doc()?.1.verified()?;
        let payload = doc.project()?;
        let delegates = doc.delegates;
-
        let issues = Issues::open(self.profile.public_key, &repo)?.counts()?;
-
        let patches = Patches::open(self.profile.public_key, &repo)?.counts()?;
+
        let issues = Issues::open(&repo)?.counts()?;
+
        let patches = Patches::open(&repo)?.counts()?;

        Ok(project::Info {
            payload,
modified radicle-httpd/src/api/v1/delegates.rs
@@ -49,9 +49,9 @@ async fn delegates_projects_handler(
                return None;
            }

-
            let Ok(issues) = Issues::open(ctx.profile.public_key, &repo) else { return None };
+
            let Ok(issues) = Issues::open(&repo) else { return None };
            let Ok(issues) = issues.counts() else { return None };
-
            let Ok(patches) = Patches::open(ctx.profile.public_key, &repo) else { return None };
+
            let Ok(patches) = Patches::open(&repo) else { return None };
            let Ok(patches) = patches.counts() else { return None };

            Some(Info {
modified radicle-httpd/src/api/v1/projects.rs
@@ -83,9 +83,9 @@ async fn project_root_handler(
            let Ok((_, doc)) = repo.identity_doc() else { return None };
            let Ok(doc) = doc.verified() else { return None };
            let Ok(payload) = doc.project() else { return None };
-
            let Ok(issues) = issue::Issues::open(ctx.profile.public_key, &repo) else { return None };
+
            let Ok(issues) = issue::Issues::open(&repo) else { return None };
            let Ok(issues) = issues.counts() else { return None };
-
            let Ok(patches) = patch::Patches::open(ctx.profile.public_key, &repo) else { return None };
+
            let Ok(patches) = patch::Patches::open(&repo) else { return None };
            let Ok(patches) = patches.counts() else { return None };
            let delegates = doc.delegates;

@@ -395,7 +395,7 @@ async fn issues_handler(
    let per_page = per_page.unwrap_or(10);
    let storage = &ctx.profile.storage;
    let repo = storage.repository(project)?;
-
    let issues = issue::Issues::open(ctx.profile.public_key, &repo)?;
+
    let issues = issue::Issues::open(&repo)?;
    let mut issues: Vec<_> = issues.all()?.filter_map(|r| r.ok()).collect::<Vec<_>>();
    issues.sort_by(|(_, a, _), (_, b, _)| b.timestamp().cmp(&a.timestamp()));
    let issues = issues
@@ -432,7 +432,7 @@ async fn issue_create_handler(
        .signer()
        .map_err(|_| Error::Auth("Unauthorized"))?;
    let repo = storage.repository(project)?;
-
    let mut issues = issue::Issues::open(ctx.profile.public_key, &repo)?;
+
    let mut issues = issue::Issues::open(&repo)?;
    let issue = issues
        .create(
            issue.title,
@@ -466,7 +466,7 @@ async fn issue_update_handler(
    let storage = &ctx.profile.storage;
    let signer = ctx.profile.signer().unwrap();
    let repo = storage.repository(project)?;
-
    let mut issues = issue::Issues::open(ctx.profile.public_key, &repo)?;
+
    let mut issues = issue::Issues::open(&repo)?;
    let mut issue = issues.get_mut(&issue_id.into())?;

    match action {
@@ -514,7 +514,7 @@ async fn issue_handler(
) -> impl IntoResponse {
    let storage = &ctx.profile.storage;
    let repo = storage.repository(project)?;
-
    let issue = issue::Issues::open(ctx.profile.public_key, &repo)?
+
    let issue = issue::Issues::open(&repo)?
        .get(&issue_id.into())?
        .ok_or(Error::NotFound)?;

@@ -549,7 +549,7 @@ async fn patch_create_handler(
        .signer()
        .map_err(|_| Error::Auth("Unauthorized"))?;
    let repo = storage.repository(project)?;
-
    let mut patches = patch::Patches::open(ctx.profile.public_key, &repo)?;
+
    let mut patches = patch::Patches::open(&repo)?;
    let base_oid = repo.raw().merge_base(*patch.target, *patch.oid)?;

    let patch = patches
@@ -582,7 +582,7 @@ async fn patches_handler(
    let per_page = per_page.unwrap_or(10);
    let storage = &ctx.profile.storage;
    let repo = storage.repository(project)?;
-
    let patches = patch::Patches::open(ctx.profile.public_key, &repo)?;
+
    let patches = patch::Patches::open(&repo)?;
    let mut patches = patches.all()?.filter_map(|r| r.ok()).collect::<Vec<_>>();
    patches.sort_by(|(_, a, _), (_, b, _)| b.timestamp().cmp(&a.timestamp()));
    let patches = patches
@@ -603,7 +603,7 @@ async fn patch_handler(
) -> impl IntoResponse {
    let storage = &ctx.profile.storage;
    let repo = storage.repository(project)?;
-
    let patch = patch::Patches::open(ctx.profile.public_key, &repo)?
+
    let patch = patch::Patches::open(&repo)?
        .get(&patch_id.into())?
        .ok_or(Error::NotFound)?;

modified radicle-httpd/src/test.rs
@@ -17,7 +17,6 @@ use radicle::git::raw as git2;
use radicle::storage::ReadStorage;
use radicle_cli::commands::rad_init;
use radicle_crypto::ssh::keystore::MemorySigner;
-
use radicle_crypto::Signer;

use crate::api::{auth, Context};

@@ -110,7 +109,7 @@ pub fn seed(dir: &Path) -> Context {
    let storage = &profile.storage;
    let (_, id) = radicle::rad::repo(&workdir).unwrap();
    let repo = storage.repository(id).unwrap();
-
    let mut issues = Issues::open(*signer.public_key(), &repo).unwrap();
+
    let mut issues = Issues::open(&repo).unwrap();
    issues
        .create(
            "Issue #1".to_string(),
@@ -122,7 +121,7 @@ pub fn seed(dir: &Path) -> Context {
        .unwrap();

    // eq. rad patch open
-
    let mut patches = Patches::open(*signer.public_key(), &repo).unwrap();
+
    let mut patches = Patches::open(&repo).unwrap();
    let oid = radicle::git::Oid::from_str(HEAD).unwrap();
    let base = radicle::git::Oid::from_str(HEAD_1).unwrap();
    patches
modified radicle/src/cob/identity.rs
@@ -672,11 +672,8 @@ impl<'a> Deref for Proposals<'a> {

impl<'a> Proposals<'a> {
    /// Open a proposals store.
-
    pub fn open(
-
        whoami: PublicKey,
-
        repository: &'a storage::Repository,
-
    ) -> Result<Self, store::Error> {
-
        let raw = store::Store::open(whoami, repository)?;
+
    pub fn open(repository: &'a storage::Repository) -> Result<Self, store::Error> {
+
        let raw = store::Store::open(repository)?;

        Ok(Self { raw })
    }
modified radicle/src/cob/issue.rs
@@ -15,7 +15,7 @@ use crate::cob::store::Transaction;
use crate::cob::thread;
use crate::cob::thread::{CommentId, Thread};
use crate::cob::{store, ActorId, ObjectId, OpId, TypeName};
-
use crate::crypto::{PublicKey, Signer};
+
use crate::crypto::Signer;
use crate::prelude::Did;
use crate::storage::git as storage;

@@ -416,11 +416,8 @@ pub struct IssueCounts {

impl<'a> Issues<'a> {
    /// Open an issues store.
-
    pub fn open(
-
        whoami: PublicKey,
-
        repository: &'a storage::Repository,
-
    ) -> Result<Self, store::Error> {
-
        let raw = store::Store::open(whoami, repository)?;
+
    pub fn open(repository: &'a storage::Repository) -> Result<Self, store::Error> {
+
        let raw = store::Store::open(repository)?;

        Ok(Self { raw })
    }
@@ -549,7 +546,7 @@ mod test {
    fn test_issue_create_and_assign() {
        let tmp = tempfile::tempdir().unwrap();
        let (_, signer, project) = test::setup::context(&tmp);
-
        let mut issues = Issues::open(*signer.public_key(), &project).unwrap();
+
        let mut issues = Issues::open(&project).unwrap();

        let assignee: ActorId = arbitrary::gen(1);
        let assignee_two: ActorId = arbitrary::gen(1);
@@ -586,7 +583,7 @@ mod test {
    fn test_issue_create_and_reassign() {
        let tmp = tempfile::tempdir().unwrap();
        let (_, signer, project) = test::setup::context(&tmp);
-
        let mut issues = Issues::open(*signer.public_key(), &project).unwrap();
+
        let mut issues = Issues::open(&project).unwrap();

        let assignee: ActorId = arbitrary::gen(1);
        let assignee_two: ActorId = arbitrary::gen(1);
@@ -616,7 +613,7 @@ mod test {
    fn test_issue_create_and_get() {
        let tmp = tempfile::tempdir().unwrap();
        let (_, signer, project) = test::setup::context(&tmp);
-
        let mut issues = Issues::open(*signer.public_key(), &project).unwrap();
+
        let mut issues = Issues::open(&project).unwrap();
        let created = issues
            .create("My first issue", "Blah blah blah.", &[], &[], &signer)
            .unwrap();
@@ -628,7 +625,7 @@ mod test {

        assert_eq!(created, issue);
        assert_eq!(issue.title(), "My first issue");
-
        assert_eq!(issue.author(), issues.author());
+
        assert_eq!(issue.author().id, Did::from(signer.public_key()));
        assert_eq!(issue.description(), Some("Blah blah blah."));
        assert_eq!(issue.comments().count(), 1);
        assert_eq!(issue.state(), &State::Open);
@@ -638,7 +635,7 @@ mod test {
    fn test_issue_create_and_change_state() {
        let tmp = tempfile::tempdir().unwrap();
        let (_, signer, project) = test::setup::context(&tmp);
-
        let mut issues = Issues::open(*signer.public_key(), &project).unwrap();
+
        let mut issues = Issues::open(&project).unwrap();
        let mut issue = issues
            .create("My first issue", "Blah blah blah.", &[], &[], &signer)
            .unwrap();
@@ -672,7 +669,7 @@ mod test {
    fn test_issue_create_and_unassign() {
        let tmp = tempfile::tempdir().unwrap();
        let (_, signer, project) = test::setup::context(&tmp);
-
        let mut issues = Issues::open(*signer.public_key(), &project).unwrap();
+
        let mut issues = Issues::open(&project).unwrap();

        let assignee: ActorId = arbitrary::gen(1);
        let assignee_two: ActorId = arbitrary::gen(1);
@@ -700,7 +697,7 @@ mod test {
    fn test_issue_edit_title() {
        let tmp = tempfile::tempdir().unwrap();
        let (_, signer, project) = test::setup::context(&tmp);
-
        let mut issues = Issues::open(*signer.public_key(), &project).unwrap();
+
        let mut issues = Issues::open(&project).unwrap();
        let mut issue = issues
            .create("My first issue", "Blah blah blah.", &[], &[], &signer)
            .unwrap();
@@ -718,7 +715,7 @@ mod test {
    fn test_issue_react() {
        let tmp = tempfile::tempdir().unwrap();
        let (_, signer, project) = test::setup::context(&tmp);
-
        let mut issues = Issues::open(*signer.public_key(), &project).unwrap();
+
        let mut issues = Issues::open(&project).unwrap();
        let mut issue = issues
            .create("My first issue", "Blah blah blah.", &[], &[], &signer)
            .unwrap();
@@ -741,7 +738,7 @@ mod test {
    fn test_issue_reply() {
        let tmp = tempfile::tempdir().unwrap();
        let (_, signer, project) = test::setup::context(&tmp);
-
        let mut issues = Issues::open(*signer.public_key(), &project).unwrap();
+
        let mut issues = Issues::open(&project).unwrap();
        let mut issue = issues
            .create("My first issue", "Blah blah blah.", &[], &[], &signer)
            .unwrap();
@@ -779,7 +776,7 @@ mod test {
    fn test_issue_tag() {
        let tmp = tempfile::tempdir().unwrap();
        let (_, signer, project) = test::setup::context(&tmp);
-
        let mut issues = Issues::open(*signer.public_key(), &project).unwrap();
+
        let mut issues = Issues::open(&project).unwrap();
        let bug_tag = Tag::new("bug").unwrap();
        let ux_tag = Tag::new("ux").unwrap();
        let wontfix_tag = Tag::new("wontfix").unwrap();
@@ -810,7 +807,7 @@ mod test {
        let tmp = tempfile::tempdir().unwrap();
        let (_, signer, project) = test::setup::context(&tmp);
        let author = *signer.public_key();
-
        let mut issues = Issues::open(*signer.public_key(), &project).unwrap();
+
        let mut issues = Issues::open(&project).unwrap();
        let mut issue = issues
            .create("My first issue", "Blah blah blah.", &[], &[], &signer)
            .unwrap();
@@ -856,7 +853,7 @@ mod test {
    fn test_issue_all() {
        let tmp = tempfile::tempdir().unwrap();
        let (_, signer, project) = test::setup::context(&tmp);
-
        let mut issues = Issues::open(*signer.public_key(), &project).unwrap();
+
        let mut issues = Issues::open(&project).unwrap();

        issues.create("First", "Blah", &[], &[], &signer).unwrap();
        issues.create("Second", "Blah", &[], &[], &signer).unwrap();
@@ -880,7 +877,7 @@ mod test {
    fn test_issue_multilines() {
        let tmp = tempfile::tempdir().unwrap();
        let (_, signer, project) = test::setup::context(&tmp);
-
        let mut issues = Issues::open(*signer.public_key(), &project).unwrap();
+
        let mut issues = Issues::open(&project).unwrap();
        let created = issues
            .create(
                "My first issue",
@@ -898,7 +895,7 @@ mod test {

        assert_eq!(created, issue);
        assert_eq!(issue.title(), "My first issue");
-
        assert_eq!(issue.author(), issues.author());
+
        assert_eq!(issue.author().id, Did::from(signer.public_key()));
        assert_eq!(issue.description(), Some("Blah blah blah.\nYah yah yah"));
        assert_eq!(issue.comments().count(), 1);
        assert_eq!(issue.state(), &State::Open);
modified radicle/src/cob/patch.rs
@@ -797,11 +797,8 @@ impl<'a> Deref for Patches<'a> {

impl<'a> Patches<'a> {
    /// Open an patches store.
-
    pub fn open(
-
        whoami: PublicKey,
-
        repository: &'a storage::Repository,
-
    ) -> Result<Self, store::Error> {
-
        let raw = store::Store::open(whoami, repository)?;
+
    pub fn open(repository: &'a storage::Repository) -> Result<Self, store::Error> {
+
        let raw = store::Store::open(repository)?;

        Ok(Self { raw })
    }
@@ -1071,7 +1068,7 @@ mod test {
    fn test_patch_create_and_get() {
        let tmp = tempfile::tempdir().unwrap();
        let (_, signer, project) = test::setup::context(&tmp);
-
        let mut patches = Patches::open(*signer.public_key(), &project).unwrap();
+
        let mut patches = Patches::open(&project).unwrap();
        let author: Did = signer.public_key().into();
        let target = MergeTarget::Delegates;
        let oid = git::Oid::from_str("e2a85016a458cd809c0ecee81f8c99613b0b0945").unwrap();
@@ -1113,7 +1110,7 @@ mod test {
    fn test_patch_discussion() {
        let tmp = tempfile::tempdir().unwrap();
        let (_, signer, project) = test::setup::context(&tmp);
-
        let mut patches = Patches::open(*signer.public_key(), &project).unwrap();
+
        let mut patches = Patches::open(&project).unwrap();
        let patch = patches
            .create(
                "My first patch",
@@ -1147,7 +1144,7 @@ mod test {
        let (_, signer, project) = test::setup::context(&tmp);
        let oid = git::Oid::from_str("e2a85016a458cd809c0ecee81f8c99613b0b0945").unwrap();
        let base = git::Oid::from_str("cb18e95ada2bb38aadd8e6cef0963ce37a87add3").unwrap();
-
        let mut patches = Patches::open(*signer.public_key(), &project).unwrap();
+
        let mut patches = Patches::open(&project).unwrap();
        let mut patch = patches
            .create(
                "My first patch",
@@ -1181,7 +1178,7 @@ mod test {
        let (_, signer, project) = test::setup::context(&tmp);
        let base = git::Oid::from_str("cb18e95ada2bb38aadd8e6cef0963ce37a87add3").unwrap();
        let oid = git::Oid::from_str("518d5069f94c03427f694bb494ac1cd7d1339380").unwrap();
-
        let mut patches = Patches::open(*signer.public_key(), &project).unwrap();
+
        let mut patches = Patches::open(&project).unwrap();
        let mut patch = patches
            .create(
                "My first patch",
@@ -1300,7 +1297,7 @@ mod test {
        let (_, signer, project) = test::setup::context(&tmp);
        let base = git::Oid::from_str("cb18e95ada2bb38aadd8e6cef0963ce37a87add3").unwrap();
        let oid = git::Oid::from_str("518d5069f94c03427f694bb494ac1cd7d1339380").unwrap();
-
        let mut patches = Patches::open(*signer.public_key(), &project).unwrap();
+
        let mut patches = Patches::open(&project).unwrap();
        let mut patch = patches
            .create(
                "My first patch",
@@ -1354,7 +1351,7 @@ mod test {
        let base = git::Oid::from_str("af08e95ada2bb38aadd8e6cef0963ce37a87add3").unwrap();
        let rev0_oid = git::Oid::from_str("518d5069f94c03427f694bb494ac1cd7d1339380").unwrap();
        let rev1_oid = git::Oid::from_str("cb18e95ada2bb38aadd8e6cef0963ce37a87add3").unwrap();
-
        let mut patches = Patches::open(*signer.public_key(), &project).unwrap();
+
        let mut patches = Patches::open(&project).unwrap();
        let mut patch = patches
            .create(
                "My first patch",
modified radicle/src/cob/store.rs
@@ -10,11 +10,9 @@ use rand::rngs::StdRng;
use rand::{RngCore as _, SeedableRng};
use serde::{Deserialize, Serialize};

-
use crate::cob::common::Author;
use crate::cob::op::{Nonce, Op, OpId, Ops};
use crate::cob::CollaborativeObject;
use crate::cob::{ActorId, Create, History, ObjectId, TypeName, Update};
-
use crate::crypto::PublicKey;
use crate::git;
use crate::prelude::*;
use crate::storage::git as storage;
@@ -90,7 +88,6 @@ pub enum Error {

/// Storage for collaborative objects of a specific type `T` in a single repository.
pub struct Store<'a, T> {
-
    whoami: PublicKey,
    parent: git::Oid,
    repo: &'a storage::Repository,
    witness: PhantomData<T>,
@@ -105,29 +102,18 @@ impl<'a, T> AsRef<storage::Repository> for Store<'a, T> {

impl<'a, T> Store<'a, T> {
    /// Open a new generic store.
-
    pub fn open(whoami: PublicKey, repo: &'a storage::Repository) -> Result<Self, Error> {
+
    pub fn open(repo: &'a storage::Repository) -> Result<Self, Error> {
        let rng = rng::std();
        let identity = repo.identity()?;

        Ok(Self {
            parent: identity.current,
-
            whoami,
            repo,
            witness: PhantomData,
            rng,
        })
    }

-
    /// Get this store's author.
-
    pub fn author(&self) -> Author {
-
        Author::new(self.whoami)
-
    }
-

-
    /// Get the public key associated with this store.
-
    pub fn public_key(&self) -> &PublicKey {
-
        &self.whoami
-
    }
-

    /// Derive a new RNG from the existing one.
    pub fn rng(&self) -> StdRng {
        StdRng::from_rng(self.rng.clone()).expect("Store::rng: failed to derive RNG")
@@ -230,7 +216,7 @@ where

    /// Remove an object.
    pub fn remove<G: Signer>(&self, id: &ObjectId, signer: &G) -> Result<(), Error> {
-
        cob::remove(self.repo, &self.whoami, T::type_name(), id)?;
+
        cob::remove(self.repo, signer.public_key(), T::type_name(), id)?;
        self.repo.sign_refs(signer).map_err(Error::SignRefs)?;

        Ok(())