Introduce coValue nicknames and change how agentIDs work
This commit is contained in:
@@ -10,7 +10,7 @@ import { LocalNode } from "./node";
|
||||
import { sign } from "./crypto";
|
||||
|
||||
test("Can create coValue with new agent credentials and add transaction to it", () => {
|
||||
const agentCredential = newRandomAgentCredential();
|
||||
const agentCredential = newRandomAgentCredential("agent1");
|
||||
const node = new LocalNode(
|
||||
agentCredential,
|
||||
newRandomSessionID(getAgentID(getAgent(agentCredential)))
|
||||
@@ -48,9 +48,8 @@ test("Can create coValue with new agent credentials and add transaction to it",
|
||||
});
|
||||
|
||||
test("transactions with wrong signature are rejected", () => {
|
||||
const agent = newRandomAgentCredential();
|
||||
const wrongAgent = newRandomAgentCredential();
|
||||
const agentCredential = newRandomAgentCredential();
|
||||
const wrongAgent = newRandomAgentCredential("wrongAgent");
|
||||
const agentCredential = newRandomAgentCredential("agent1");
|
||||
const node = new LocalNode(
|
||||
agentCredential,
|
||||
newRandomSessionID(getAgentID(getAgent(agentCredential)))
|
||||
@@ -88,8 +87,7 @@ test("transactions with wrong signature are rejected", () => {
|
||||
});
|
||||
|
||||
test("transactions with correctly signed, but wrong hash are rejected", () => {
|
||||
const agent = newRandomAgentCredential();
|
||||
const agentCredential = newRandomAgentCredential();
|
||||
const agentCredential = newRandomAgentCredential("agent1");
|
||||
const node = new LocalNode(
|
||||
agentCredential,
|
||||
newRandomSessionID(getAgentID(getAgent(agentCredential)))
|
||||
@@ -131,7 +129,7 @@ test("transactions with correctly signed, but wrong hash are rejected", () => {
|
||||
node.ownSessionID,
|
||||
[transaction],
|
||||
expectedNewHash,
|
||||
sign(agent.signatorySecret, expectedNewHash)
|
||||
sign(agentCredential.signatorySecret, expectedNewHash)
|
||||
)
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
@@ -33,27 +33,32 @@ import {
|
||||
import { LocalNode } from "./node";
|
||||
import { CoValueKnownState, NewContentMessage } from "./sync";
|
||||
|
||||
export type RawCoValueID = `coval_${string}`;
|
||||
export type RawCoValueID = `co_z${string}` | `co_${string}_z${string}`;
|
||||
|
||||
export type CoValueHeader = {
|
||||
type: ContentType["type"];
|
||||
ruleset: RulesetDef;
|
||||
meta: JsonValue;
|
||||
publicNickname?: string;
|
||||
};
|
||||
|
||||
function coValueIDforHeader(header: CoValueHeader): RawCoValueID {
|
||||
const hash = shortHash(header);
|
||||
return `coval_${hash.slice("shortHash_".length)}`;
|
||||
if (header.publicNickname) {
|
||||
return `co_${header.publicNickname}_z${hash.slice("shortHash_z".length)}`;
|
||||
} else {
|
||||
return `co_z${hash.slice("shortHash_z".length)}`;
|
||||
}
|
||||
}
|
||||
|
||||
export type SessionID = `session_${string}_${AgentID}`;
|
||||
export type SessionID = `${AgentID}_session_z${string}`;
|
||||
|
||||
export function agentIDfromSessionID(sessionID: SessionID): AgentID {
|
||||
return `agent_${sessionID.substring(sessionID.lastIndexOf("_") + 1)}`;
|
||||
return sessionID.split("_session")[0] as AgentID;
|
||||
}
|
||||
|
||||
export function newRandomSessionID(agentID: AgentID): SessionID {
|
||||
return `session_${base58.encode(randomBytes(8))}_${agentID}`;
|
||||
return `${agentID}_session_z${base58.encode(randomBytes(8))}`;
|
||||
}
|
||||
|
||||
type SessionLog = {
|
||||
@@ -482,25 +487,26 @@ export class CoValue {
|
||||
return this.header.ruleset.type === "team"
|
||||
? expectTeamContent(this.getCurrentContent())
|
||||
.keys()
|
||||
.filter((k): k is AgentID => k.startsWith("agent_"))
|
||||
.map((agent) => agentIDAsCoValueID(agent))
|
||||
.filter((k): k is AgentID => k.startsWith("co_agent"))
|
||||
: this.header.ruleset.type === "ownedByTeam"
|
||||
? [this.header.ruleset.team]
|
||||
: [];
|
||||
}
|
||||
}
|
||||
|
||||
export type AgentID = `agent_${string}`;
|
||||
export type AgentID = `co_agent${string}_z${string}`;
|
||||
|
||||
export type Agent = {
|
||||
signatoryID: SignatoryID;
|
||||
recipientID: RecipientID;
|
||||
publicNickname?: string;
|
||||
};
|
||||
|
||||
export function getAgent(agentCredential: AgentCredential) {
|
||||
return {
|
||||
signatoryID: getSignatoryID(agentCredential.signatorySecret),
|
||||
recipientID: getRecipientID(agentCredential.recipientSecret),
|
||||
publicNickname: agentCredential.publicNickname,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -513,28 +519,24 @@ export function getAgentCoValueHeader(agent: Agent): CoValueHeader {
|
||||
initialRecipientID: agent.recipientID,
|
||||
},
|
||||
meta: null,
|
||||
publicNickname: "agent" + agent.publicNickname?.slice(0, 1).toUpperCase() + agent.publicNickname?.slice(1),
|
||||
};
|
||||
}
|
||||
|
||||
export function getAgentID(agent: Agent): AgentID {
|
||||
return `agent_${coValueIDforHeader(getAgentCoValueHeader(agent)).slice(
|
||||
"coval_".length
|
||||
)}`;
|
||||
}
|
||||
|
||||
export function agentIDAsCoValueID(agentID: AgentID): RawCoValueID {
|
||||
return `coval_${agentID.substring("agent_".length)}`;
|
||||
return coValueIDforHeader(getAgentCoValueHeader(agent)) as AgentID;
|
||||
}
|
||||
|
||||
export type AgentCredential = {
|
||||
signatorySecret: SignatorySecret;
|
||||
recipientSecret: RecipientSecret;
|
||||
publicNickname?: string;
|
||||
};
|
||||
|
||||
export function newRandomAgentCredential(): AgentCredential {
|
||||
export function newRandomAgentCredential(publicNickname: string): AgentCredential {
|
||||
const signatorySecret = newRandomSignatory();
|
||||
const recipientSecret = newRandomRecipient();
|
||||
return { signatorySecret, recipientSecret };
|
||||
return { signatorySecret, recipientSecret, publicNickname };
|
||||
}
|
||||
|
||||
// type Role = "admin" | "writer" | "reader";
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
import { LocalNode } from "./node";
|
||||
|
||||
test("Empty COJSON Map works", () => {
|
||||
const agentCredential = newRandomAgentCredential();
|
||||
const agentCredential = newRandomAgentCredential("agent1");
|
||||
const node = new LocalNode(
|
||||
agentCredential,
|
||||
newRandomSessionID(getAgentID(getAgent(agentCredential)))
|
||||
@@ -32,7 +32,7 @@ test("Empty COJSON Map works", () => {
|
||||
});
|
||||
|
||||
test("Can insert and delete Map entries in edit()", () => {
|
||||
const agentCredential = newRandomAgentCredential();
|
||||
const agentCredential = newRandomAgentCredential("agent1");
|
||||
const node = new LocalNode(
|
||||
agentCredential,
|
||||
newRandomSessionID(getAgentID(getAgent(agentCredential)))
|
||||
@@ -64,7 +64,7 @@ test("Can insert and delete Map entries in edit()", () => {
|
||||
});
|
||||
|
||||
test("Can get map entry values at different points in time", () => {
|
||||
const agentCredential = newRandomAgentCredential();
|
||||
const agentCredential = newRandomAgentCredential("agent1");
|
||||
const node = new LocalNode(
|
||||
agentCredential,
|
||||
newRandomSessionID(getAgentID(getAgent(agentCredential)))
|
||||
@@ -103,7 +103,7 @@ test("Can get map entry values at different points in time", () => {
|
||||
});
|
||||
|
||||
test("Can get all historic values of key", () => {
|
||||
const agentCredential = newRandomAgentCredential();
|
||||
const agentCredential = newRandomAgentCredential("agent1");
|
||||
const node = new LocalNode(
|
||||
agentCredential,
|
||||
newRandomSessionID(getAgentID(getAgent(agentCredential)))
|
||||
@@ -160,7 +160,7 @@ test("Can get all historic values of key", () => {
|
||||
});
|
||||
|
||||
test("Can get last tx ID for a key", () => {
|
||||
const agentCredential = newRandomAgentCredential();
|
||||
const agentCredential = newRandomAgentCredential("agent1");
|
||||
const node = new LocalNode(
|
||||
agentCredential,
|
||||
newRandomSessionID(getAgentID(getAgent(agentCredential)))
|
||||
|
||||
@@ -49,8 +49,8 @@ test("Sealing round-trips, but invalid receiver can't unseal", () => {
|
||||
const recipient3 = newRandomRecipient();
|
||||
|
||||
const nOnceMaterial = {
|
||||
in: "coval_zTEST",
|
||||
tx: { sessionID: "session_zTEST_agent_zTEST", txIndex: 0 },
|
||||
in: "co_zTEST",
|
||||
tx: { sessionID: "co_agent_zTEST_session_zTEST", txIndex: 0 },
|
||||
} as const;
|
||||
|
||||
const sealed = seal(
|
||||
@@ -106,23 +106,23 @@ test("Encryption for transactions round-trips", () => {
|
||||
const { secret } = newRandomKeySecret();
|
||||
|
||||
const encrypted1 = encryptForTransaction({ a: "hello" }, secret, {
|
||||
in: "coval_zTEST",
|
||||
tx: { sessionID: "session_zTEST_agent_zTEST", txIndex: 0 },
|
||||
in: "co_zTEST",
|
||||
tx: { sessionID: "co_agent_zTEST_session_zTEST", txIndex: 0 },
|
||||
});
|
||||
|
||||
const encrypted2 = encryptForTransaction({ b: "world" }, secret, {
|
||||
in: "coval_zTEST",
|
||||
tx: { sessionID: "session_zTEST_agent_zTEST", txIndex: 1 },
|
||||
in: "co_zTEST",
|
||||
tx: { sessionID: "co_agent_zTEST_session_zTEST", txIndex: 1 },
|
||||
});
|
||||
|
||||
const decrypted1 = decryptForTransaction(encrypted1, secret, {
|
||||
in: "coval_zTEST",
|
||||
tx: { sessionID: "session_zTEST_agent_zTEST", txIndex: 0 },
|
||||
in: "co_zTEST",
|
||||
tx: { sessionID: "co_agent_zTEST_session_zTEST", txIndex: 0 },
|
||||
});
|
||||
|
||||
const decrypted2 = decryptForTransaction(encrypted2, secret, {
|
||||
in: "coval_zTEST",
|
||||
tx: { sessionID: "session_zTEST_agent_zTEST", txIndex: 1 },
|
||||
in: "co_zTEST",
|
||||
tx: { sessionID: "co_agent_zTEST_session_zTEST", txIndex: 1 },
|
||||
});
|
||||
|
||||
expect([decrypted1, decrypted2]).toEqual([{ a: "hello" }, { b: "world" }]);
|
||||
@@ -133,23 +133,23 @@ test("Encryption for transactions doesn't decrypt with a wrong key", () => {
|
||||
const { secret: secret2 } = newRandomKeySecret();
|
||||
|
||||
const encrypted1 = encryptForTransaction({ a: "hello" }, secret, {
|
||||
in: "coval_zTEST",
|
||||
tx: { sessionID: "session_zTEST_agent_zTEST", txIndex: 0 },
|
||||
in: "co_zTEST",
|
||||
tx: { sessionID: "co_agent_zTEST_session_zTEST", txIndex: 0 },
|
||||
});
|
||||
|
||||
const encrypted2 = encryptForTransaction({ b: "world" }, secret, {
|
||||
in: "coval_zTEST",
|
||||
tx: { sessionID: "session_zTEST_agent_zTEST", txIndex: 1 },
|
||||
in: "co_zTEST",
|
||||
tx: { sessionID: "co_agent_zTEST_session_zTEST", txIndex: 1 },
|
||||
});
|
||||
|
||||
const decrypted1 = decryptForTransaction(encrypted1, secret2, {
|
||||
in: "coval_zTEST",
|
||||
tx: { sessionID: "session_zTEST_agent_zTEST", txIndex: 0 },
|
||||
in: "co_zTEST",
|
||||
tx: { sessionID: "co_agent_zTEST_session_zTEST", txIndex: 0 },
|
||||
});
|
||||
|
||||
const decrypted2 = decryptForTransaction(encrypted2, secret2, {
|
||||
in: "coval_zTEST",
|
||||
tx: { sessionID: "session_zTEST_agent_zTEST", txIndex: 1 },
|
||||
in: "co_zTEST",
|
||||
tx: { sessionID: "co_agent_zTEST_session_zTEST", txIndex: 1 },
|
||||
});
|
||||
|
||||
expect([decrypted1, decrypted2]).toEqual([undefined, undefined]);
|
||||
|
||||
@@ -89,6 +89,7 @@ export class LocalNode {
|
||||
type: "comap",
|
||||
ruleset: { type: "team", initialAdmin: this.agentID },
|
||||
meta: null,
|
||||
publicNickname: "team",
|
||||
});
|
||||
|
||||
let teamContent = expectTeamContent(teamCoValue.getCurrentContent());
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
function teamWithTwoAdmins() {
|
||||
const { team, admin, adminID } = newTeam();
|
||||
|
||||
const otherAdmin = newRandomAgentCredential();
|
||||
const otherAdmin = newRandomAgentCredential("otherAdmin");
|
||||
const otherAdminID = getAgentID(getAgent(otherAdmin));
|
||||
|
||||
let content = expectTeamContent(team.getCurrentContent());
|
||||
@@ -38,7 +38,7 @@ function teamWithTwoAdmins() {
|
||||
}
|
||||
|
||||
function newTeam() {
|
||||
const admin = newRandomAgentCredential();
|
||||
const admin = newRandomAgentCredential("admin");
|
||||
const adminID = getAgentID(getAgent(admin));
|
||||
|
||||
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
||||
@@ -47,6 +47,7 @@ function newTeam() {
|
||||
type: "comap",
|
||||
ruleset: { type: "team", initialAdmin: adminID },
|
||||
meta: null,
|
||||
publicNickname: "team"
|
||||
});
|
||||
|
||||
const teamContent = expectTeamContent(team.getCurrentContent());
|
||||
@@ -64,7 +65,7 @@ test("Initial admin can add another admin to a team", () => {
|
||||
});
|
||||
|
||||
function newTeamHighLevel() {
|
||||
const admin = newRandomAgentCredential();
|
||||
const admin = newRandomAgentCredential("admin");
|
||||
const adminID = getAgentID(getAgent(admin));
|
||||
|
||||
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
||||
@@ -77,7 +78,7 @@ function newTeamHighLevel() {
|
||||
function teamWithTwoAdminsHighLevel() {
|
||||
const { admin, adminID, node, team } = newTeamHighLevel();
|
||||
|
||||
const otherAdmin = newRandomAgentCredential();
|
||||
const otherAdmin = newRandomAgentCredential("otherAdmin");
|
||||
const otherAdminID = getAgentID(getAgent(otherAdmin));
|
||||
|
||||
node.addKnownAgent(getAgent(otherAdmin));
|
||||
@@ -103,7 +104,7 @@ test("Added admin can add a third admin to a team", () => {
|
||||
|
||||
expect(otherContent.get(otherAdminID)).toEqual("admin");
|
||||
|
||||
const thirdAdmin = newRandomAgentCredential();
|
||||
const thirdAdmin = newRandomAgentCredential("admin");
|
||||
const thirdAdminID = getAgentID(getAgent(thirdAdmin));
|
||||
|
||||
otherContent.edit((editable) => {
|
||||
@@ -125,7 +126,7 @@ test("Added adming can add a third admin to a team (high level)", () => {
|
||||
newRandomSessionID(otherAdminID)
|
||||
);
|
||||
|
||||
const thirdAdmin = newRandomAgentCredential();
|
||||
const thirdAdmin = newRandomAgentCredential("admin");
|
||||
const thirdAdminID = getAgentID(getAgent(thirdAdmin));
|
||||
|
||||
node.addKnownAgent(getAgent(thirdAdmin));
|
||||
@@ -187,7 +188,7 @@ test("Admins can't demote other admins in a team (high level)", () => {
|
||||
|
||||
test("Admins an add writers to a team, who can't add admins, writers, or readers", () => {
|
||||
const { team } = newTeam();
|
||||
const writer = newRandomAgentCredential();
|
||||
const writer = newRandomAgentCredential("writer");
|
||||
const writerID = getAgentID(getAgent(writer));
|
||||
|
||||
let teamContent = expectTeamContent(team.getCurrentContent());
|
||||
@@ -211,7 +212,7 @@ test("Admins an add writers to a team, who can't add admins, writers, or readers
|
||||
|
||||
expect(teamContentAsWriter.get(writerID)).toEqual("writer");
|
||||
|
||||
const otherAgent = newRandomAgentCredential();
|
||||
const otherAgent = newRandomAgentCredential("otherAgent");
|
||||
const otherAgentID = getAgentID(getAgent(otherAgent));
|
||||
|
||||
teamContentAsWriter.edit((editable) => {
|
||||
@@ -233,7 +234,7 @@ test("Admins an add writers to a team, who can't add admins, writers, or readers
|
||||
test("Admins an add writers to a team, who can't add admins, writers, or readers (high level)", () => {
|
||||
const { team, node } = newTeamHighLevel();
|
||||
|
||||
const writer = newRandomAgentCredential();
|
||||
const writer = newRandomAgentCredential("writer");
|
||||
const writerID = getAgentID(getAgent(writer));
|
||||
|
||||
node.addKnownAgent(getAgent(writer));
|
||||
@@ -248,7 +249,7 @@ test("Admins an add writers to a team, who can't add admins, writers, or readers
|
||||
|
||||
expect(teamAsWriter.teamMap.get(writerID)).toEqual("writer");
|
||||
|
||||
const otherAgent = newRandomAgentCredential();
|
||||
const otherAgent = newRandomAgentCredential("otherAgent");
|
||||
const otherAgentID = getAgentID(getAgent(otherAgent));
|
||||
|
||||
node.addKnownAgent(getAgent(otherAgent));
|
||||
@@ -268,7 +269,7 @@ test("Admins an add writers to a team, who can't add admins, writers, or readers
|
||||
|
||||
test("Admins can add readers to a team, who can't add admins, writers, or readers", () => {
|
||||
const { team } = newTeam();
|
||||
const reader = newRandomAgentCredential();
|
||||
const reader = newRandomAgentCredential("reader");
|
||||
const readerID = getAgentID(getAgent(reader));
|
||||
|
||||
let teamContent = expectTeamContent(team.getCurrentContent());
|
||||
@@ -292,7 +293,7 @@ test("Admins can add readers to a team, who can't add admins, writers, or reader
|
||||
|
||||
expect(teamContentAsReader.get(readerID)).toEqual("reader");
|
||||
|
||||
const otherAgent = newRandomAgentCredential();
|
||||
const otherAgent = newRandomAgentCredential("otherAgent");
|
||||
const otherAgentID = getAgentID(getAgent(otherAgent));
|
||||
|
||||
teamContentAsReader.edit((editable) => {
|
||||
@@ -314,7 +315,7 @@ test("Admins can add readers to a team, who can't add admins, writers, or reader
|
||||
test("Admins can add readers to a team, who can't add admins, writers, or readers (high level)", () => {
|
||||
const { team, node } = newTeamHighLevel();
|
||||
|
||||
const reader = newRandomAgentCredential();
|
||||
const reader = newRandomAgentCredential("reader");
|
||||
const readerID = getAgentID(getAgent(reader));
|
||||
|
||||
node.addKnownAgent(getAgent(reader));
|
||||
@@ -329,7 +330,7 @@ test("Admins can add readers to a team, who can't add admins, writers, or reader
|
||||
|
||||
expect(teamAsReader.teamMap.get(readerID)).toEqual("reader");
|
||||
|
||||
const otherAgent = newRandomAgentCredential();
|
||||
const otherAgent = newRandomAgentCredential("otherAgent");
|
||||
const otherAgentID = getAgentID(getAgent(otherAgent));
|
||||
|
||||
node.addKnownAgent(getAgent(otherAgent));
|
||||
@@ -354,6 +355,7 @@ test("Admins can write to an object that is owned by their team", () => {
|
||||
type: "comap",
|
||||
ruleset: { type: "ownedByTeam", team: team.id },
|
||||
meta: null,
|
||||
publicNickname: "childObject"
|
||||
});
|
||||
|
||||
let childContent = expectMap(childObject.getCurrentContent());
|
||||
@@ -384,7 +386,7 @@ test("Admins can write to an object that is owned by their team (high level)", (
|
||||
test("Writers can write to an object that is owned by their team", () => {
|
||||
const { node, team } = newTeam();
|
||||
|
||||
const writer = newRandomAgentCredential();
|
||||
const writer = newRandomAgentCredential("writer");
|
||||
const writerID = getAgentID(getAgent(writer));
|
||||
|
||||
expectTeamContent(team.getCurrentContent()).edit((editable) => {
|
||||
@@ -396,6 +398,7 @@ test("Writers can write to an object that is owned by their team", () => {
|
||||
type: "comap",
|
||||
ruleset: { type: "ownedByTeam", team: team.id },
|
||||
meta: null,
|
||||
publicNickname: "childObject"
|
||||
});
|
||||
|
||||
const childObjectAsWriter = childObject.testWithDifferentCredentials(
|
||||
@@ -420,7 +423,7 @@ test("Writers can write to an object that is owned by their team", () => {
|
||||
test("Writers can write to an object that is owned by their team (high level)", () => {
|
||||
const { node, team } = newTeamHighLevel();
|
||||
|
||||
const writer = newRandomAgentCredential();
|
||||
const writer = newRandomAgentCredential("writer");
|
||||
const writerID = getAgentID(getAgent(writer));
|
||||
|
||||
node.addKnownAgent(getAgent(writer));
|
||||
@@ -446,7 +449,7 @@ test("Writers can write to an object that is owned by their team (high level)",
|
||||
test("Readers can not write to an object that is owned by their team", () => {
|
||||
const { node, team } = newTeam();
|
||||
|
||||
const reader = newRandomAgentCredential();
|
||||
const reader = newRandomAgentCredential("reader");
|
||||
const readerID = getAgentID(getAgent(reader));
|
||||
|
||||
expectTeamContent(team.getCurrentContent()).edit((editable) => {
|
||||
@@ -458,6 +461,7 @@ test("Readers can not write to an object that is owned by their team", () => {
|
||||
type: "comap",
|
||||
ruleset: { type: "ownedByTeam", team: team.id },
|
||||
meta: null,
|
||||
publicNickname: "childObject"
|
||||
});
|
||||
|
||||
const childObjectAsReader = childObject.testWithDifferentCredentials(
|
||||
@@ -482,7 +486,7 @@ test("Readers can not write to an object that is owned by their team", () => {
|
||||
test("Readers can not write to an object that is owned by their team (high level)", () => {
|
||||
const { node, team } = newTeamHighLevel();
|
||||
|
||||
const reader = newRandomAgentCredential();
|
||||
const reader = newRandomAgentCredential("reader");
|
||||
const readerID = getAgentID(getAgent(reader));
|
||||
|
||||
node.addKnownAgent(getAgent(reader));
|
||||
@@ -533,6 +537,7 @@ test("Admins can set team read key and then use it to create and read private tr
|
||||
type: "comap",
|
||||
ruleset: { type: "ownedByTeam", team: team.id },
|
||||
meta: null,
|
||||
publicNickname: "childObject"
|
||||
});
|
||||
|
||||
let childContent = expectMap(childObject.getCurrentContent());
|
||||
@@ -562,7 +567,7 @@ test("Admins can set team read key and then use it to create and read private tr
|
||||
test("Admins can set team read key and then writers can use it to create and read private transactions in owned objects", () => {
|
||||
const { node, team, admin } = newTeam();
|
||||
|
||||
const writer = newRandomAgentCredential();
|
||||
const writer = newRandomAgentCredential("writer");
|
||||
const writerID = getAgentID(getAgent(writer));
|
||||
const { secret: readKey, id: readKeyID } = newRandomKeySecret();
|
||||
|
||||
@@ -591,6 +596,7 @@ test("Admins can set team read key and then writers can use it to create and rea
|
||||
type: "comap",
|
||||
ruleset: { type: "ownedByTeam", team: team.id },
|
||||
meta: null,
|
||||
publicNickname: "childObject"
|
||||
});
|
||||
|
||||
const childObjectAsWriter = childObject.testWithDifferentCredentials(
|
||||
@@ -617,7 +623,7 @@ test("Admins can set team read key and then writers can use it to create and rea
|
||||
test("Admins can set team read key and then writers can use it to create and read private transactions in owned objects (high level)", () => {
|
||||
const { node, team, admin } = newTeamHighLevel();
|
||||
|
||||
const writer = newRandomAgentCredential();
|
||||
const writer = newRandomAgentCredential("writer");
|
||||
const writerID = getAgentID(getAgent(writer));
|
||||
|
||||
node.addKnownAgent(getAgent(writer));
|
||||
@@ -643,7 +649,7 @@ test("Admins can set team read key and then writers can use it to create and rea
|
||||
test("Admins can set team read key and then use it to create private transactions in owned objects, which readers can read", () => {
|
||||
const { node, team, admin } = newTeam();
|
||||
|
||||
const reader = newRandomAgentCredential();
|
||||
const reader = newRandomAgentCredential("reader");
|
||||
const readerID = getAgentID(getAgent(reader));
|
||||
const { secret: readKey, id: readKeyID } = newRandomKeySecret();
|
||||
|
||||
@@ -672,6 +678,7 @@ test("Admins can set team read key and then use it to create private transaction
|
||||
type: "comap",
|
||||
ruleset: { type: "ownedByTeam", team: team.id },
|
||||
meta: null,
|
||||
publicNickname: "childObject"
|
||||
});
|
||||
|
||||
expectMap(childObject.getCurrentContent()).edit((editable) => {
|
||||
@@ -696,7 +703,7 @@ test("Admins can set team read key and then use it to create private transaction
|
||||
test("Admins can set team read key and then use it to create private transactions in owned objects, which readers can read (high level)", () => {
|
||||
const { node, team, admin } = newTeamHighLevel();
|
||||
|
||||
const reader = newRandomAgentCredential();
|
||||
const reader = newRandomAgentCredential("reader");
|
||||
const readerID = getAgentID(getAgent(reader));
|
||||
|
||||
node.addKnownAgent(getAgent(reader));
|
||||
@@ -722,9 +729,9 @@ test("Admins can set team read key and then use it to create private transaction
|
||||
test("Admins can set team read key and then use it to create private transactions in owned objects, which readers can read, even with a separate later revelation for the same read key", () => {
|
||||
const { node, team, admin } = newTeam();
|
||||
|
||||
const reader1 = newRandomAgentCredential();
|
||||
const reader1 = newRandomAgentCredential("reader1");
|
||||
const reader1ID = getAgentID(getAgent(reader1));
|
||||
const reader2 = newRandomAgentCredential();
|
||||
const reader2 = newRandomAgentCredential("reader2");
|
||||
const reader2ID = getAgentID(getAgent(reader2));
|
||||
const { secret: readKey, id: readKeyID } = newRandomKeySecret();
|
||||
|
||||
@@ -772,6 +779,7 @@ test("Admins can set team read key and then use it to create private transaction
|
||||
type: "comap",
|
||||
ruleset: { type: "ownedByTeam", team: team.id },
|
||||
meta: null,
|
||||
publicNickname: "childObject"
|
||||
});
|
||||
|
||||
expectMap(childObject.getCurrentContent()).edit((editable) => {
|
||||
@@ -809,9 +817,9 @@ test("Admins can set team read key and then use it to create private transaction
|
||||
test("Admins can set team read key and then use it to create private transactions in owned objects, which readers can read, even with a separate later revelation for the same read key (high level)", () => {
|
||||
const { node, team, admin } = newTeamHighLevel();
|
||||
|
||||
const reader1 = newRandomAgentCredential();
|
||||
const reader1 = newRandomAgentCredential("reader1");
|
||||
const reader1ID = getAgentID(getAgent(reader1));
|
||||
const reader2 = newRandomAgentCredential();
|
||||
const reader2 = newRandomAgentCredential("reader2");
|
||||
const reader2ID = getAgentID(getAgent(reader2));
|
||||
|
||||
node.addKnownAgent(getAgent(reader1));
|
||||
@@ -872,6 +880,7 @@ test("Admins can set team read key, make a private transaction in an owned objec
|
||||
type: "comap",
|
||||
ruleset: { type: "ownedByTeam", team: team.id },
|
||||
meta: null,
|
||||
publicNickname: "childObject"
|
||||
});
|
||||
|
||||
let childContent = expectMap(childObject.getCurrentContent());
|
||||
@@ -951,6 +960,7 @@ test("Admins can set team read key, make a private transaction in an owned objec
|
||||
type: "comap",
|
||||
ruleset: { type: "ownedByTeam", team: team.id },
|
||||
meta: null,
|
||||
publicNickname: "childObject"
|
||||
});
|
||||
|
||||
const teamContent = expectTeamContent(team.getCurrentContent());
|
||||
@@ -984,7 +994,7 @@ test("Admins can set team read key, make a private transaction in an owned objec
|
||||
childContent = expectMap(childObject.getCurrentContent());
|
||||
expect(childContent.get("foo")).toEqual("bar");
|
||||
|
||||
const reader = newRandomAgentCredential();
|
||||
const reader = newRandomAgentCredential("reader");
|
||||
const readerID = getAgentID(getAgent(reader));
|
||||
const { secret: readKey2, id: readKeyID2 } = newRandomKeySecret();
|
||||
|
||||
@@ -1064,7 +1074,7 @@ test("Admins can set team read key, make a private transaction in an owned objec
|
||||
|
||||
expect(childObject.coValue.getCurrentReadKey()).not.toEqual(firstReadKey);
|
||||
|
||||
const reader = newRandomAgentCredential();
|
||||
const reader = newRandomAgentCredential("reader");
|
||||
const readerID = getAgentID(getAgent(reader));
|
||||
|
||||
node.addKnownAgent(getAgent(reader));
|
||||
@@ -1093,13 +1103,14 @@ test("Admins can set team read rey, make a private transaction in an owned objec
|
||||
type: "comap",
|
||||
ruleset: { type: "ownedByTeam", team: team.id },
|
||||
meta: null,
|
||||
publicNickname: "childObject"
|
||||
});
|
||||
|
||||
const teamContent = expectTeamContent(team.getCurrentContent());
|
||||
const { secret: readKey, id: readKeyID } = newRandomKeySecret();
|
||||
const reader = newRandomAgentCredential();
|
||||
const reader = newRandomAgentCredential("reader");
|
||||
const readerID = getAgentID(getAgent(reader));
|
||||
const reader2 = newRandomAgentCredential();
|
||||
const reader2 = newRandomAgentCredential("reader2");
|
||||
const reader2ID = getAgentID(getAgent(reader));
|
||||
|
||||
teamContent.edit((editable) => {
|
||||
@@ -1229,9 +1240,9 @@ test("Admins can set team read rey, make a private transaction in an owned objec
|
||||
|
||||
const secondReadKey = childObject.coValue.getCurrentReadKey();
|
||||
|
||||
const reader = newRandomAgentCredential();
|
||||
const reader = newRandomAgentCredential("reader");
|
||||
const readerID = getAgentID(getAgent(reader));
|
||||
const reader2 = newRandomAgentCredential();
|
||||
const reader2 = newRandomAgentCredential("reader2");
|
||||
const reader2ID = getAgentID(getAgent(reader2));
|
||||
|
||||
node.addKnownAgent(getAgent(reader));
|
||||
|
||||
@@ -271,7 +271,7 @@ export class Team {
|
||||
|
||||
rotateReadKey() {
|
||||
const currentlyPermittedReaders = this.teamMap.keys().filter((key) => {
|
||||
if (key.startsWith("agent_")) {
|
||||
if (key.startsWith("co_agent")) {
|
||||
const role = this.teamMap.get(key);
|
||||
return (
|
||||
role === "admin" || role === "writer" || role === "reader"
|
||||
@@ -342,6 +342,7 @@ export class Team {
|
||||
team: this.teamMap.id,
|
||||
},
|
||||
meta: meta || null,
|
||||
publicNickname: "map",
|
||||
})
|
||||
.getCurrentContent() as CoMap<M, Meta>;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {
|
||||
AgentID,
|
||||
agentIDAsCoValueID,
|
||||
getAgent,
|
||||
getAgentID,
|
||||
newRandomAgentCredential,
|
||||
@@ -19,7 +18,7 @@ import {
|
||||
test(
|
||||
"Node replies with initial tx and header to empty subscribe",
|
||||
async () => {
|
||||
const admin = newRandomAgentCredential();
|
||||
const admin = newRandomAgentCredential("admin");
|
||||
const adminID = getAgentID(getAgent(admin));
|
||||
|
||||
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
||||
@@ -74,6 +73,7 @@ test(
|
||||
type: "comap",
|
||||
ruleset: { type: "ownedByTeam", team: team.id },
|
||||
meta: null,
|
||||
publicNickname: "map",
|
||||
},
|
||||
newContent: {
|
||||
[node.ownSessionID]: {
|
||||
@@ -103,7 +103,7 @@ test(
|
||||
);
|
||||
|
||||
test("Node replies with only new tx to subscribe with some known state", async () => {
|
||||
const admin = newRandomAgentCredential();
|
||||
const admin = newRandomAgentCredential("admin");
|
||||
const adminID = getAgentID(getAgent(admin));
|
||||
|
||||
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
||||
@@ -188,7 +188,7 @@ test.todo(
|
||||
);
|
||||
|
||||
test("After subscribing, node sends own known state and new txs to peer", async () => {
|
||||
const admin = newRandomAgentCredential();
|
||||
const admin = newRandomAgentCredential("admin");
|
||||
const adminID = getAgentID(getAgent(admin));
|
||||
|
||||
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
||||
@@ -309,7 +309,7 @@ test("After subscribing, node sends own known state and new txs to peer", async
|
||||
});
|
||||
|
||||
test("Client replies with known new content to tellKnownState from server", async () => {
|
||||
const admin = newRandomAgentCredential();
|
||||
const admin = newRandomAgentCredential("admin");
|
||||
const adminID = getAgentID(getAgent(admin));
|
||||
|
||||
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
||||
@@ -391,7 +391,7 @@ test("Client replies with known new content to tellKnownState from server", asyn
|
||||
});
|
||||
|
||||
test("No matter the optimistic known state, node respects invalid known state messages and resyncs", async () => {
|
||||
const admin = newRandomAgentCredential();
|
||||
const admin = newRandomAgentCredential("admin");
|
||||
const adminID = getAgentID(getAgent(admin));
|
||||
|
||||
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
||||
@@ -496,7 +496,7 @@ test("No matter the optimistic known state, node respects invalid known state me
|
||||
});
|
||||
|
||||
test("If we add a peer, but it never subscribes to a coValue, it won't get any messages", async () => {
|
||||
const admin = newRandomAgentCredential();
|
||||
const admin = newRandomAgentCredential("admin");
|
||||
const adminID = getAgentID(getAgent(admin));
|
||||
|
||||
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
||||
@@ -525,7 +525,7 @@ test("If we add a peer, but it never subscribes to a coValue, it won't get any m
|
||||
});
|
||||
|
||||
test("If we add a server peer, all updates to all coValues are sent to it, even if it doesn't subscribe", async () => {
|
||||
const admin = newRandomAgentCredential();
|
||||
const admin = newRandomAgentCredential("admin");
|
||||
const adminID = getAgentID(getAgent(admin));
|
||||
|
||||
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
||||
@@ -547,7 +547,7 @@ test("If we add a server peer, all updates to all coValues are sent to it, even
|
||||
const reader = outRx.getReader();
|
||||
expect((await reader.read()).value).toMatchObject({
|
||||
action: "subscribe",
|
||||
coValueID: agentIDAsCoValueID(adminID),
|
||||
coValueID: adminID,
|
||||
});
|
||||
expect((await reader.read()).value).toMatchObject({
|
||||
action: "subscribe",
|
||||
@@ -602,7 +602,7 @@ test("If we add a server peer, all updates to all coValues are sent to it, even
|
||||
});
|
||||
|
||||
test("If we add a server peer, newly created coValues are auto-subscribed to", async () => {
|
||||
const admin = newRandomAgentCredential();
|
||||
const admin = newRandomAgentCredential("admin");
|
||||
const adminID = getAgentID(getAgent(admin));
|
||||
|
||||
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
||||
@@ -624,7 +624,7 @@ test("If we add a server peer, newly created coValues are auto-subscribed to", a
|
||||
const reader = outRx.getReader();
|
||||
expect((await reader.read()).value).toMatchObject({
|
||||
action: "subscribe",
|
||||
coValueID: agentIDAsCoValueID(adminID),
|
||||
coValueID: adminID,
|
||||
});
|
||||
expect((await reader.read()).value).toMatchObject({
|
||||
action: "subscribe",
|
||||
@@ -658,7 +658,7 @@ test.todo(
|
||||
);
|
||||
|
||||
test("When we connect a new server peer, we try to sync all existing coValues to it", async () => {
|
||||
const admin = newRandomAgentCredential();
|
||||
const admin = newRandomAgentCredential("admin");
|
||||
const adminID = getAgentID(getAgent(admin));
|
||||
|
||||
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
||||
@@ -696,7 +696,7 @@ test("When we connect a new server peer, we try to sync all existing coValues to
|
||||
});
|
||||
|
||||
test("When receiving a subscribe with a known state that is ahead of our own, peers should respond with a corresponding subscribe response message", async () => {
|
||||
const admin = newRandomAgentCredential();
|
||||
const admin = newRandomAgentCredential("admin");
|
||||
const adminID = getAgentID(getAgent(admin));
|
||||
|
||||
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
||||
@@ -740,7 +740,7 @@ test("When receiving a subscribe with a known state that is ahead of our own, pe
|
||||
|
||||
test.skip("When replaying creation and transactions of a coValue as new content, the receiving peer integrates this information", async () => {
|
||||
// TODO: this test is mostly correct but also slightly unrealistic, make sure we pass all messages back and forth as expected and then it should work
|
||||
const admin = newRandomAgentCredential();
|
||||
const admin = newRandomAgentCredential("admin");
|
||||
const adminID = getAgentID(getAgent(admin));
|
||||
|
||||
const node1 = new LocalNode(admin, newRandomSessionID(adminID));
|
||||
@@ -778,7 +778,7 @@ test.skip("When replaying creation and transactions of a coValue as new content,
|
||||
const adminSubscribeMessage = await from1.read();
|
||||
expect(adminSubscribeMessage.value).toMatchObject({
|
||||
action: "subscribe",
|
||||
coValueID: agentIDAsCoValueID(adminID),
|
||||
coValueID: adminID,
|
||||
});
|
||||
const teamSubscribeMsg = await from1.read();
|
||||
expect(teamSubscribeMsg.value).toMatchObject({
|
||||
@@ -862,7 +862,7 @@ test.skip("When replaying creation and transactions of a coValue as new content,
|
||||
|
||||
test.skip("When loading a coValue on one node, the server node it is requested from replies with all the necessary depended on coValues to make it work", async () => {
|
||||
// TODO: this test is mostly correct but also slightly unrealistic, make sure we pass all messages back and forth as expected and then it should work
|
||||
const admin = newRandomAgentCredential();
|
||||
const admin = newRandomAgentCredential("admin");
|
||||
const adminID = getAgentID(getAgent(admin));
|
||||
|
||||
const node1 = new LocalNode(admin, newRandomSessionID(adminID));
|
||||
@@ -891,7 +891,7 @@ test.skip("When loading a coValue on one node, the server node it is requested f
|
||||
});
|
||||
|
||||
test("Can sync a coValue through a server to another client", async () => {
|
||||
const admin = newRandomAgentCredential();
|
||||
const admin = newRandomAgentCredential("admin");
|
||||
const adminID = getAgentID(getAgent(admin));
|
||||
|
||||
const client1 = new LocalNode(admin, newRandomSessionID(adminID));
|
||||
@@ -903,7 +903,55 @@ test("Can sync a coValue through a server to another client", async () => {
|
||||
editable.set("hello", "world", "trusting");
|
||||
});
|
||||
|
||||
const server = new LocalNode(admin, newRandomSessionID(adminID));
|
||||
const serverUser = newRandomAgentCredential("serverUser");
|
||||
const serverUserID = getAgentID(getAgent(serverUser));
|
||||
|
||||
const server = new LocalNode(serverUser, newRandomSessionID(serverUserID));
|
||||
|
||||
const [serverAsPeer, client1AsPeer] = connectedPeers("server", "client1", {
|
||||
trace: true,
|
||||
peer1role: "server",
|
||||
peer2role: "client",
|
||||
});
|
||||
|
||||
client1.sync.addPeer(serverAsPeer);
|
||||
server.sync.addPeer(client1AsPeer);
|
||||
|
||||
const client2 = new LocalNode(admin, newRandomSessionID(adminID));
|
||||
|
||||
const [serverAsOtherPeer, client2AsPeer] = connectedPeers(
|
||||
"server",
|
||||
"client2",
|
||||
{ trace: true, peer1role: "server", peer2role: "client" }
|
||||
);
|
||||
|
||||
client2.sync.addPeer(serverAsOtherPeer);
|
||||
server.sync.addPeer(client2AsPeer);
|
||||
|
||||
const mapOnClient2 = await client2.loadCoValue(map.coValue.id);
|
||||
|
||||
expect(expectMap(mapOnClient2.getCurrentContent()).get("hello")).toEqual(
|
||||
"world"
|
||||
);
|
||||
});
|
||||
|
||||
test("Can sync a coValue with private transactions through a server to another client", async () => {
|
||||
const admin = newRandomAgentCredential("admin");
|
||||
const adminID = getAgentID(getAgent(admin));
|
||||
|
||||
const client1 = new LocalNode(admin, newRandomSessionID(adminID));
|
||||
|
||||
const team = client1.createTeam();
|
||||
|
||||
const map = team.createMap();
|
||||
map.edit((editable) => {
|
||||
editable.set("hello", "world", "private");
|
||||
});
|
||||
|
||||
const serverUser = newRandomAgentCredential("serverUser");
|
||||
const serverUserID = getAgentID(getAgent(serverUser));
|
||||
|
||||
const server = new LocalNode(serverUser, newRandomSessionID(serverUserID));
|
||||
|
||||
const [serverAsPeer, client1AsPeer] = connectedPeers("server", "client1", {
|
||||
trace: true,
|
||||
@@ -942,7 +990,7 @@ function teamContentEx(team: Team) {
|
||||
function admContEx(adminID: AgentID) {
|
||||
return {
|
||||
action: "newContent",
|
||||
coValueID: agentIDAsCoValueID(adminID),
|
||||
coValueID: adminID,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -956,7 +1004,7 @@ function teamStateEx(team: Team) {
|
||||
function admStateEx(adminID: AgentID) {
|
||||
return {
|
||||
action: "tellKnownState",
|
||||
coValueID: agentIDAsCoValueID(adminID),
|
||||
coValueID: adminID,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user