import { action, assert, type Cell, currentPrincipal, equals, handler, pattern, type Stream, TESTS, Writable, } from "commonfabric"; import { seedProfileName, type SeedProfileNameEvent, } from "./profile-create.tsx"; import ProfileHome, { type ProfileInbox } from "./profile-home.tsx"; import PrivateInbox, { ensurePrivateInbox, type EnsurePrivateInboxEvent, isNonListAppendRefusal, type Offer, OFFER_ADDRESS_MAX_LENGTH, OFFER_DEFAULT_KIND, OFFER_ID_MAX_LENGTH, OFFER_KIND_MAX_LENGTH, OFFER_TITLE_MAX_LENGTH, pointProfilesAtPrivateInbox, type PointTarget, type PrivateInboxHolder, type PrivateInboxPiece, type PrivateInboxRefusalHolder, type PrivateInboxReplacementRecord, REFUSAL_REASON_MAX_LENGTH, replaceRefusedPrivateInbox, repointProfilesFromReplacedInbox, type RetainedPrivateInboxes, } from "./private-inbox.tsx"; /** A well-formed space DID for an offer to name. */ const ROOM_SPACE = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"; /** A well-formed DID of a principal other than the test's. */ const SOMEONE_ELSE = "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH"; /** A well-formed host origin for an offer to name. */ const HOST = "https://example.com"; /** The offer in `offers` with `id`, if any. */ function offerWithId( offers: readonly (Offer | undefined)[], id: string, ): Offer | undefined { return offers.find((each) => each?.id === id); } /** * A time no later than the start of this test's refusals: when the inbox * received the first offer, which the test sends before any refusal. */ function refusalsStartedBy(offers: readonly (Offer | undefined)[]): number { return offerWithId(offers, "loom-shaped")?.receivedAt ?? Infinity; } /** An inbox's result, as the link a holder keeps. */ function linkOf(inbox: unknown): Cell; function linkOf(inbox: unknown): unknown { return inbox; } /** * Creates an inbox and keeps it in `holder`, as `ensurePrivateInbox` does but * in the calling space. */ const holdNewInbox = handler }>( (_event, { holder }) => { holder.set({ piece: linkOf(PrivateInbox({ offers: [] })) }); }, ); /** A pointer as a profile holds it. */ type Pointer = { piece?: Cell }; /** Points a stand-in profile's pointer where the event says. */ const setStandInInbox = handler< { inbox?: Cell }, { inbox: Writable } >((event, { inbox }) => { inbox.set(event.inbox === undefined ? {} : { piece: event.inbox }); }); /** * Stands in for a profile of an earlier vintage: a pointer and `setInbox`, and * none of the current profile's other fields and streams. */ const EarlierVintageProfile = pattern< Record, { inbox: Pointer; setInbox: Stream<{ inbox?: Cell }> } >(() => { const inbox = new Writable({}).for("inbox"); return { inbox, setInbox: setStandInInbox({ inbox }) }; }); /** The string a malformed stored pointer holds instead of an object. */ const MALFORMED_POINTER = "broken-pointer-container"; /** * Stands in for a profile whose stored pointer is not an object, as a writer * bypassing `setInbox` can leave it. `stored` is the pointer as stored, which * `inbox`'s type does not show. */ const MalformedPointerProfile = pattern< Record, { inbox: Pointer; stored: Pointer | string; setInbox: Stream<{ inbox?: Cell }>; } >(() => { const inbox = new Writable(MALFORMED_POINTER).for("inbox"); return { // deno-lint-ignore no-explicit-any inbox: inbox as any, stored: inbox, // deno-lint-ignore no-explicit-any setInbox: setStandInInbox({ inbox: inbox as any }), }; }); /** * Stands in for the profile-create surface's seed step, the step that runs * after each profile is created, with Home's inbox given or left out as an * embedder gives it or leaves it out. */ const Seeder = pattern< { privateInbox?: ProfileInbox }, { seed: Stream } >(({ privateInbox }) => ({ seed: seedProfileName({ privateInbox }), })); /** * Stands in for Home's ensure step: Home's `ensurePrivateInbox` over a holder, * a list of retained inboxes and a profile list, with its pointing step, and * a refusal holder of its own, which `refusal` returns. */ const EnsuringHome = pattern< { privateInbox: Writable; retainedPrivateInboxes: Writable; profiles: PointTarget[]; }, { ensure: Stream; refusal: PrivateInboxRefusalHolder; } >(({ privateInbox, retainedPrivateInboxes, profiles }) => { const refusal = new Writable({}); return { ensure: ensurePrivateInbox({ privateInbox, retainedPrivateInboxes, privateInboxRefusal: refusal, profiles, pointProfiles: pointProfilesAtPrivateInbox({ privateInbox, profiles }), }), refusal, }; }); /** * Like {@link EnsuringHome}, except that the refusal holder is given, so that * a test can put a refusal in it first. */ const SeededEnsuringHome = pattern< { privateInbox: Writable; privateInboxRefusal: Writable; profiles: PointTarget[]; }, { ensure: Stream } >(({ privateInbox, privateInboxRefusal, profiles }) => ({ ensure: ensurePrivateInbox({ privateInbox, retainedPrivateInboxes: new Writable([]), privateInboxRefusal, profiles, pointProfiles: pointProfilesAtPrivateInbox({ privateInbox, profiles }), }), })); /** * Stands in for Home's replacement of a refused inbox: Home's * `replaceRefusedPrivateInbox` over a holder, a refusal holder and a profile * list, with its re-pointing step, which `repoint` returns, and a replacement * record of its own, which `replacement` returns. */ const ReplacingHome = pattern< { privateInbox: Writable; privateInboxRefusal: Writable; profiles: PointTarget[]; }, { replace: Stream; repoint: Stream; replacement: PrivateInboxReplacementRecord; } >(({ privateInbox, privateInboxRefusal, profiles }) => { const replacement = new Writable({}); const repoint = repointProfilesFromReplacedInbox({ privateInbox, privateInboxReplacement: replacement, profiles, }); return { replace: replaceRefusedPrivateInbox({ privateInbox, privateInboxRefusal, privateInboxReplacement: replacement, repointProfiles: repoint, }), repoint, replacement, }; }); /** Whether `retained` holds exactly the inboxes `expected` holds, in order. */ function retainsExactly( retained: readonly (Cell | undefined)[] | undefined, expected: readonly (Cell | undefined)[], ): boolean { return (retained ?? []).length === expected.length && expected.every((each, index) => equals(retained?.[index], each)); } /** Records the actor's principal in `me`. */ const introduce = handler }>((_event, { me }) => { me.set(currentPrincipal() ?? ""); }); export default pattern(() => { const inbox = PrivateInbox({ offers: [] }); const me = new Writable(""); const introduceMe = introduce({ me }); const action_introduce = action(() => { introduceMe.send(); }); // A loom-shaped offer, with all eight fields and one the envelope lacks. const action_receive_loom_shaped = action(() => { inbox.receive.send({ kind: "loom", id: "loom-shaped", space: ROOM_SPACE, host: HOST, ownerOrigin: "https://owner.example.com", title: "Lunch", from: me.get(), sharedAt: 1_700_000_000_123, extra: "dropped", } as never); }); const assert_loom_shaped_offer_kept_whole = assert(() => { const offer = offerWithId(inbox.offers, "loom-shaped"); return me.get() !== "" && offer !== undefined && offer.kind === "loom" && offer.space === ROOM_SPACE && offer.host === HOST && offer.ownerOrigin === "https://owner.example.com" && offer.title === "Lunch" && offer.from === me.get() && offer.sharedAt === 1_700_000_000_123 && typeof offer.receivedAt === "number" && offer.receivedAt > 0 && !("extra" in offer); }); // Strings are trimmed before they are checked and kept. const action_receive_padded = action(() => { inbox.receive.send({ kind: " fabrichat-room ", id: " padded ", space: ` ${ROOM_SPACE} `, host: ` ${HOST} `, ownerOrigin: ` ${HOST} `, title: " Dinner ", from: ` ${me.get()} `, }); }); const assert_padded_offer_trimmed = assert(() => { const offer = offerWithId(inbox.offers, "padded"); return offer !== undefined && offer.kind === "fabrichat-room" && offer.space === ROOM_SPACE && offer.host === HOST && offer.ownerOrigin === HOST && offer.title === "Dinner" && offer.from === me.get(); }); // What an offer that leaves fields out is kept with. const action_receive_bare = action(() => { inbox.receive.send({ space: ROOM_SPACE, host: HOST, ownerOrigin: "not an origin", from: me.get(), }); }); const assert_bare_offer_defaulted = assert(() => { const offer = inbox.offers.find((each) => each?.id.startsWith(`${ROOM_SPACE}@`) === true ); return offer !== undefined && offer.kind === OFFER_DEFAULT_KIND && offer.id === `${ROOM_SPACE}@${offer.sharedAt}` && offer.sharedAt === offer.receivedAt && offer.ownerOrigin === "" && offer.title === ""; }); // Over-long strings are cut, and a host is cut before it is checked. const longHost = `https://${"h".repeat(OFFER_ADDRESS_MAX_LENGTH)}`; const action_receive_long = action(() => { inbox.receive.send({ kind: "k".repeat(OFFER_KIND_MAX_LENGTH * 2), id: "i".repeat(OFFER_ID_MAX_LENGTH * 2), space: ROOM_SPACE, host: longHost, title: "t".repeat(OFFER_TITLE_MAX_LENGTH * 2), from: me.get(), }); }); const assert_long_offer_cut = assert(() => { const offer = offerWithId(inbox.offers, "i".repeat(OFFER_ID_MAX_LENGTH)); return offer !== undefined && offer.kind === "k".repeat(OFFER_KIND_MAX_LENGTH) && offer.title === "t".repeat(OFFER_TITLE_MAX_LENGTH) && offer.host === longHost.slice(0, OFFER_ADDRESS_MAX_LENGTH); }); // Each refused, by the one rule it breaks. const action_receive_refused = action(() => { const valid = { kind: "loom", space: ROOM_SPACE, host: HOST, from: me.get(), }; inbox.receive.send({ ...valid, id: "bad-space", space: "not-a-did" }); inbox.receive.send({ ...valid, id: "no-space", space: undefined }); inbox.receive.send({ ...valid, id: "bad-from", from: "not-a-did" }); inbox.receive.send({ ...valid, id: "no-from", from: undefined }); inbox.receive.send({ ...valid, id: "ftp-host", host: "ftp://example.com" }); inbox.receive.send({ ...valid, id: "path-host", host: `${HOST}/path` }); inbox.receive.send({ ...valid, id: "no-host", host: undefined }); inbox.receive.send({ ...valid, id: "userinfo-host", host: "https://good.example@evil.example", }); inbox.receive.send({ ...valid, id: "fragment-host", host: "https://good.example#@evil.example", }); inbox.receive.send({ ...valid, id: "query-host", host: "https://good.example?evil.example", }); inbox.receive.send({ ...valid, id: "bad-port-host", host: "https://example.com:99999", }); inbox.receive.send({ ...valid, id: "backslash-host", host: "https://example.com\\evil", }); inbox.receive.send({ ...valid, id: "default-port-host", host: "https://example.com:443", }); inbox.receive.send({ ...valid, id: "query-space", space: "did:key:abc?" }); inbox.receive.send({ ...valid, id: "not-me", from: SOMEONE_ELSE }); }); const assert_refused_offers_dropped = assert(() => [ "bad-space", "no-space", "bad-from", "no-from", "ftp-host", "path-host", "no-host", "userinfo-host", "fragment-host", "query-host", "bad-port-host", "backslash-host", "default-port-host", "query-space", "not-me", ].every((id) => offerWithId(inbox.offers, id) === undefined) ); // A second offer under an `id` the inbox holds is dropped. const action_receive_duplicate = action(() => { inbox.receive.send({ kind: "loom", id: "loom-shaped", space: ROOM_SPACE, host: HOST, title: "Second", from: me.get(), }); }); const assert_duplicate_dropped = assert(() => inbox.offers.filter((each) => each?.id === "loom-shaped").length === 1 && offerWithId(inbox.offers, "loom-shaped")?.title === "Lunch" ); // An inbox whose `offers` a writer replaced with something other than a // list keeps nothing, and leaves it as it is. const corruptOffers = new Writable("not a list"); // deno-lint-ignore no-explicit-any const corrupt = PrivateInbox({ offers: corruptOffers as any }); const action_receive_into_corrupt = action(() => { corrupt.receive.send({ kind: "loom", id: "into-corrupt", space: ROOM_SPACE, host: HOST, from: me.get(), }); }); const assert_corrupt_offers_left_as_they_were = assert(() => corruptOffers.get() === "not a list" ); // Only an append's refusal of a non-list is passed over; any other failure // of the append propagates out of `receive`. const assert_only_a_non_list_refusal_is_passed_over = assert(() => isNonListAppendRefusal( new Error( "Cell.push() or Cell.pushAll() requires transaction and array value\nhelp: use in handlers only, ensure cell is typed as array", ), ) && !isNonListAppendRefusal( new TypeError("Cell.pushAll() requires an array of values, not `1`"), ) && !isNonListAppendRefusal(new Error("writer-fit confidentiality misfit")) && !isNonListAppendRefusal(undefined) ); // Pointing profiles at an inbox: of the current vintage and of an earlier // one, one profile already points at another inbox, and one points at // nothing. const pointed = ProfileHome({ initialName: "Pointed" }); const unpointed = ProfileHome({ initialName: "Unpointed" }); const earlierPointed = EarlierVintageProfile({}); const earlierUnpointed = EarlierVintageProfile({}); const malformedPointer = MalformedPointerProfile({}); const home = new Writable({}); const elsewhere = new Writable({}); const holdHomeInbox = holdNewInbox({ holder: home }); const holdElsewhereInbox = holdNewInbox({ holder: elsewhere }); const pointProfiles = pointProfilesAtPrivateInbox({ privateInbox: home, profiles: [ pointed, earlierPointed, earlierUnpointed, unpointed, malformedPointer, // deno-lint-ignore no-explicit-any ] as any, }); const action_create_inboxes = action(() => { holdHomeInbox.send(); holdElsewhereInbox.send(); }); const action_point_one_elsewhere = action(() => { pointed.setInbox.send({ inbox: elsewhere.get().piece?.resolveAsCell() }); earlierPointed.setInbox.send({ inbox: elsewhere.get().piece?.resolveAsCell(), }); }); const action_point_profiles = action(() => { pointProfiles.send(); }); const assert_inboxes_created = assert(() => home.get().piece !== undefined && elsewhere.get().piece !== undefined && !equals(home.get().piece, elsewhere.get().piece) ); // Home repairs a stored pointer that is not an object: the pointer type // reads it as no pointer, so the owner's Home points the owner's profile. const assert_the_malformed_pointer_is_stored = assert(() => malformedPointer.stored === MALFORMED_POINTER ); const assert_the_malformed_pointer_is_repaired = assert(() => equals(malformedPointer.inbox?.piece, home.get().piece) ); const assert_only_the_unpointed_profile_points_at_home_inbox = assert(() => equals(pointed.inbox?.piece, elsewhere.get().piece) && equals(earlierPointed.inbox?.piece, elsewhere.get().piece) && equals(unpointed.inbox?.piece, home.get().piece) && equals(earlierUnpointed.inbox?.piece, home.get().piece) ); // A profile created after Home pointed its profiles is pointed by the seed // step that follows its creation: when Home's inbox is given and the profile // points at nothing, and not otherwise. const freshForInbox = ProfileHome({ initialName: "" }); const freshWithoutInbox = ProfileHome({ initialName: "" }); const freshPointedElsewhere = ProfileHome({ initialName: "" }); const seederWithInbox = Seeder({ privateInbox: home }); const seederWithoutInbox = Seeder({}); // A profile whose name is stored already, as when the seed event is // delivered again: left alone. const alreadyNamed = ProfileHome({ initialName: "" }); const action_name_the_existing_profile = action(() => { alreadyNamed.setName.send({ name: "Ada" }); }); const action_point_fresh_elsewhere = action(() => { freshPointedElsewhere.setInbox.send({ inbox: elsewhere.get().piece?.resolveAsCell(), }); }); const action_seed_fresh_profiles = action(() => { seederWithInbox.seed.send({ name: "Fresh", profile: freshForInbox }); seederWithoutInbox.seed.send({ name: "Fresh", profile: freshWithoutInbox }); seederWithInbox.seed.send({ name: "Fresh", profile: freshPointedElsewhere, }); seederWithInbox.seed.send({ name: "Fresh", profile: alreadyNamed }); }); const assert_only_the_unpointed_fresh_profile_is_pointed = assert(() => equals(freshForInbox.inbox?.piece, home.get().piece) && freshForInbox.name === "Fresh" && freshWithoutInbox.inbox?.piece === undefined && freshWithoutInbox.name === "Fresh" && equals(freshPointedElsewhere.inbox?.piece, elsewhere.get().piece) ); const assert_existing_named_profile_left_alone = assert(() => alreadyNamed.inbox?.piece === undefined && alreadyNamed.name === "Ada" ); // Ensuring Home's inbox. Which inbox Home should hold is the host's decision // (`packages/piece/test/ops/private-inbox.test.ts`); the event names the // inbox to adopt and the profile that decided it. Home adopts it only when // that profile is in its list and still points at it, retaining an inbox it // held, and otherwise keeps what it holds, or holds none. A profile pointing // at another inbox keeps its pointer, and the seed step points a new profile // at the adopted inbox. A Home holding none creates one when no profile // points at an inbox. const third = new Writable({}); const holdThirdInbox = holdNewInbox({ holder: third }); // Homes holding no inbox. const creatingUnpointed = ProfileHome({ initialName: "Creating unpointed" }); const creatingEarlier = EarlierVintageProfile({}); const creating = new Writable({}); const creatingRetained = new Writable([]); const ensureCreating = EnsuringHome({ privateInbox: creating, retainedPrivateInboxes: creatingRetained, // deno-lint-ignore no-explicit-any profiles: [creatingUnpointed, creatingEarlier] as any, }); const loneUnpointed = ProfileHome({ initialName: "Lone unpointed" }); const loneAdvertising = EarlierVintageProfile({}); const adoptingOne = new Writable({}); const adoptingOneRetained = new Writable([]); const ensureAdoptingOne = EnsuringHome({ privateInbox: adoptingOne, retainedPrivateInboxes: adoptingOneRetained, // deno-lint-ignore no-explicit-any profiles: [loneUnpointed, loneAdvertising] as any, }); const firstUnpointed = ProfileHome({ initialName: "First unpointed" }); const adoptedAdvertising = ProfileHome({ initialName: "Adopted advertising", }); const otherAdvertising = ProfileHome({ initialName: "Other advertising" }); const lastUnpointed = EarlierVintageProfile({}); const adoptingAmongOthers = new Writable({}); const ensureAdoptingAmongOthers = EnsuringHome({ privateInbox: adoptingAmongOthers, retainedPrivateInboxes: new Writable([]), // deno-lint-ignore no-explicit-any profiles: [ firstUnpointed, adoptedAdvertising, otherAdvertising, lastUnpointed, ] as any, }); // The host's order picked the second profile, as a default or the MRU list // does. const passedOverAdvertising = ProfileHome({ initialName: "Passed over advertising", }); const decidingAdvertising = ProfileHome({ initialName: "Deciding advertising", }); const followingDecider = new Writable({}); const ensureFollowingDecider = EnsuringHome({ privateInbox: followingDecider, retainedPrivateInboxes: new Writable([]), // deno-lint-ignore no-explicit-any profiles: [passedOverAdvertising, decidingAdvertising] as any, }); const unvettedUnpointed = ProfileHome({ initialName: "Unvetted unpointed" }); const unvettedAdvertising = ProfileHome({ initialName: "Unvetted advertising", }); const unvetted = new Writable({}); const ensureUnvetted = EnsuringHome({ privateInbox: unvetted, retainedPrivateInboxes: new Writable([]), // deno-lint-ignore no-explicit-any profiles: [unvettedUnpointed, unvettedAdvertising] as any, }); const mismatchedAdvertising = ProfileHome({ initialName: "Mismatched advertising", }); const mismatched = new Writable({}); const ensureMismatched = EnsuringHome({ privateInbox: mismatched, retainedPrivateInboxes: new Writable([]), // deno-lint-ignore no-explicit-any profiles: [mismatchedAdvertising] as any, }); // A profile outside the Home's list, pointing at the inbox the event names. const outsider = ProfileHome({ initialName: "Outsider" }); const outsiderListed = ProfileHome({ initialName: "Outsider listed" }); const namingAnOutsider = new Writable({}); const ensureNamingAnOutsider = EnsuringHome({ privateInbox: namingAnOutsider, retainedPrivateInboxes: new Writable([]), // deno-lint-ignore no-explicit-any profiles: [outsiderListed] as any, }); // An event from a host that names no deciding profile. const unnamedAdvertising = EarlierVintageProfile({}); const adoptingUnnamed = new Writable({}); const ensureAdoptingUnnamed = EnsuringHome({ privateInbox: adoptingUnnamed, retainedPrivateInboxes: new Writable([]), // deno-lint-ignore no-explicit-any profiles: [unnamedAdvertising] as any, }); const freshAfterAdoption = ProfileHome({ initialName: "" }); const seederAfterAdoption = Seeder({ privateInbox: adoptingOne }); // Homes holding Home's inbox. const readoptingAdvertising = ProfileHome({ initialName: "Adopting again advertising", }); const readoptingUnpointed = ProfileHome({ initialName: "Adopting again unpointed", }); const readopting = new Writable({}); const readoptingRetained = new Writable([]); const ensureReadopting = EnsuringHome({ privateInbox: readopting, retainedPrivateInboxes: readoptingRetained, // deno-lint-ignore no-explicit-any profiles: [readoptingAdvertising, readoptingUnpointed] as any, }); // Another profile still points at the inbox Home holds, ahead of the // deciding one in the list. const stillAdvertisingHeld = ProfileHome({ initialName: "Still advertising held", }); const decidingElsewhere = EarlierVintageProfile({}); const readoptingOverAnother = new Writable({}); const readoptingOverAnotherRetained = new Writable( [], ); const ensureReadoptingOverAnother = EnsuringHome({ privateInbox: readoptingOverAnother, retainedPrivateInboxes: readoptingOverAnotherRetained, // deno-lint-ignore no-explicit-any profiles: [stillAdvertisingHeld, decidingElsewhere] as any, }); // One whose retained list already holds the inbox it adopts, as after Home // gave that inbox up and a profile then pointed at it again. const returningAdvertising = EarlierVintageProfile({}); const returning = new Writable({}); const returningRetained = new Writable([]); const ensureReturning = EnsuringHome({ privateInbox: returning, retainedPrivateInboxes: returningRetained, // deno-lint-ignore no-explicit-any profiles: [returningAdvertising] as any, }); const keepingUnadvertisedPointed = ProfileHome({ initialName: "Keeping unadvertised pointed", }); const keepingUnadvertised = new Writable({}); const keepingUnadvertisedRetained = new Writable([]); const ensureKeepingUnadvertised = EnsuringHome({ privateInbox: keepingUnadvertised, retainedPrivateInboxes: keepingUnadvertisedRetained, // deno-lint-ignore no-explicit-any profiles: [keepingUnadvertisedPointed] as any, }); const refusingAdvertising = ProfileHome({ initialName: "Refusing advertising", }); const refusing = new Writable({}); const refusingRetained = new Writable([]); const ensureRefusing = EnsuringHome({ privateInbox: refusing, retainedPrivateInboxes: refusingRetained, // deno-lint-ignore no-explicit-any profiles: [refusingAdvertising] as any, }); const guardedAdvertising = ProfileHome({ initialName: "Guarded advertising", }); const guarded = new Writable({}); const guardedRetained = new Writable([]); const ensureGuarded = EnsuringHome({ privateInbox: guarded, retainedPrivateInboxes: guardedRetained, // deno-lint-ignore no-explicit-any profiles: [guardedAdvertising] as any, }); const heldOutsiderListed = ProfileHome({ initialName: "Held outsider listed", }); const heldNamingAnOutsider = new Writable({}); const heldNamingAnOutsiderRetained = new Writable( [], ); const ensureHeldNamingAnOutsider = EnsuringHome({ privateInbox: heldNamingAnOutsider, retainedPrivateInboxes: heldNamingAnOutsiderRetained, // deno-lint-ignore no-explicit-any profiles: [heldOutsiderListed] as any, }); // One holding the link Home's holder reached the inbox through when it // created it, while its profile is given the inbox's own result document, so // the two links are equal only once both are resolved. const aliasAdvertising = ProfileHome({ initialName: "Alias advertising" }); const aliasKeeping = new Writable({}); const aliasKeepingRetained = new Writable([]); const ensureAliasKeeping = EnsuringHome({ privateInbox: aliasKeeping, retainedPrivateInboxes: aliasKeepingRetained, // deno-lint-ignore no-explicit-any profiles: [aliasAdvertising] as any, }); const action_advertise_inboxes = action(() => { holdThirdInbox.send(); const advertised = elsewhere.get().piece?.resolveAsCell(); const homeInbox = home.get().piece?.resolveAsCell(); for ( const profile of [ loneAdvertising, adoptedAdvertising, passedOverAdvertising, unvettedAdvertising, mismatchedAdvertising, outsiderListed, unnamedAdvertising, readoptingAdvertising, decidingElsewhere, returningAdvertising, refusingAdvertising, guardedAdvertising, heldOutsiderListed, outsider, ] ) { profile.setInbox.send({ inbox: advertised }); } stillAdvertisingHeld.setInbox.send({ inbox: homeInbox }); aliasAdvertising.setInbox.send({ inbox: homeInbox }); for ( const holder of [ readopting, readoptingOverAnother, returning, keepingUnadvertised, refusing, guarded, heldNamingAnOutsider, ] ) { holder.set({ piece: homeInbox }); } aliasKeeping.set({ piece: home.get().piece }); if (advertised !== undefined) returningRetained.set([advertised]); }); const action_advertise_a_second_inbox = action(() => { const another = third.get().piece?.resolveAsCell(); otherAdvertising.setInbox.send({ inbox: another }); decidingAdvertising.setInbox.send({ inbox: another }); }); const action_ensure_inboxes = action(() => { const vetted = elsewhere.get().piece?.resolveAsCell(); const another = third.get().piece?.resolveAsCell(); const homeInbox = home.get().piece?.resolveAsCell(); ensureCreating.ensure.send({}); ensureAdoptingOne.ensure.send({ adopt: vetted, from: loneAdvertising }); ensureAdoptingAmongOthers.ensure.send({ adopt: vetted, from: adoptedAdvertising, }); ensureFollowingDecider.ensure.send({ adopt: another, from: decidingAdvertising, }); ensureUnvetted.ensure.send({}); ensureMismatched.ensure.send({ adopt: another, from: mismatchedAdvertising, }); ensureNamingAnOutsider.ensure.send({ adopt: vetted, from: outsider }); ensureAdoptingUnnamed.ensure.send({ adopt: vetted }); ensureReadopting.ensure.send({ adopt: vetted, from: readoptingAdvertising, }); ensureReadoptingOverAnother.ensure.send({ adopt: vetted, from: decidingElsewhere, }); ensureReturning.ensure.send({ adopt: vetted, from: returningAdvertising }); ensureKeepingUnadvertised.ensure.send({}); ensureRefusing.ensure.send({}); ensureGuarded.ensure.send({ adopt: another, from: guardedAdvertising }); ensureHeldNamingAnOutsider.ensure.send({ adopt: vetted, from: outsider }); ensureAliasKeeping.ensure.send({ adopt: homeInbox, from: aliasAdvertising, }); }); // The created inbox is none of the others. Asserted again after the second // ensure, where a Home that created another inbox would hold one its // profiles do not point at. const assert_an_inbox_is_created_when_none_is_advertised = assert(() => creating.get().piece !== undefined && !equals(creating.get().piece, home.get().piece) && !equals(creating.get().piece, elsewhere.get().piece) && !equals(creating.get().piece, third.get().piece) && equals(creatingUnpointed.inbox?.piece, creating.get().piece) && equals(creatingEarlier.inbox?.piece, creating.get().piece) && creatingRetained.get().length === 0 && ensureCreating.refusal.refusal === undefined ); const assert_the_named_inbox_is_adopted = assert(() => equals(adoptingOne.get().piece, elsewhere.get().piece) && equals(loneUnpointed.inbox?.piece, elsewhere.get().piece) && equals(loneAdvertising.inbox?.piece, elsewhere.get().piece) && adoptingOneRetained.get().length === 0 ); const assert_another_advertised_inbox_is_left_as_it_was = assert(() => equals(adoptingAmongOthers.get().piece, elsewhere.get().piece) && equals(firstUnpointed.inbox?.piece, elsewhere.get().piece) && equals(lastUnpointed.inbox?.piece, elsewhere.get().piece) && equals(otherAdvertising.inbox?.piece, third.get().piece) ); const assert_the_deciding_profile_is_followed_past_an_earlier_one = assert( () => equals(followingDecider.get().piece, third.get().piece) && equals(passedOverAdvertising.inbox?.piece, elsewhere.get().piece), ); const assert_an_unvetted_advertisement_leaves_home_without_an_inbox = assert( () => unvetted.get().piece === undefined && unvettedUnpointed.inbox?.piece === undefined && equals(unvettedAdvertising.inbox?.piece, elsewhere.get().piece), ); const assert_an_inbox_the_named_profile_does_not_advertise_is_not_adopted = assert(() => mismatched.get().piece === undefined && equals(mismatchedAdvertising.inbox?.piece, elsewhere.get().piece) ); const assert_an_inbox_named_by_a_profile_outside_the_list_is_not_adopted = assert(() => namingAnOutsider.get().piece === undefined && heldNamingAnOutsiderRetained.get().length === 0 && equals(heldNamingAnOutsider.get().piece, home.get().piece) && equals(outsider.inbox?.piece, elsewhere.get().piece) ); const assert_an_unnamed_profile_is_taken_as_the_first_advertising_one = assert(() => equals(adoptingUnnamed.get().piece, elsewhere.get().piece)); const assert_a_held_inbox_is_replaced_and_retained = assert(() => equals(readopting.get().piece, elsewhere.get().piece) && retainsExactly(readoptingRetained.get(), [home.get().piece]) && equals(readoptingUnpointed.inbox?.piece, elsewhere.get().piece) && equals(readoptingAdvertising.inbox?.piece, elsewhere.get().piece) ); const assert_a_held_inbox_another_profile_advertises_is_replaced = assert( () => equals(readoptingOverAnother.get().piece, elsewhere.get().piece) && retainsExactly(readoptingOverAnotherRetained.get(), [ home.get().piece, ]) && equals(stillAdvertisingHeld.inbox?.piece, home.get().piece), ); const assert_an_inbox_adopted_again_leaves_the_retained_list = assert(() => equals(returning.get().piece, elsewhere.get().piece) && retainsExactly(returningRetained.get(), [home.get().piece]) ); const assert_a_held_inbox_is_kept_when_none_is_advertised = assert(() => equals(keepingUnadvertised.get().piece, home.get().piece) && keepingUnadvertisedRetained.get().length === 0 && equals(keepingUnadvertisedPointed.inbox?.piece, home.get().piece) ); const assert_a_held_inbox_is_kept_when_the_host_names_none = assert(() => equals(refusing.get().piece, home.get().piece) && refusingRetained.get().length === 0 && equals(refusingAdvertising.inbox?.piece, elsewhere.get().piece) ); const assert_a_held_inbox_is_kept_when_the_host_names_another = assert(() => equals(guarded.get().piece, home.get().piece) && guardedRetained.get().length === 0 && equals(guardedAdvertising.inbox?.piece, elsewhere.get().piece) ); const assert_a_held_inbox_reached_through_another_link_is_kept = assert( () => equals(aliasKeeping.get().piece, home.get().piece) && !aliasKeeping.get().piece?.equalLinks(aliasAdvertising.inbox?.piece) && aliasKeepingRetained.get().length === 0, ); const action_seed_after_adoption = action(() => { seederAfterAdoption.seed.send({ name: "Fresh", profile: freshAfterAdoption, }); }); const assert_a_new_profile_is_pointed_at_the_adopted_inbox = assert(() => equals(freshAfterAdoption.inbox?.piece, elsewhere.get().piece) ); // Recording the host's refusal of the deciding profile's inbox. Home records // a refusal only while the profile the event names is in its list and still // points at the refused inbox, replaces one recorded before, and clears it // when it adopts an inbox, when the deciding profile points at the inbox it // holds, and when no profile in its list points at the refused inbox. It // never records a refusal of the inbox it holds, and cuts a long code. // Clearing it when Home creates an inbox is covered by // `integration/private-inbox-multi-runtime.test.ts`. const REFUSED = "inbox-adoption-acl-mismatch"; const REFUSED_AGAIN = "inbox-receive-missing"; const refusedNoneUnpointed = ProfileHome({ initialName: "Refused none unpointed", }); const refusedNoneAdvertising = ProfileHome({ initialName: "Refused none advertising", }); const refusedNone = new Writable({}); const ensureRefusedNone = EnsuringHome({ privateInbox: refusedNone, retainedPrivateInboxes: new Writable([]), // deno-lint-ignore no-explicit-any profiles: [refusedNoneUnpointed, refusedNoneAdvertising] as any, }); const refusedHeldAdvertising = ProfileHome({ initialName: "Refused held advertising", }); const refusedHeld = new Writable({}); const refusedHeldRetained = new Writable([]); const ensureRefusedHeld = EnsuringHome({ privateInbox: refusedHeld, retainedPrivateInboxes: refusedHeldRetained, // deno-lint-ignore no-explicit-any profiles: [refusedHeldAdvertising] as any, }); const staleInboxAdvertising = ProfileHome({ initialName: "Stale inbox advertising", }); const ensureStaleInbox = EnsuringHome({ privateInbox: new Writable({}), retainedPrivateInboxes: new Writable([]), // deno-lint-ignore no-explicit-any profiles: [staleInboxAdvertising] as any, }); const staleProfileListed = ProfileHome({ initialName: "Stale profile listed", }); const ensureStaleProfile = EnsuringHome({ privateInbox: new Writable({}), retainedPrivateInboxes: new Writable([]), // deno-lint-ignore no-explicit-any profiles: [staleProfileListed] as any, }); const unnamedRefusalAdvertising = ProfileHome({ initialName: "Unnamed refusal advertising", }); const ensureUnnamedRefusal = EnsuringHome({ privateInbox: new Writable({}), retainedPrivateInboxes: new Writable([]), // deno-lint-ignore no-explicit-any profiles: [unnamedRefusalAdvertising] as any, }); const repeatedAdvertising = ProfileHome({ initialName: "Repeated advertising", }); const ensureRepeated = EnsuringHome({ privateInbox: new Writable({}), retainedPrivateInboxes: new Writable([]), // deno-lint-ignore no-explicit-any profiles: [repeatedAdvertising] as any, }); const abandonedAdvertising = ProfileHome({ initialName: "Abandoned advertising", }); const abandoned = new Writable({}); const ensureAbandoned = EnsuringHome({ privateInbox: abandoned, retainedPrivateInboxes: new Writable([]), // deno-lint-ignore no-explicit-any profiles: [abandonedAdvertising] as any, }); const stillRefusedMoved = ProfileHome({ initialName: "Still refused moved" }); const stillRefusedStaying = ProfileHome({ initialName: "Still refused staying", }); const stillRefused = new Writable({}); const ensureStillRefused = EnsuringHome({ privateInbox: stillRefused, retainedPrivateInboxes: new Writable([]), // deno-lint-ignore no-explicit-any profiles: [stillRefusedMoved, stillRefusedStaying] as any, }); const longReasonAdvertising = ProfileHome({ initialName: "Long reason advertising", }); const ensureLongReason = EnsuringHome({ privateInbox: new Writable({}), retainedPrivateInboxes: new Writable([]), // deno-lint-ignore no-explicit-any profiles: [longReasonAdvertising] as any, }); const curedAdvertising = ProfileHome({ initialName: "Cured advertising" }); const cured = new Writable({}); const ensureCured = EnsuringHome({ privateInbox: cured, retainedPrivateInboxes: new Writable([]), // deno-lint-ignore no-explicit-any profiles: [curedAdvertising] as any, }); // A Home whose refused profile moves to a third inbox, and is then named by // a refusal it no longer advertises. const movedAwayAdvertising = ProfileHome({ initialName: "Moved away advertising", }); const movedAway = new Writable({}); const ensureMovedAway = EnsuringHome({ privateInbox: movedAway, retainedPrivateInboxes: new Writable([]), // deno-lint-ignore no-explicit-any profiles: [movedAwayAdvertising] as any, }); // A Home whose first advertising profile points at another inbox, ahead of // the one still pointing at the refused inbox. const secondFirst = ProfileHome({ initialName: "Second first" }); const secondRefused = ProfileHome({ initialName: "Second refused" }); const secondAdvertiser = new Writable({}); const ensureSecondAdvertiser = EnsuringHome({ privateInbox: secondAdvertiser, retainedPrivateInboxes: new Writable([]), // deno-lint-ignore no-explicit-any profiles: [secondFirst, secondRefused] as any, }); // A Home whose deciding profile, pointing at the held inbox, is not its // first advertising profile, which still points at the refused inbox. const heldLaterRefused = ProfileHome({ initialName: "Held later refused" }); const heldLaterDeciding = ProfileHome({ initialName: "Held later deciding", }); const heldLater = new Writable({}); const ensureHeldLater = EnsuringHome({ privateInbox: heldLater, retainedPrivateInboxes: new Writable([]), // deno-lint-ignore no-explicit-any profiles: [heldLaterRefused, heldLaterDeciding] as any, }); // Homes holding a refusal recorded at a known time: one of the inbox their // profile advertises, and one of another inbox. const EARLIER = 1_000; const keptAdvertising = ProfileHome({ initialName: "Kept advertising" }); const keptRefusal = new Writable({}); const ensureKept = SeededEnsuringHome({ privateInbox: new Writable({}), privateInboxRefusal: keptRefusal, // deno-lint-ignore no-explicit-any profiles: [keptAdvertising] as any, }); const otherInboxAdvertising = ProfileHome({ initialName: "Other inbox advertising", }); const otherInboxRefusal = new Writable({}); const ensureOtherInbox = SeededEnsuringHome({ privateInbox: new Writable({}), privateInboxRefusal: otherInboxRefusal, // deno-lint-ignore no-explicit-any profiles: [otherInboxAdvertising] as any, }); const action_advertise_refused_inboxes = action(() => { const advertised = elsewhere.get().piece?.resolveAsCell(); for ( const profile of [ refusedNoneAdvertising, refusedHeldAdvertising, staleInboxAdvertising, staleProfileListed, unnamedRefusalAdvertising, repeatedAdvertising, curedAdvertising, abandonedAdvertising, stillRefusedMoved, stillRefusedStaying, longReasonAdvertising, movedAwayAdvertising, secondRefused, heldLaterRefused, keptAdvertising, otherInboxAdvertising, ] ) { profile.setInbox.send({ inbox: advertised }); } const homeInbox = home.get().piece?.resolveAsCell(); const another = third.get().piece?.resolveAsCell(); secondFirst.setInbox.send({ inbox: another }); heldLaterDeciding.setInbox.send({ inbox: homeInbox }); refusedHeld.set({ piece: homeInbox }); abandoned.set({ piece: homeInbox }); stillRefused.set({ piece: homeInbox }); movedAway.set({ piece: homeInbox }); secondAdvertiser.set({ piece: homeInbox }); heldLater.set({ piece: homeInbox }); if (advertised !== undefined && another !== undefined) { keptRefusal.set({ refusal: { reason: REFUSED, inbox: advertised, refusedAt: EARLIER }, }); otherInboxRefusal.set({ refusal: { reason: REFUSED, inbox: another, refusedAt: EARLIER }, }); } }); const action_send_refusals = action(() => { const advertised = elsewhere.get().piece?.resolveAsCell(); const another = third.get().piece?.resolveAsCell(); if (advertised === undefined || another === undefined) return; ensureRefusedNone.ensure.send({ from: refusedNoneAdvertising, refused: { reason: REFUSED, inbox: advertised }, }); ensureRefusedHeld.ensure.send({ from: refusedHeldAdvertising, refused: { reason: REFUSED, inbox: advertised }, }); ensureStaleInbox.ensure.send({ from: staleInboxAdvertising, refused: { reason: REFUSED, inbox: another }, }); ensureStaleProfile.ensure.send({ from: outsider, refused: { reason: REFUSED, inbox: advertised }, }); ensureUnnamedRefusal.ensure.send({ refused: { reason: REFUSED, inbox: advertised }, }); ensureRepeated.ensure.send({ from: repeatedAdvertising, refused: { reason: REFUSED, inbox: advertised }, }); ensureCured.ensure.send({ from: curedAdvertising, refused: { reason: REFUSED, inbox: advertised }, }); ensureAbandoned.ensure.send({ from: abandonedAdvertising, refused: { reason: REFUSED, inbox: advertised }, }); ensureStillRefused.ensure.send({ from: stillRefusedMoved, refused: { reason: REFUSED, inbox: advertised }, }); for ( const [home, profile] of [ [ensureMovedAway, movedAwayAdvertising], [ensureSecondAdvertiser, secondRefused], [ensureHeldLater, heldLaterRefused], [ensureKept, keptAdvertising], [ensureOtherInbox, otherInboxAdvertising], ] as const ) { home.ensure.send({ from: profile, refused: { reason: REFUSED, inbox: advertised }, }); } ensureLongReason.ensure.send({ from: longReasonAdvertising, refused: { reason: ` ${"r".repeat(REFUSAL_REASON_MAX_LENGTH * 3)} `, inbox: advertised, }, }); }); const assert_a_long_refusal_code_is_trimmed_and_cut = assert(() => ensureLongReason.refusal.refusal?.reason === "r".repeat(REFUSAL_REASON_MAX_LENGTH) ); const assert_a_refusal_is_recorded_with_its_reason_and_inbox = assert(() => { const refusal = ensureRefusedNone.refusal.refusal; return refusal !== undefined && refusal.reason === REFUSED && equals(refusal.inbox, elsewhere.get().piece) && typeof refusal.refusedAt === "number" && refusal.refusedAt >= refusalsStartedBy(inbox.offers) && refusedNone.get().piece === undefined && refusedNoneUnpointed.inbox?.piece === undefined; }); const assert_a_refusal_is_recorded_beside_a_held_inbox = assert(() => ensureRefusedHeld.refusal.refusal?.reason === REFUSED && equals(ensureRefusedHeld.refusal.refusal?.inbox, elsewhere.get().piece) && equals(refusedHeld.get().piece, home.get().piece) && refusedHeldRetained.get().length === 0 ); const assert_a_refusal_of_an_inbox_the_named_profile_does_not_advertise_is_not_recorded = assert(() => ensureStaleInbox.refusal.refusal === undefined); const assert_a_refusal_named_by_a_profile_outside_the_list_is_not_recorded = assert(() => ensureStaleProfile.refusal.refusal === undefined); const assert_a_refusal_naming_no_profile_is_not_recorded = assert(() => ensureUnnamedRefusal.refusal.refusal === undefined ); const assert_a_repeat_of_the_recorded_refusal_keeps_its_time = assert(() => keptRefusal.get().refusal?.refusedAt === EARLIER && keptRefusal.get().refusal?.reason === REFUSED ); const assert_a_refusal_of_another_inbox_takes_a_new_time = assert(() => equals(otherInboxRefusal.get().refusal?.inbox, elsewhere.get().piece) && (otherInboxRefusal.get().refusal?.refusedAt ?? 0) >= refusalsStartedBy(inbox.offers) ); const assert_an_event_naming_no_refusal_records_none = assert(() => ensureRefusing.refusal.refusal === undefined && ensureUnvetted.refusal.refusal === undefined ); const action_move_refused_pointers = action(() => { repeatedAdvertising.setInbox.send({ inbox: third.get().piece?.resolveAsCell(), }); refusedHeldAdvertising.setInbox.send({ inbox: home.get().piece?.resolveAsCell(), }); abandonedAdvertising.setInbox.send({}); stillRefusedMoved.setInbox.send({}); movedAwayAdvertising.setInbox.send({ inbox: third.get().piece?.resolveAsCell(), }); }); const action_send_after_the_refusals = action(() => { const advertised = elsewhere.get().piece?.resolveAsCell(); const another = third.get().piece?.resolveAsCell(); if (another === undefined) return; ensureRepeated.ensure.send({ from: repeatedAdvertising, refused: { reason: REFUSED_AGAIN, inbox: another }, }); ensureRefusedHeld.ensure.send({ from: refusedHeldAdvertising }); ensureCured.ensure.send({ adopt: advertised, from: curedAdvertising }); ensureAbandoned.ensure.send({}); ensureStillRefused.ensure.send({ from: stillRefusedStaying }); if (advertised === undefined) return; // A refusal naming a profile that no longer advertises the refused inbox, // as a stale event does. ensureMovedAway.ensure.send({ from: movedAwayAdvertising, refused: { reason: REFUSED, inbox: advertised }, }); ensureSecondAdvertiser.ensure.send({}); ensureHeldLater.ensure.send({ from: heldLaterDeciding }); ensureKept.ensure.send({ from: keptAdvertising, refused: { reason: REFUSED_AGAIN, inbox: advertised }, }); }); const assert_a_repeated_refusal_replaces_the_one_recorded = assert(() => ensureRepeated.refusal.refusal?.reason === REFUSED_AGAIN && equals(ensureRepeated.refusal.refusal?.inbox, third.get().piece) ); const assert_a_refusal_is_cleared_when_the_deciding_profile_points_at_the_held_inbox = assert(() => ensureRefusedHeld.refusal.refusal === undefined && equals(refusedHeld.get().piece, home.get().piece) ); const assert_a_refusal_and_its_inbox_are_recorded_before_the_pointers_move = assert(() => equals(ensureAbandoned.refusal.refusal?.inbox, elsewhere.get().piece) && equals(ensureStillRefused.refusal.refusal?.inbox, elsewhere.get().piece) ); const assert_a_refusal_is_cleared_when_no_profile_points_at_the_refused_inbox = assert(() => ensureAbandoned.refusal.refusal === undefined && abandonedAdvertising.inbox?.piece !== undefined && equals(abandonedAdvertising.inbox?.piece, home.get().piece) ); const assert_a_refusal_is_kept_while_another_profile_points_at_the_refused_inbox = assert(() => equals(ensureStillRefused.refusal.refusal?.inbox, elsewhere.get().piece) ); // A refusal naming the inbox Home holds, as a stale refusal that lost a race // to an adoption of the same inbox, or the owner's own code, sends one. const action_refuse_the_held_inbox = action(() => { const homeInbox = home.get().piece?.resolveAsCell(); if (homeInbox === undefined) return; ensureRefusedHeld.ensure.send({ from: refusedHeldAdvertising, refused: { reason: "held-reason", inbox: homeInbox }, }); }); const assert_a_refusal_of_the_held_inbox_is_not_recorded = assert(() => ensureRefusedHeld.refusal.refusal === undefined && equals(refusedHeld.get().piece, home.get().piece) && equals(refusedHeldAdvertising.inbox?.piece, home.get().piece) ); const assert_a_stale_refusal_clears_one_no_profile_points_at = assert(() => ensureMovedAway.refusal.refusal === undefined && equals(movedAwayAdvertising.inbox?.piece, third.get().piece) ); const assert_a_refusal_a_later_profile_still_points_at_is_kept = assert(() => equals( ensureSecondAdvertiser.refusal.refusal?.inbox, elsewhere.get().piece, ) && equals(secondFirst.inbox?.piece, third.get().piece) ); const assert_a_refusal_is_cleared_when_a_later_deciding_profile_points_at_the_held_inbox = assert(() => ensureHeldLater.refusal.refusal === undefined && equals(heldLaterRefused.inbox?.piece, elsewhere.get().piece) ); const assert_a_new_reason_for_the_recorded_inbox_takes_a_new_time = assert( () => keptRefusal.get().refusal?.reason === REFUSED_AGAIN && (keptRefusal.get().refusal?.refusedAt ?? 0) >= refusalsStartedBy(inbox.offers), ); const assert_a_refusal_is_cleared_when_home_adopts_an_inbox = assert(() => ensureCured.refusal.refusal === undefined && equals(cured.get().piece, elsewhere.get().piece) ); // Replacing the refused inbox, for the owner. Home keeps the inbox it holds, // clears the refusal and records it as replaced, and points the profiles // that point at the refused inbox at its own; profiles pointing at another // inbox, or at none, are left alone. With no refusal recorded it does // nothing. The re-pointing step reads the refused inbox from the record, so // sending it again re-points a pointer moved back to the refused inbox, and // with no record it does nothing. Replacing while Home holds no inbox, which // creates one, is covered by // `integration/private-inbox-multi-runtime.test.ts`. const replacedFirst = ProfileHome({ initialName: "Replaced first" }); const replacedSecond = ProfileHome({ initialName: "Replaced second" }); const replacedOther = ProfileHome({ initialName: "Replaced other" }); const replacedUnpointed = ProfileHome({ initialName: "Replaced unpointed" }); const replacing = new Writable({}); const replacingRefusal = new Writable({}); const replaceRefused = ReplacingHome({ privateInbox: replacing, privateInboxRefusal: replacingRefusal, profiles: [ replacedFirst, replacedSecond, replacedOther, replacedUnpointed, // deno-lint-ignore no-explicit-any ] as any, }); const unrefusedAdvertising = ProfileHome({ initialName: "Unrefused advertising", }); const unrefused = new Writable({}); const replaceUnrefused = ReplacingHome({ privateInbox: unrefused, privateInboxRefusal: new Writable({}), // deno-lint-ignore no-explicit-any profiles: [unrefusedAdvertising] as any, }); const action_advertise_the_inbox_to_replace = action(() => { const refused = elsewhere.get().piece?.resolveAsCell(); const homeInbox = home.get().piece?.resolveAsCell(); if (refused === undefined || homeInbox === undefined) return; replacedFirst.setInbox.send({ inbox: refused }); replacedSecond.setInbox.send({ inbox: refused }); replacedOther.setInbox.send({ inbox: third.get().piece?.resolveAsCell() }); unrefusedAdvertising.setInbox.send({ inbox: refused }); replacing.set({ piece: homeInbox }); unrefused.set({ piece: homeInbox }); replacingRefusal.set({ refusal: { reason: REFUSED, inbox: refused, refusedAt: EARLIER }, }); }); const action_replace_the_refused_inbox = action(() => { replaceRefused.replace.send(); replaceUnrefused.replace.send(); }); const assert_the_profiles_pointing_at_the_refused_inbox_point_at_home_inbox = assert(() => equals(replacedFirst.inbox?.piece, home.get().piece) && equals(replacedSecond.inbox?.piece, home.get().piece) && equals(replacing.get().piece, home.get().piece) ); const assert_replacing_leaves_profiles_pointing_elsewhere_or_nowhere = assert( () => equals(replacedOther.inbox?.piece, third.get().piece) && replacedUnpointed.inbox?.piece === undefined, ); const assert_replacing_clears_the_refusal_and_records_it = assert(() => { const replacement = replaceRefused.replacement.replacement; return replacingRefusal.get().refusal === undefined && replacement?.reason === REFUSED && replacement.refusedAt === EARLIER && equals(replacement.inbox, elsewhere.get().piece) && replacement.replacedAt >= refusalsStartedBy(inbox.offers); }); const assert_replacing_with_no_refusal_does_nothing = assert(() => replaceUnrefused.replacement.replacement === undefined && equals(unrefusedAdvertising.inbox?.piece, elsewhere.get().piece) && equals(unrefused.get().piece, home.get().piece) ); const action_point_back_at_the_replaced_inbox = action(() => { replacedSecond.setInbox.send({ inbox: elsewhere.get().piece?.resolveAsCell(), }); }); const action_repoint_again = action(() => { replaceRefused.repoint.send(); replaceUnrefused.repoint.send(); }); return { [TESTS]: [ { action: action_introduce }, { action: action_receive_loom_shaped }, { assertion: assert_loom_shaped_offer_kept_whole }, { action: action_receive_padded }, { assertion: assert_padded_offer_trimmed }, { action: action_receive_bare }, { assertion: assert_bare_offer_defaulted }, { action: action_receive_long }, { assertion: assert_long_offer_cut }, { action: action_receive_refused }, { assertion: assert_refused_offers_dropped }, { action: action_receive_duplicate }, { assertion: assert_duplicate_dropped }, { action: action_receive_into_corrupt }, { assertion: assert_corrupt_offers_left_as_they_were }, { assertion: assert_only_a_non_list_refusal_is_passed_over }, { action: action_create_inboxes }, { assertion: assert_inboxes_created }, { action: action_point_one_elsewhere }, { assertion: assert_the_malformed_pointer_is_stored }, { action: action_point_profiles }, { assertion: assert_only_the_unpointed_profile_points_at_home_inbox }, { assertion: assert_the_malformed_pointer_is_repaired }, // Pointing again changes nothing. { action: action_point_profiles }, { assertion: assert_only_the_unpointed_profile_points_at_home_inbox }, { action: action_point_fresh_elsewhere }, { action: action_name_the_existing_profile }, { action: action_seed_fresh_profiles }, { assertion: assert_only_the_unpointed_fresh_profile_is_pointed }, { assertion: assert_existing_named_profile_left_alone }, { action: action_advertise_inboxes }, { action: action_advertise_a_second_inbox }, { action: action_ensure_inboxes }, { assertion: assert_an_inbox_is_created_when_none_is_advertised }, { assertion: assert_the_named_inbox_is_adopted }, { assertion: assert_another_advertised_inbox_is_left_as_it_was }, { assertion: assert_the_deciding_profile_is_followed_past_an_earlier_one, }, { assertion: assert_an_unvetted_advertisement_leaves_home_without_an_inbox, }, { assertion: assert_an_inbox_the_named_profile_does_not_advertise_is_not_adopted, }, { assertion: assert_an_inbox_named_by_a_profile_outside_the_list_is_not_adopted, }, { assertion: assert_an_unnamed_profile_is_taken_as_the_first_advertising_one, }, { assertion: assert_a_held_inbox_is_replaced_and_retained }, { assertion: assert_a_held_inbox_another_profile_advertises_is_replaced }, { assertion: assert_an_inbox_adopted_again_leaves_the_retained_list }, { assertion: assert_a_held_inbox_is_kept_when_none_is_advertised }, { assertion: assert_a_held_inbox_is_kept_when_the_host_names_none }, { assertion: assert_a_held_inbox_is_kept_when_the_host_names_another }, { assertion: assert_a_held_inbox_reached_through_another_link_is_kept }, // Ensuring again changes nothing, and retains nothing more. { action: action_ensure_inboxes }, { assertion: assert_an_inbox_is_created_when_none_is_advertised }, { assertion: assert_the_named_inbox_is_adopted }, { assertion: assert_another_advertised_inbox_is_left_as_it_was }, { assertion: assert_the_deciding_profile_is_followed_past_an_earlier_one, }, { assertion: assert_an_unvetted_advertisement_leaves_home_without_an_inbox, }, { assertion: assert_an_inbox_the_named_profile_does_not_advertise_is_not_adopted, }, { assertion: assert_an_inbox_named_by_a_profile_outside_the_list_is_not_adopted, }, { assertion: assert_an_unnamed_profile_is_taken_as_the_first_advertising_one, }, { assertion: assert_a_held_inbox_is_replaced_and_retained }, { assertion: assert_a_held_inbox_another_profile_advertises_is_replaced }, { assertion: assert_an_inbox_adopted_again_leaves_the_retained_list }, { assertion: assert_a_held_inbox_is_kept_when_none_is_advertised }, { assertion: assert_a_held_inbox_is_kept_when_the_host_names_none }, { assertion: assert_a_held_inbox_is_kept_when_the_host_names_another }, { assertion: assert_a_held_inbox_reached_through_another_link_is_kept }, { action: action_seed_after_adoption }, { assertion: assert_a_new_profile_is_pointed_at_the_adopted_inbox }, { action: action_advertise_refused_inboxes }, { action: action_send_refusals }, { assertion: assert_a_refusal_is_recorded_with_its_reason_and_inbox }, { assertion: assert_a_refusal_is_recorded_beside_a_held_inbox }, { assertion: assert_a_refusal_of_an_inbox_the_named_profile_does_not_advertise_is_not_recorded, }, { assertion: assert_a_refusal_named_by_a_profile_outside_the_list_is_not_recorded, }, { assertion: assert_a_refusal_naming_no_profile_is_not_recorded }, { assertion: assert_an_event_naming_no_refusal_records_none }, { assertion: assert_a_long_refusal_code_is_trimmed_and_cut }, { assertion: assert_a_repeat_of_the_recorded_refusal_keeps_its_time }, { assertion: assert_a_refusal_of_another_inbox_takes_a_new_time }, { assertion: assert_a_refusal_and_its_inbox_are_recorded_before_the_pointers_move, }, { action: action_move_refused_pointers }, { action: action_send_after_the_refusals }, { assertion: assert_a_repeated_refusal_replaces_the_one_recorded }, { assertion: assert_a_refusal_is_cleared_when_the_deciding_profile_points_at_the_held_inbox, }, { assertion: assert_a_refusal_is_cleared_when_home_adopts_an_inbox }, { assertion: assert_a_refusal_is_cleared_when_no_profile_points_at_the_refused_inbox, }, { assertion: assert_a_refusal_is_kept_while_another_profile_points_at_the_refused_inbox, }, { assertion: assert_a_stale_refusal_clears_one_no_profile_points_at }, { assertion: assert_a_refusal_a_later_profile_still_points_at_is_kept, }, { assertion: assert_a_refusal_is_cleared_when_a_later_deciding_profile_points_at_the_held_inbox, }, { assertion: assert_a_new_reason_for_the_recorded_inbox_takes_a_new_time, }, { action: action_refuse_the_held_inbox }, { assertion: assert_a_refusal_of_the_held_inbox_is_not_recorded }, { action: action_advertise_the_inbox_to_replace }, { action: action_replace_the_refused_inbox }, { assertion: assert_the_profiles_pointing_at_the_refused_inbox_point_at_home_inbox, }, { assertion: assert_replacing_leaves_profiles_pointing_elsewhere_or_nowhere, }, { assertion: assert_replacing_clears_the_refusal_and_records_it }, { assertion: assert_replacing_with_no_refusal_does_nothing }, { action: action_point_back_at_the_replaced_inbox }, { action: action_repoint_again }, { assertion: assert_the_profiles_pointing_at_the_refused_inbox_point_at_home_inbox, }, { assertion: assert_replacing_with_no_refusal_does_nothing }, ], }; });