clone

one developer profile for links and private tcp services, reached peer to peer over iroh with no open ports

Stop using a real person's handle as the default and in tests

Dami committed 957247b
`dami` was the placeholder in the claim-handle field, so every new user was
shown someone else's handle as the suggested value for their own. It is now
`yourhandle`, which cannot be mistaken for a suggestion.

Tests and fixtures move to alice/bob, joining the mallory that policy.rs and
tests/authz.rs already used for the third party — so the whole suite now reads
in one convention instead of two. Doc comments, CLI help text and the README
walkthrough follow.

docs/milestones.md keeps its names. M4 and M6 record what two real accounts
actually did on a specific day, and editing that would be inventing a history
rather than anonymising one.
commit
957247b790f2e6ef247edbcd4aa40771f15e5bab
parent
d74882ffe18d519d7547d281732f41cda86f2acc
author
Dami <dami.etoile@gmail.com>
14 files changed, +85 -85
MREADME.md6+-
Mcrates/devsite-cli/src/main.rs4+-
Mcrates/devsite-daemon/tests/authz.rs2+-
Mcrates/devsite-proto/src/capability.rs2+-
Mcrates/devsite-proto/src/id.rs2+-
Mcrates/devsite-server/src/api.rs2+-
Mcrates/devsite-server/src/auth.rs4+-
Mcrates/devsite-server/src/db.rs102+++++++++++++++---------------
Mcrates/devsite-server/src/main.rs2+-
Mcrates/devsite-server/src/policy.rs30++++----
Mdocs/profile-template.md2+-
Mfixtures/page-a.html2+-
Mfixtures/page-b.html6+-
Mweb/app.js4+-
M README.md +3 -3
M crates/devsite-cli/src/main.rs +2 -2
M crates/devsite-daemon/tests/authz.rs +1 -1
M crates/devsite-proto/src/capability.rs +1 -1
M crates/devsite-proto/src/id.rs +1 -1
M crates/devsite-server/src/api.rs +1 -1
M crates/devsite-server/src/auth.rs +2 -2
M crates/devsite-server/src/db.rs +51 -51
@@ -482,59 +482,59 @@ mod tests {
482482 483483 fn seeded() -> (Db, Account, Account) {484484 let db = Db::open_in_memory().unwrap();485- let dami = db.upsert_account("ps_dami", 0).unwrap();486- let frank = db.upsert_account("ps_frank", 0).unwrap();487- db.set_handle(dami.id, "dami").unwrap();488- db.set_handle(frank.id, "frank").unwrap();489- (db, dami, frank)485+ let alice = db.upsert_account("ps_alice", 0).unwrap();486+ let bob = db.upsert_account("ps_bob", 0).unwrap();487+ db.set_handle(alice.id, "alice").unwrap();488+ db.set_handle(bob.id, "bob").unwrap();489+ (db, alice, bob)490490 }491491 492492 #[test]493493 fn signing_in_twice_reuses_the_same_account() {494494 let db = Db::open_in_memory().unwrap();495- let first = db.upsert_account("ps_dami", 0).unwrap();496- let second = db.upsert_account("ps_dami", 100).unwrap();495+ let first = db.upsert_account("ps_alice", 0).unwrap();496+ let second = db.upsert_account("ps_alice", 100).unwrap();497497 assert_eq!(first.id, second.id, "a returning user must not get a new account");498498 }499499 500500 #[test]501501 fn shares_are_visible_to_the_named_viewer_only() {502- let (db, dami, frank) = seeded();502+ let (db, alice, bob) = seeded();503503 let agent = db504- .create_resource(dami.id, "Agent", ResourceKind::Service, Visibility::Shared, None, 0)504+ .create_resource(alice.id, "Agent", ResourceKind::Service, Visibility::Shared, None, 0)505505 .unwrap();506506 let hermes = db507- .create_resource(dami.id, "Hermes", ResourceKind::Service, Visibility::Private, None, 0)507+ .create_resource(alice.id, "Hermes", ResourceKind::Service, Visibility::Private, None, 0)508508 .unwrap();509- db.share_with(agent, frank.id).unwrap();509+ db.share_with(agent, bob.id).unwrap();510510 511- let franks = db.resources_shared_with(frank.id).unwrap();512- assert_eq!(franks.len(), 1);513- assert_eq!(franks[0].id, agent);511+ let bobs = db.resources_shared_with(bob.id).unwrap();512+ assert_eq!(bobs.len(), 1);513+ assert_eq!(bobs[0].id, agent);514514 assert!(515- !franks.iter().any(|r| r.id == hermes),515+ !bobs.iter().any(|r| r.id == hermes),516516 "a private resource must never appear in someone else's shared list"517517 );518518 }519519 520520 #[test]521521 fn owners_do_not_see_their_own_resources_as_shared_with_them() {522- let (db, dami, frank) = seeded();522+ let (db, alice, bob) = seeded();523523 let agent = db524- .create_resource(dami.id, "Agent", ResourceKind::Service, Visibility::Shared, None, 0)524+ .create_resource(alice.id, "Agent", ResourceKind::Service, Visibility::Shared, None, 0)525525 .unwrap();526- db.share_with(agent, frank.id).unwrap();527- db.share_with(agent, dami.id).unwrap();526+ db.share_with(agent, bob.id).unwrap();527+ db.share_with(agent, alice.id).unwrap();528528 assert!(529- db.resources_shared_with(dami.id).unwrap().is_empty(),529+ db.resources_shared_with(alice.id).unwrap().is_empty(),530530 "own resources belong in the profile list, not `shared with me`"531531 );532532 }533533 534534 #[test]535535 fn expired_sessions_do_not_resolve() {536- let (db, dami, _) = seeded();537- db.create_session("hash", dami.id, 100).unwrap();536+ let (db, alice, _) = seeded();537+ db.create_session("hash", alice.id, 100).unwrap();538538 assert!(db.session_account("hash", 50).unwrap().is_some());539539 assert!(db.session_account("hash", 100).unwrap().is_none());540540 assert!(db.session_account("hash", 500).unwrap().is_none());
@@ -542,17 +542,17 @@ mod tests {
542542 543543 #[test]544544 fn registering_a_daemon_is_idempotent_and_survives_re_registration() {545- let (db, dami, _) = seeded();546- assert!(db.daemon_endpoint(dami.id).unwrap().is_none());545+ let (db, alice, _) = seeded();546+ assert!(db.daemon_endpoint(alice.id).unwrap().is_none());547547 548- db.register_daemon(dami.id, "abc").unwrap();549- db.register_daemon(dami.id, "abc").unwrap();550- assert_eq!(db.daemon_endpoint(dami.id).unwrap().as_deref(), Some("abc"));548+ db.register_daemon(alice.id, "abc").unwrap();549+ db.register_daemon(alice.id, "abc").unwrap();550+ assert_eq!(db.daemon_endpoint(alice.id).unwrap().as_deref(), Some("abc"));551551 552552 // A new identity file means a new endpoint id, and the account should553553 // follow it rather than keeping an id nothing answers on.554- db.register_daemon(dami.id, "def").unwrap();555- assert_eq!(db.daemon_endpoint(dami.id).unwrap().as_deref(), Some("def"));554+ db.register_daemon(alice.id, "def").unwrap();555+ assert_eq!(db.daemon_endpoint(alice.id).unwrap().as_deref(), Some("def"));556556 }557557 558558 #[test]
@@ -580,7 +580,7 @@ mod tests {
580580 legacy581581 .execute(582582 "INSERT INTO accounts (id, external_sub, handle, created_at)583- VALUES (?1, 'ps_x', 'dami', 0)",583+ VALUES (?1, 'ps_x', 'alice', 0)",584584 params![legacy_account],585585 )586586 .unwrap();
@@ -594,11 +594,11 @@ mod tests {
594594 drop(legacy);595595 596596 let db = Db::open(file.to_str().unwrap()).unwrap();597- let dami = db.account_by_handle("dami").unwrap().unwrap();597+ let alice = db.account_by_handle("alice").unwrap().unwrap();598598 599599 // The identity survives the columns around it being dropped: an existing600600 // daemon keeps working without re-registering.601- assert_eq!(db.daemon_endpoint(dami.id).unwrap().as_deref(), Some("abc"));601+ assert_eq!(db.daemon_endpoint(alice.id).unwrap().as_deref(), Some("abc"));602602 603603 std::fs::remove_file(&file).ok();604604 }
@@ -608,28 +608,28 @@ mod tests {
608608 // `devsite expose --name Hermes` run twice must not leave two Hermes entries on609609 // the profile, and the id must survive so already-issued capabilities still name610610 // the same thing.611- let (db, dami, _) = seeded();611+ let (db, alice, _) = seeded();612612 let first = db613- .create_resource(dami.id, "Hermes", ResourceKind::Service, Visibility::Private, None, 0)613+ .create_resource(alice.id, "Hermes", ResourceKind::Service, Visibility::Private, None, 0)614614 .unwrap();615615 let second = db616- .create_resource(dami.id, "Hermes", ResourceKind::Service, Visibility::Shared, None, 10)616+ .create_resource(alice.id, "Hermes", ResourceKind::Service, Visibility::Shared, None, 10)617617 .unwrap();618618 619619 assert_eq!(first, second, "re-exposing must reuse the resource id");620- let owned = db.resources_owned_by(dami.id).unwrap();620+ let owned = db.resources_owned_by(alice.id).unwrap();621621 assert_eq!(owned.len(), 1, "expected exactly one Hermes, got {owned:?}");622622 assert_eq!(owned[0].visibility, Visibility::Shared, "visibility should update");623623 }624624 625625 #[test]626626 fn different_people_may_use_the_same_service_name() {627- let (db, dami, frank) = seeded();627+ let (db, alice, bob) = seeded();628628 let a = db629- .create_resource(dami.id, "Agent", ResourceKind::Service, Visibility::Private, None, 0)629+ .create_resource(alice.id, "Agent", ResourceKind::Service, Visibility::Private, None, 0)630630 .unwrap();631631 let b = db632- .create_resource(frank.id, "Agent", ResourceKind::Service, Visibility::Private, None, 0)632+ .create_resource(bob.id, "Agent", ResourceKind::Service, Visibility::Private, None, 0)633633 .unwrap();634634 assert_ne!(a, b, "names are scoped to their owner");635635 }
@@ -639,40 +639,40 @@ mod tests {
639639 // Not a hypothetical: the pragma lived in SCHEMA, which migrations skip640640 // for an existing database, so every process after the first ran without641641 // it. A share pointing at a deleted resource would have been left behind.642- let (db, dami, frank) = seeded();642+ let (db, alice, bob) = seeded();643643 let agent = db644- .create_resource(dami.id, "Agent", ResourceKind::Service, Visibility::Shared, None, 0)644+ .create_resource(alice.id, "Agent", ResourceKind::Service, Visibility::Shared, None, 0)645645 .unwrap();646- db.share_with(agent, frank.id).unwrap();646+ db.share_with(agent, bob.id).unwrap();647647 648648 db.conn649649 .execute("DELETE FROM resources WHERE id = ?1", params![agent.to_string()])650650 .unwrap();651651 652652 assert!(653- db.resources_shared_with(frank.id).unwrap().is_empty(),653+ db.resources_shared_with(bob.id).unwrap().is_empty(),654654 "the share should have been cascaded away with its resource"655655 );656656 }657657 658658 #[test]659659 fn a_theme_round_trips_and_can_be_cleared() {660- let (db, dami, _) = seeded();661- assert!(db.custom_css(dami.id).unwrap().is_none());660+ let (db, alice, _) = seeded();661+ assert!(db.custom_css(alice.id).unwrap().is_none());662662 663- db.set_custom_css(dami.id, Some("--pico-primary: #7b3fe4;\n")).unwrap();663+ db.set_custom_css(alice.id, Some("--pico-primary: #7b3fe4;\n")).unwrap();664664 assert_eq!(665- db.custom_css(dami.id).unwrap().as_deref(),665+ db.custom_css(alice.id).unwrap().as_deref(),666666 Some("--pico-primary: #7b3fe4;\n")667667 );668668 669- db.set_custom_css(dami.id, None).unwrap();670- assert!(db.custom_css(dami.id).unwrap().is_none());669+ db.set_custom_css(alice.id, None).unwrap();670+ assert!(db.custom_css(alice.id).unwrap().is_none());671671 }672672 673673 #[test]674674 fn handles_are_matched_case_insensitively() {675- let (db, dami, _) = seeded();676- assert_eq!(db.account_by_handle("DaMi").unwrap().unwrap().id, dami.id);675+ let (db, alice, _) = seeded();676+ assert_eq!(db.account_by_handle("AlIcE").unwrap().unwrap().id, alice.id);677677 }678678 }
M crates/devsite-server/src/main.rs +1 -1
M crates/devsite-server/src/policy.rs +15 -15
@@ -1,7 +1,7 @@
11 //! The one place that decides who may see what.22 //!33 //! Both the profile listing and capability issuance route through [`can_view`]. Keeping it4-//! single means the two can never disagree — a resource hidden from Frank's view of a4+//! single means the two can never disagree — a resource hidden from Bob's view of a55 //! profile is also a resource he cannot obtain a capability for.66 77 use devsite_proto::AccountId;
@@ -58,37 +58,37 @@ pub fn can_view(
5858 mod tests {5959 use super::*;6060 61- const DAMI: AccountId = AccountId::from_bytes([1; 16]);62- const FRANK: AccountId = AccountId::from_bytes([2; 16]);61+ const ALICE: AccountId = AccountId::from_bytes([1; 16]);62+ const BOB: AccountId = AccountId::from_bytes([2; 16]);6363 const MALLORY: AccountId = AccountId::from_bytes([3; 16]);6464 6565 #[test]6666 fn public_resources_are_visible_to_everyone_including_strangers() {67- assert!(can_view(None, DAMI, Visibility::Public, &[]));68- assert!(can_view(Some(FRANK), DAMI, Visibility::Public, &[]));67+ assert!(can_view(None, ALICE, Visibility::Public, &[]));68+ assert!(can_view(Some(BOB), ALICE, Visibility::Public, &[]));6969 }7070 7171 #[test]7272 fn private_resources_are_visible_only_to_their_owner() {73- assert!(can_view(Some(DAMI), DAMI, Visibility::Private, &[]));74- assert!(!can_view(Some(FRANK), DAMI, Visibility::Private, &[]));75- assert!(!can_view(None, DAMI, Visibility::Private, &[]));73+ assert!(can_view(Some(ALICE), ALICE, Visibility::Private, &[]));74+ assert!(!can_view(Some(BOB), ALICE, Visibility::Private, &[]));75+ assert!(!can_view(None, ALICE, Visibility::Private, &[]));7676 }7777 7878 #[test]7979 fn shared_resources_reach_the_named_viewers_and_no_one_else() {80- let shared = [FRANK];81- assert!(can_view(Some(DAMI), DAMI, Visibility::Shared, &shared));82- assert!(can_view(Some(FRANK), DAMI, Visibility::Shared, &shared));83- assert!(!can_view(Some(MALLORY), DAMI, Visibility::Shared, &shared));84- assert!(!can_view(None, DAMI, Visibility::Shared, &shared));80+ let shared = [BOB];81+ assert!(can_view(Some(ALICE), ALICE, Visibility::Shared, &shared));82+ assert!(can_view(Some(BOB), ALICE, Visibility::Shared, &shared));83+ assert!(!can_view(Some(MALLORY), ALICE, Visibility::Shared, &shared));84+ assert!(!can_view(None, ALICE, Visibility::Shared, &shared));8585 }8686 8787 #[test]8888 fn an_empty_share_list_is_not_a_wildcard() {8989 // A "shared" resource with nobody named must behave like a private one rather9090 // than falling open.91- assert!(!can_view(Some(FRANK), DAMI, Visibility::Shared, &[]));92- assert!(can_view(Some(DAMI), DAMI, Visibility::Shared, &[]));91+ assert!(!can_view(Some(BOB), ALICE, Visibility::Shared, &[]));92+ assert!(can_view(Some(ALICE), ALICE, Visibility::Shared, &[]));9393 }9494 }
M docs/profile-template.md +1 -1
M fixtures/page-a.html +1 -1
M fixtures/page-b.html +3 -3
M web/app.js +2 -2