⊇ Algebra of Contexts
Spaces inside spaces.
A space is a region of meaning that can contain other spaces. Where it lives, who can read it and what may be done to it are properties of that same space, not three separate systems.
Kernel: this.me 4.2.1 (npm) ⓘ
Theory: Digital Space Algebra. Source map and tests: TypeScript implementation.
One space, four sets
| Set | Says | In the kernel |
|---|---|---|
| P path | which subspace | the path itself: home.kitchen.light |
| A audience | who can read it | a secret scope ["_"], enforced by encryption |
| T topology | where it lives | copies of the space (snapshots, devices); outside the kernel |
| C capability | what is allowed | granted outside the kernel (gateways); never inferred from A |
Not four ontologies: four views of one space.
Space ⊇ subspace
A deeper path is a smaller region. Leaves hold values; a read names a leaf.
import { ME } from "this.me";
const me = new ME() as any;
me.home.kitchen.light("on");
me.home.kitchen.temp(21);
me("home.kitchen.light") // "on"
me("home.kitchen") // undefined (a region, not a leaf)
home.kitchen.light ⊆ home.kitchen ⊆ home
Predicates select subspaces
Public, adult, cheap: adjectives are predicates, and a predicate selects a subspace. Name the field you want after the selector.
me.friends[1].age(17);
me.friends[2].age(34);
me.friends[3].age(21);
me("friends[age > 18].age") // { "2": 34, "3": 21 }
me("friends[1..2].age") // { "1": 17, "2": 34 }
Plurality: x[] and x[].f
[] is grammar, not a data type: it says a space has members. x[] is how many; x[].f sums a field over them.
me("friends[]") // 3
me("friends[].age") // 72
friends[1] ⊆ friends[] ⊆ friends
Anchored and derived shared spaces
A shared space (more than one reader) keeps its identity in one of two ways.
- Anchored: P is chosen once; A moves inside it. Members join and leave, the space stays where it is.
- Derived: P is computed from A itself, P = f(A). Change the members and the address changes; remove one and nothing resolves to the old space.
Anchored is what the kernel does today:
me.groups.family.members[1].name("ana");
me.groups.family.members[2].name("luis");
me("groups.family.members[]") // 2
me.groups.family.members[3].name("sol");
me("groups.family.members[]") // 3
Derived spaces have no kernel primitive. Their address form, surface[a+b] next to the anchored group:name, is set out in NRP Chemistry.
Encryption as membership
A secret scope does not move data to another universe. It narrows the readable audience of a space, here to {self}: the scope’s root does not resolve, its leaves do for the owner, and a guest gets nothing.
me.wallet["_"]("vault-key");
me.wallet.hidden.note("private");
me.wallet.balance(500);
me("wallet") // undefined
me("wallet.hidden.note") // "private"
me.as(null)("wallet.hidden.note"); // undefined (guest)
A value computed from the secret can be public; its secret input stays masked:
me["="]("budget", "wallet.balance * 0.1");
me("budget") // 50
me.explain("budget").derivation.inputs[0]
// { path: "wallet.balance", value: "●●●●", origin: "stealth", masked: true, … }
Shared audiences are union and intersection over real identities: an OR audience opens for any member, an AND audience only for the whole coalition.
A = {me, ana} readable by me ∪ ana
I_AB = I_A ∩ I_B the identities in both
The OR/AND audience algebra is in the 4.2.1 source with its own tests, but it is not exported by the npm 4.2.1 package (TypeScript implementation).
T ⊥ A: copying is not reading
Topology and audience are orthogonal. Copy a space anywhere; the copy is no more readable than the original.
const copy = new ME();
copy.importSnapshot(me.exportSnapshot());
copy("home.kitchen.light") // "on"
copy("wallet.hidden.note") // undefined
copy("wallet") // undefined
The snapshot carries the sealed branch, not its key: the exported JSON contains neither "private" nor "vault-key".
Namespaces: me://
A namespace names a space; a selector says which surface; the path names the subspace.
import { parseMeUri } from "this.me";
parseMeUri("me://suign.neurons.me[macbook]/profile.name");
// { href: "me://suign.neurons.me[surface:macbook]/profile.name",
// namespace: "suign.neurons.me", selector: { kind: "surface", value: "surface:macbook" },
// path: "profile.name" }
parseMeUri("me://suign.neurons.me[]/chat.general");
// { href: "me://suign.neurons.me[]/chat.general", selector: { kind: "fanout" }, path: "chat.general" }
Grammar: me:// URI.
TypeScript implementation
Algebra of Contexts: source and tests: where each part lives in the v4.2.1 source, the tests that prove it, and their results on npm 4.2.1.
See also
- .me Syntax: Dot builds the path, [] selects members, () writes, reads or applies an operator. Names in any language.
- me.whatever(what): me.a.b(value) declares, me("a.b") reads: chaining, indexes, and why me.a.b() is not a read.
- me.explain(path): Why a path has its value: formula, inputs, and the last wave (k, recomputed, changed, sourcePath).
- Axioms: The invariants the kernel guarantees, with runtime proof.
- Digital Space Algebra: The theory: topology, audience and capability as three sets over one space.