`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>
@@ -60,17 +60,17 @@ cargo run -p devsite-fixture -- 4102 fixtures/page-b.html # Agent
6060 Sign in at <http://127.0.0.1:4000> (Google, via Shoo), or mint a session from the shell:6161 6262 ```bash63-cargo run -p devsite-server -- issue-session dami63+cargo run -p devsite-server -- issue-session alice6464 ```6565 6666 Then configure the machine:6767 6868 ```bash6969 devsite login --token <token>70-devsite profile create @dami70+devsite profile create @alice7171 devsite link add --name "Klot Ski" --url https://klot.ski --public7272 devsite expose http://127.0.0.1:4101 --name "Hermes" --private73-devsite expose http://127.0.0.1:4102 --name "Agent" --share @frank73+devsite expose http://127.0.0.1:4102 --name "Agent" --share @bob7474 devsite theme set my-theme.css7575 devsite daemon run7676 ```@@ -47,7 +47,7 @@ enum Command {
4747 public: bool,4848 )]4949 private: bool,50- /// Share with a specific user, e.g. --share @frank. Repeatable.50+ /// Share with a specific user, e.g. --share @bob. Repeatable.5151 5252 share: Vec<String>,5353 },@@ -63,7 +63,7 @@ enum Command {
6363 6464 6565 enum ProfileCommand {66- /// Claim a handle, e.g. `devsite profile create @dami`.66+ /// Claim a handle, e.g. `devsite profile create @alice`.6767 Create { handle: String },6868 }6969 @@ -233,7 +233,7 @@ async fn valid_capability_fetches_the_page(h: &Harness) {
233233 234234 async fn each_resource_maps_to_its_own_service(h: &Harness) {235235 // Proves the daemon routes by resource id rather than serving one default origin —236- // otherwise "Frank can reach Agent" would quietly also mean "Frank can reach Hermes".236+ // otherwise "Bob can reach Agent" would quietly also mean "Bob can reach Hermes".237237 let page = h.fetch(h.valid(h.agent)).await.unwrap();238238 assert!(page.contains(AGENT_BODY), "got: {page}");239239 assert!(!page.contains(HERMES_BODY));@@ -199,7 +199,7 @@ mod tests {
199199 200200 201201 fn rejects_use_from_a_different_browser_key() {202- // Frank hands his capability to someone else, or it leaks from the network. The202+ // Bob hands his capability to someone else, or it leaks from the network. The203203 // thief connects with their own endpoint key, and the binding fails.204204 let key = signing_key(9);205205 let cap = SignedCapability::sign(&claims([7; 32], [8; 32]), &key).unwrap();@@ -1,6 +1,6 @@
11 //! Immutable, opaque identifiers.22 //!3-//! Handles such as `@dami` are presentation names only. Every authorization decision in3+//! Handles such as `@alice` are presentation names only. Every authorization decision in44 //! the system is made against these IDs, which never change and are never reassigned.55 66 use std::fmt;@@ -493,7 +493,7 @@ async fn profile(
493493 }494494 495495 // "Shared with me" belongs on your own profile, not on everyone else's. Listing it on496- // @dami's page would also show Frank the same Agent entry twice.496+ // @alice's page would also show Bob the same Agent entry twice.497497 let mut shared_with_me = Vec::new();498498 if let Some(viewer_id) = viewer.filter(|v| *v == owner.id) {499499 for resource in db@@ -208,8 +208,8 @@ mod tests {
208208 209209 210210 fn accepts_reasonable_handles() {211- assert_eq!(validate_handle("@Dami").unwrap(), "dami");212- assert_eq!(validate_handle("frank_2").unwrap(), "frank_2");211+ assert_eq!(validate_handle("@Alice").unwrap(), "alice");212+ assert_eq!(validate_handle("bob_2").unwrap(), "bob_2");213213 }214214 215215 @@ -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 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 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 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 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 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 @@ -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 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 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 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 }@@ -190,7 +190,7 @@ fn issue_session(config: &Config, handle: &str) -> Result<()> {
190190 191191 // Attach to the existing account when the handle is taken. Creating a second one would192192 // collide on the unique handle, and the useful operator action here is "give me a193- // session for @dami" — including when @dami signed in through Shoo.193+ // session for @alice" — including when @alice signed in through Shoo.194194 let account = match db.account_by_handle(&handle)? {195195 Some(existing) => existing,196196 None => {@@ -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 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 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 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 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 }@@ -39,7 +39,7 @@ changes here and changes to the whitelist belong in the same commit.
3939 <main class="container" id="main">4040 <article id="profile">4141 <hgroup>42- <h1>@dami</h1>42+ <h1>@alice</h1>4343 <p>2 services · 1 link</p>4444 </hgroup>4545 @@ -25,7 +25,7 @@
2525 <div class="card">2626 <h1>Hermes</h1>2727 <p class="kicker">page a — private</p>28- <p>Served from <code>127.0.0.1:4101</code> on Dami's machine.</p>28+ <p>Served from <code>127.0.0.1:4101</code> on Alice's machine.</p>2929 <p>If you can read this, it arrived over an Iroh relay. No port was opened.</p>3030 <p class="clock" id="clock"></p>3131 </div>@@ -24,9 +24,9 @@
2424 <body>2525 <div class="card">2626 <h1>Agent</h1>27- <p class="kicker">page b — shared with @frank</p>28- <p>Served from <code>127.0.0.1:4102</code> on Dami's machine.</p>29- <p>Frank reached this without Dami forwarding a port or deploying anything.</p>27+ <p class="kicker">page b — shared with @bob</p>28+ <p>Served from <code>127.0.0.1:4102</code> on Alice's machine.</p>29+ <p>Bob reached this without Alice forwarding a port or deploying anything.</p>3030 <p class="clock" id="clock"></p>3131 </div>3232 <script>@@ -448,8 +448,8 @@ function renderClaimHandle() {
448448 </hgroup>449449 <form id="claim-form">450450 <fieldset role="group">451- <input id="handle" name="handle" placeholder="dami" autocomplete="off" spellcheck="false"452- aria-label="Handle" required>451+ <input id="handle" name="handle" placeholder="yourhandle" autocomplete="off"452+ spellcheck="false" aria-label="Handle" required>453453 <button type="submit">Claim</button>454454 </fieldset>455455 <small id="claim-note"></small>