diff --git a/src/relay.ts b/src/relay.ts index edda73d..d3dfe90 100644 --- a/src/relay.ts +++ b/src/relay.ts @@ -340,7 +340,10 @@ export interface RelayActorOptions extends RelayOptions { nextLocalOid?: Oid; } -export function spawnRelay(t: Turn, options: RelayActorOptions): Promise { +export function spawnRelay(t: Turn, options: RelayActorOptions & {initialOid: Oid}): Promise; +export function spawnRelay(t: Turn, options: Omit): Promise; +export function spawnRelay(t: Turn, options: RelayActorOptions): Promise +{ return new Promise(resolve => { t.spawn(t => { const relay = new Relay(t, options); diff --git a/src/sandbox.ts b/src/sandbox.ts index 6825430..ab76a15 100644 --- a/src/sandbox.ts +++ b/src/sandbox.ts @@ -1,9 +1,13 @@ -import { Actor, Ref, Turn } from "./actor.js"; +import { Actor, Assertion, Ref, Turn } from "./actor.js"; import { Relay, spawnRelay } from "./relay.js"; +import { sturdyDecode } from "./sturdy.js"; +import { Observe } from "./dataspace.js"; import * as net from 'net'; +import { Bytes } from "preserves"; -const [ moduleName ] = process.argv.slice(2); +const [ moduleName, hexCap ] = process.argv.slice(2); +const cap = sturdyDecode(Bytes.fromHex(hexCap ?? '')); const socket = net.createConnection({ port: 5999, host: 'localhost' }, () => { Turn.for(new Actor(), t => { @@ -23,9 +27,13 @@ const socket = net.createConnection({ port: 5999, host: 'localhost' }, () => { }, initialOid: 0, // debug: true, - }).then(ds => import(moduleName).then(m => t.freshen(t => { + }).then(gatekeeper => import(moduleName).then(m => t.freshen(t => { t.assert(shutdownRef, true); - m.default(t, ds); + t.assert(gatekeeper, Observe(cap as Assertion, t.ref({ + assert(t, ds) { + m.default(t, ds); + } + }))); }))); }); }); diff --git a/src/server.ts b/src/server.ts index 0531096..7920438 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,8 +1,28 @@ -import { Actor, Turn } from './actor.js'; -import { Dataspace } from './dataspace.js'; +import { Actor, Handle, Turn } from './actor.js'; +import { Dataspace, Observe } from './dataspace.js'; import { Relay, spawnRelay } from './relay.js'; import * as net from 'net'; +import { Caveat, mint, Or, Rewrite, sturdyEncode, SturdyRef, validate, _Or, _Rewrite } from './sturdy.js'; +import { KEY_LENGTH } from './cryptography.js'; +import { attenuate, Attenuation } from './rewrite.js'; +import { Bytes, IdentityMap } from 'preserves'; + +const secretKey = new Bytes(KEY_LENGTH); +mint('syndicate', secretKey).then(v => { + console.log(v.asPreservesText()); + console.log(sturdyEncode(v).toHex()); +}); + +function internalize(caveatChain: Caveat[][]): Attenuation { + const a: Attenuation = []; + caveatChain.slice().reverse().forEach(cs => a.push(... cs.map(c => { + const alts = c.label === _Rewrite ? [c] : Or()._.alternatives(c); + return alts.map(r => ({ pattern: Rewrite._.pattern(r), template: Rewrite._.template(r) })); + }))); + return a; +} + Turn.for(new Actor(), t => { const ds = t.ref(new Dataspace()); @@ -18,7 +38,28 @@ Turn.for(new Actor(), t => { socket.on('data', data => r.accept(data)); t.actor.atExit(() => socket.destroy()); }, - initialRef: ds, + initialRef: t.ref({ + handleMap: new IdentityMap(), + async assert(t, a, h) { + if (!Observe.isClassOf(a)) return; + const r = Observe._.label(a); + if (!SturdyRef.isClassOf(r)) return; + if (!await validate(r, secretKey)) { + console.warn(`Invalid SturdyRef: ${r.asPreservesText()}`); + return; + } + const attenuated_ds = attenuate( + ds, + ... internalize(SturdyRef._.caveatChain(r))); + t.freshen(t => this.handleMap.set( + h, + t.assert(Observe._.observer(a), attenuated_ds))); + }, + retract(t, h) { + t.retract(this.handleMap.get(h)); + this.handleMap.delete(h); + } + }), // debug: true, }); } diff --git a/src/sturdy.ts b/src/sturdy.ts index 73b9659..6bdc133 100644 --- a/src/sturdy.ts +++ b/src/sturdy.ts @@ -7,10 +7,10 @@ // California: Internet Society, 2014. import { mac } from './cryptography.js'; -import { Bytes, encode, is, Record, Value } from 'preserves'; +import { Bytes, decode, encode, is, Record, Value } from 'preserves'; import type { Pattern, Template } from './rewrite.js'; -export type EmbeddedRef = { ref: SturdyRef }; +export type EmbeddedRef = never; export type SturdyValue = Value; export const _SturdyRef = Symbol.for('sturdyref'); @@ -44,7 +44,14 @@ export function sturdyEncode(v: SturdyValue): Bytes { return encode(v, { canonical: true, includeAnnotations: false, - encodePointer(v) { return v }, + encodePointer() { throw new Error("EmbeddedRef not permitted in SturdyRef"); }, + }); +} + +export function sturdyDecode(bs: Bytes): SturdyValue { + return decode(bs, { + includeAnnotations: false, + decodePointer() { throw new Error("EmbeddedRef not permitted in SturdyRef"); }, }); }