diff --git a/zod/seax/app/seax.hoon b/zod/seax/app/seax.hoon
index 707802f..71acb0f 100644
--- a/zod/seax/app/seax.hoon
+++ b/zod/seax/app/seax.hoon
@@ -1,6 +1,6 @@
/- *seax
-/+ dbug, engines, rank, sink
-
+/- diary
+/+ dbug, engines, rank, sink, strandio
|%
+$ query cord
+$ search-state
@@ -10,6 +10,7 @@ $:
==
+$ state-0
$:
+ notes=shelf:diary
search-subscriptions=(map query search-state)
peers=_(silt ~[~zod ~racfer-hattes])
alive-peers=(set @p)
@@ -17,6 +18,7 @@ $:
+$ poke
$%
[%add-peers (set @p)]
+ [%get-notes ~]
==
++ rank-results
|= search-results=(map term (unit (list search-result)))
@@ -88,15 +90,16 @@ $:
state state
==
++ on-poke
- |= [* * pk=*]
+ |= [=mark =vase]
^- (quip card:agent:gall _this)
- =/ poke (poke pk)
+ =/ poke !<(poke vase)
~& poke
?- -.poke
- %add-peers
- [~ this(peers.state (~(put in (~(uni in peers.state) +.poke)) src.bowl))]
+ %add-peers
+ [~ this(peers.state (~(put in (~(uni in peers.state) +.poke)) src.bowl))]
+ %get-notes
+ `this(notes.state .^(shelf:diary %gx /(scot %p our.bowl)/diary/(scot %da now.bowl)/shelf/noun))
==
-
++ on-watch
|= =path
?+ path !!
diff --git a/zod/seax/lib/graph-store.hoon b/zod/seax/lib/graph-store.hoon
new file mode 100644
index 0000000..df11d03
--- /dev/null
+++ b/zod/seax/lib/graph-store.hoon
@@ -0,0 +1,919 @@
+/- sur=graph-store, pos=post, pull-hook, hark=hark-store
+/+ res=resource, migrate
+=< [sur .]
+=< [pos .]
+=, sur
+=, pos
+|%
+++ hark-content
+ |= =content
+ ^- content:hark
+ ?- -.content
+ %text content
+ %mention ship+ship.content
+ %url text+url.content
+ %code text+'A code excerpt'
+ %reference text+'A reference'
+ ==
+::
+++ hark-contents
+ |= cs=(list content)
+ (turn cs hark-content)
+:: NOTE: move these functions to zuse
+++ nu :: parse number as hex
+ |= jon=json
+ ?> ?=([%s *] jon)
+ (rash p.jon hex)
+::
+++ re :: recursive reparsers
+ |* [gar=* sef=_|.(fist:dejs-soft:format)]
+ |= jon=json
+ ^- (unit _gar)
+ =- ~! gar ~! (need -) -
+ ((sef) jon)
+::
+++ dank :: tank
+ ^- $-(json (unit tank))
+ =, ^? dejs-soft:format
+ %+ re *tank |. ~+
+ %- of :~
+ leaf+sa
+ palm+(ot style+(ot mid+sa cap+sa open+sa close+sa ~) lines+(ar dank) ~)
+ rose+(ot style+(ot mid+sa open+sa close+sa ~) lines+(ar dank) ~)
+ ==
+::
+++ orm ((on atom node) gth)
+++ orm-log ((on time logged-update) gth)
+::
+++ enjs
+ =, enjs:format
+ |%
+ ::
+ ++ signatures
+ |= s=^signatures
+ ^- json
+ [%a (turn ~(tap in s) signature)]
+ ::
+ ++ signature
+ |= s=^signature
+ ^- json
+ %- pairs
+ :~ [%signature s+(scot %ux p.s)]
+ [%ship (ship q.s)]
+ [%life (numb r.s)]
+ ==
+ ::
+ ++ index
+ |= ind=^index
+ ^- json
+ :- %s
+ ?: =(~ ind)
+ '/'
+ %+ roll ind
+ |= [cur=@ acc=@t]
+ ^- @t
+ =/ num (numb cur)
+ ?> ?=(%n -.num)
+ (rap 3 acc '/' p.num ~)
+ ::
+ ++ uid
+ |= u=^uid
+ ^- json
+ %- pairs
+ :~ [%resource (enjs:res resource.u)]
+ [%index (index index.u)]
+ ==
+ ::
+ ++ content
+ |= c=^content
+ ^- json
+ ?- -.c
+ %mention (frond %mention (ship ship.c))
+ %text (frond %text s+text.c)
+ %url (frond %url s+url.c)
+ %reference (frond %reference (reference +.c))
+ %code
+ %+ frond %code
+ %- pairs
+ :- [%expression s+expression.c]
+ :_ ~
+ :- %output
+ :: virtualize output rendering, +tank:enjs:format might crash
+ ::
+ =/ result=(each (list json) tang)
+ (mule |.((turn output.c tank)))
+ ?- -.result
+ %& a+p.result
+ %| a+[a+[%s '[[output rendering error]]']~]~
+ ==
+ ==
+ ::
+ ++ reference
+ |= ref=^reference
+ |^
+ %+ frond -.ref
+ ?- -.ref
+ %graph (graph +.ref)
+ %group (group +.ref)
+ %app (app +.ref)
+ ==
+ ::
+ ++ graph
+ |= [grp=res gra=res idx=^index]
+ %- pairs
+ :~ graph+s+(enjs-path:res gra)
+ group+s+(enjs-path:res grp)
+ index+(index idx)
+ ==
+ ::
+ ++ group
+ |= grp=res
+ s+(enjs-path:res grp)
+ ::
+ ++ app
+ |= [=^ship =desk p=^path]
+ %- pairs
+ :~ ship+s+(scot %p ship)
+ desk+s+desk
+ path+(path p)
+ ==
+ --
+ ::
+ ++ maybe-post
+ |= mp=^maybe-post
+ ^- json
+ ?- -.mp
+ %| s+(scot %ux p.mp)
+ %& (post p.mp)
+ ==
+ ::
+ ++ post
+ |= p=^post
+ ^- json
+ %- pairs
+ :~ [%author (ship author.p)]
+ [%index (index index.p)]
+ [%time-sent (time time-sent.p)]
+ [%contents [%a (turn contents.p content)]]
+ [%hash ?~(hash.p ~ s+(scot %ux u.hash.p))]
+ [%signatures (signatures signatures.p)]
+ ==
+ ::
+ ++ update
+ |= upd=^update
+ ^- json
+ |^ (frond %graph-update (pairs ~[(encode q.upd)]))
+ ::
+ ++ encode
+ |= upd=action
+ ^- [cord json]
+ ?- -.upd
+ %add-graph
+ :- %add-graph
+ %- pairs
+ :~ [%resource (enjs:res resource.upd)]
+ [%graph (graph graph.upd)]
+ [%mark ?~(mark.upd ~ s+u.mark.upd)]
+ [%overwrite b+overwrite.upd]
+ ==
+ ::
+ %remove-graph
+ [%remove-graph (enjs:res resource.upd)]
+ ::
+ %add-nodes
+ :- %add-nodes
+ %- pairs
+ :~ [%resource (enjs:res resource.upd)]
+ [%nodes (nodes nodes.upd)]
+ ==
+ ::
+ %remove-posts
+ :- %remove-posts
+ %- pairs
+ :~ [%resource (enjs:res resource.upd)]
+ [%indices (indices indices.upd)]
+ ==
+ ::
+ %add-signatures
+ :- %add-signatures
+ %- pairs
+ :~ [%uid (uid uid.upd)]
+ [%signatures (signatures signatures.upd)]
+ ==
+ ::
+ %remove-signatures
+ :- %remove-signatures
+ %- pairs
+ :~ [%uid (uid uid.upd)]
+ [%signatures (signatures signatures.upd)]
+ ==
+ ::
+ %add-tag
+ :- %add-tag
+ %- pairs
+ :~ [%term s+term.upd]
+ [%uid (uid uid.upd)]
+ ==
+ ::
+ %remove-tag
+ :- %remove-tag
+ %- pairs
+ :~ [%term s+term.upd]
+ [%uid (uid uid.upd)]
+ ==
+ ::
+ %archive-graph
+ [%archive-graph (enjs:res resource.upd)]
+ ::
+ %unarchive-graph
+ [%unarchive-graph (enjs:res resource.upd)]
+ ::
+ %keys
+ [%keys [%a (turn ~(tap in resources.upd) enjs:res)]]
+ ::
+ %tags
+ [%tags [%a (turn ~(tap in tags.upd) |=(=term s+term))]]
+ ::
+ %run-updates
+ [%run-updates ~]
+ ::
+ %tag-queries
+ :- %tag-queries
+ %- pairs
+ %+ turn ~(tap by tag-queries.upd)
+ |= [=term uids=(set ^uid)]
+ ^- [cord json]
+ [term [%a (turn ~(tap in uids) uid)]]
+ ==
+ ::
+ ++ graph
+ |= g=^graph
+ ^- json
+ %- pairs
+ %+ turn
+ (tap:orm g)
+ |= [a=atom n=^node]
+ ^- [@t json]
+ :_ (node n)
+ =/ idx (numb a)
+ ?> ?=(%n -.idx)
+ p.idx
+ ::
+ ++ node
+ |= n=^node
+ ^- json
+ %- pairs
+ :~ [%post (maybe-post post.n)]
+ :- %children
+ ?- -.children.n
+ %empty ~
+ %graph (graph +.children.n)
+ ==
+ ==
+ ::
+ ++ nodes
+ |= m=(map ^index ^node)
+ ^- json
+ %- pairs
+ %+ turn ~(tap by m)
+ |= [n=^index o=^node]
+ ^- [@t json]
+ :_ (node o)
+ =/ idx (index n)
+ ?> ?=(%s -.idx)
+ p.idx
+ ::
+ ++ indices
+ |= i=(set ^index)
+ ^- json
+ [%a (turn ~(tap in i) index)]
+ ::
+ --
+ --
+::
+++ dejs
+ =, dejs:format
+ |%
+ ++ update
+ |= jon=json
+ ^- ^update
+ :- *time
+ ^- action
+ =< (decode jon)
+ |%
+ ++ decode
+ %- of
+ :~ [%add-nodes add-nodes]
+ [%remove-posts remove-posts]
+ [%add-signatures add-signatures]
+ [%remove-signatures remove-signatures]
+ ::
+ [%add-graph add-graph]
+ [%remove-graph remove-graph]
+ ::
+ [%add-tag add-tag]
+ [%remove-tag remove-tag]
+ ::
+ [%archive-graph archive-graph]
+ [%unarchive-graph unarchive-graph]
+ [%run-updates run-updates]
+ ::
+ [%keys keys]
+ [%tags tags]
+ [%tag-queries tag-queries]
+ ==
+ ::
+ ++ add-graph
+ %- ot
+ :~ [%resource dejs:res]
+ [%graph graph]
+ [%mark (mu so)]
+ [%overwrite bo]
+ ==
+ ::
+ ++ graph
+ |= a=json
+ ^- ^graph
+ =/ or-mp ((on atom ^node) gth)
+ %+ gas:or-mp ~
+ %+ turn ~(tap by ((om node) a))
+ |* [b=cord c=*]
+ ^- [atom ^node]
+ => .(+< [b c]=+<)
+ [(rash b dem) c]
+ ::
+ ++ remove-graph (ot [%resource dejs:res]~)
+ ++ archive-graph (ot [%resource dejs:res]~)
+ ++ unarchive-graph (ot [%resource dejs:res]~)
+ ::
+ ++ add-nodes
+ %- ot
+ :~ [%resource dejs:res]
+ [%nodes nodes]
+ ==
+ ::
+ ++ nodes (op ;~(pfix fas (more fas dem)) node)
+ ::
+ ++ node
+ %- ot
+ :~ [%post maybe-post]
+ [%children internal-graph]
+ ==
+ ::
+ ++ internal-graph
+ |= jon=json
+ ^- ^internal-graph
+ ?~ jon
+ [%empty ~]
+ [%graph (graph jon)]
+ ::
+ ++ maybe-post
+ |= jon=json
+ ^- ^maybe-post
+ ?~ jon !!
+ ?+ -.jon !!
+ %s [%| (nu jon)]
+ %o [%& (post jon)]
+ ==
+ ::
+ ++ post
+ %- ot
+ :~ [%author (su ;~(pfix sig fed:ag))]
+ [%index index]
+ [%time-sent di]
+ [%contents (ar content)]
+ [%hash (mu nu)]
+ [%signatures (as signature)]
+ ==
+ ::
+ ++ content
+ %- of
+ :~ [%mention (su ;~(pfix sig fed:ag))]
+ [%text so]
+ [%url so]
+ [%reference reference]
+ [%code eval]
+ ==
+ ::
+ ++ reference
+ |^
+ %- of
+ :~ graph+graph
+ group+dejs-path:res
+ app+app
+ ==
+ ::
+ ++ graph
+ %- ot
+ :~ group+dejs-path:res
+ graph+dejs-path:res
+ index+index
+ ==
+ ::
+ ++ app
+ %- ot
+ :~ ship+(su ;~(pfix sig fed:ag))
+ desk+so
+ path+pa
+ ==
+ --
+ ::
+ ++ tang
+ |= jon=^json
+ ^- ^tang
+ ?> ?=(%a -.jon)
+ %- zing
+ %+ turn
+ p.jon
+ |= jo=^json
+ ^- (list tank)
+ ?> ?=(%a -.jo)
+ %+ turn
+ p.jo
+ |= j=^json
+ ?> ?=(%s -.j)
+ ^- tank
+ leaf+(trip p.j)
+ ::
+ ++ eval
+ %- ot
+ :~ expression+so
+ output+tang
+ ==
+ ::
+ ++ remove-posts
+ %- ot
+ :~ [%resource dejs:res]
+ [%indices (as index)]
+ ==
+ ::
+ ++ add-signatures
+ %- ot
+ :~ [%uid uid]
+ [%signatures (as signature)]
+ ==
+ ::
+ ++ remove-signatures
+ %- ot
+ :~ [%uid uid]
+ [%signatures (as signature)]
+ ==
+ ::
+ ++ signature
+ %- ot
+ :~ [%hash nu]
+ [%ship (su ;~(pfix sig fed:ag))]
+ [%life ni]
+ ==
+ ::
+ ++ uid
+ %- ot
+ :~ [%resource dejs:res]
+ [%index index]
+ ==
+ ::
+ ++ index (su ;~(pfix fas (more fas dem)))
+ ::
+ ++ add-tag
+ %- ot
+ :~ [%term so]
+ [%uid uid]
+ ==
+ ::
+ ++ remove-tag
+ %- ot
+ :~ [%term so]
+ [%uid uid]
+ ==
+ ::
+ ++ keys
+ |= =json
+ *resources
+ ::
+ ++ tags
+ |= =json
+ *(set term)
+ ::
+ ++ tag-queries
+ |= =json
+ *^tag-queries
+ ::
+ ++ run-updates
+ |= a=json
+ ^- [resource update-log]
+ [*resource *update-log]
+ --
+ ++ pa
+ |= j=json
+ ^- path
+ ?> ?=(%s -.j)
+ ?: =('/' p.j) /
+ (stab p.j)
+ ::
+ --
+::
+++ create
+ |_ [our=ship now=time]
+ ++ post
+ |= [=index contents=(list content)]
+ ^- ^post
+ :* our
+ index
+ now
+ contents
+ ~
+ *signatures
+ ==
+ --
+::
+++ upgrade
+ |%
+ ::
+ :: +two
+ ::
+ ++ marked-graph-to-two
+ |= [=graph:one m=(unit mark)]
+ [(graph-to-two graph) m]
+ ::
+ ++ graph-to-two
+ |= =graph:one
+ (graph:(upgrade ,post:one ,maybe-post:two) graph post-to-two)
+ ::
+ ++ post-to-two
+ |= p=post:one
+ ^- maybe-post:two
+ [%& p]
+ ::
+ ::
+ :: +one
+ ::
+ ++ update-log-to-one
+ |= =update-log:zero
+ ^- update-log:one
+ %+ gas:orm-log:one *update-log:one
+ %+ turn (tap:orm-log:zero update-log)
+ |= [=time =logged-update:zero]
+ ^- [^time logged-update:one]
+ :- time
+ :- p.logged-update
+ (logged-update-to-one q.logged-update)
+ ::
+ ++ logged-update-to-one
+ |= upd=logged-update-0:zero
+ ^- logged-action:one
+ ?+ -.upd upd
+ %add-graph upd(graph (graph-to-one graph.upd))
+ %add-nodes upd(nodes (~(run by nodes.upd) node-to-one))
+ ==
+ ::
+ ++ node-to-one
+ |= =node:zero
+ (node:(upgrade ,post:zero ,post:one) node post-to-one)
+ ::
+ ++ graph-to-one
+ |= =graph:zero
+ (graph:(upgrade ,post:zero ,post:one) graph post-to-one)
+ ::
+ ++ marked-graph-to-one
+ |= [=graph:zero m=(unit mark)]
+ [(graph-to-one graph) m]
+ ::
+ ++ post-to-one
+ |= p=post:zero
+ ^- post:one
+ p(contents (contents-to-one contents.p))
+ ::
+ ++ contents-to-one
+ |= cs=(list content:zero)
+ ^- (list content:one)
+ %+ murn cs
+ |= =content:zero
+ ^- (unit content:one)
+ ?: ?=(%reference -.content) ~
+ `content
+ ::
+ ++ upgrade
+ |* [in-pst=mold out-pst=mold]
+ =>
+ |%
+ ++ in-orm
+ ((on atom in-node) gth)
+ +$ in-node
+ [post=in-pst children=in-internal-graph]
+ +$ in-graph
+ ((mop atom in-node) gth)
+ +$ in-internal-graph
+ $~ [%empty ~]
+ $% [%graph p=in-graph]
+ [%empty ~]
+ ==
+ ::
+ ++ out-orm
+ ((on atom out-node) gth)
+ +$ out-node
+ [post=out-pst children=out-internal-graph]
+ +$ out-graph
+ ((mop atom out-node) gth)
+ +$ out-internal-graph
+ $~ [%empty ~]
+ $% [%graph p=out-graph]
+ [%empty ~]
+ ==
+ --
+ |%
+ ::
+ ++ graph
+ |= $: gra=in-graph
+ fn=$-(in-pst out-pst)
+ ==
+ ^- out-graph
+ %+ gas:out-orm *out-graph
+ ^- (list [atom out-node])
+ %+ turn (tap:in-orm gra)
+ |= [a=atom n=in-node]
+ ^- [atom out-node]
+ [a (node n fn)]
+ ::
+ ++ node
+ |= [nod=in-node fn=$-(in-pst out-pst)]
+ ^- out-node
+ :- (fn post.nod)
+ ^- out-internal-graph
+ ?: ?=(%empty -.children.nod)
+ [%empty ~]
+ [%graph (graph p.children.nod fn)]
+ --
+ ::
+ ++ zero-load
+ :: =* infinitely recurses
+ =, store=zero
+ =, orm=orm:zero
+ =, orm-log=orm-log:zero
+ |%
+ ++ change-revision-graph
+ |= [=graph:store q=(unit mark)]
+ ^- [graph:store (unit mark)]
+ |^
+ :_ q
+ ?+ q graph
+ [~ %graph-validator-link] convert-links
+ [~ %graph-validator-publish] convert-publish
+ ==
+ ::
+ ++ convert-links
+ %+ gas:orm *graph:store
+ %+ turn (tap:orm graph)
+ |= [=atom =node:store]
+ ^- [^atom node:store]
+ :: top-level
+ ::
+ :+ atom post.node
+ ?: ?=(%empty -.children.node)
+ [%empty ~]
+ :- %graph
+ %+ gas:orm *graph:store
+ %+ turn (tap:orm p.children.node)
+ |= [=^atom =node:store]
+ ^- [^^atom node:store]
+ :: existing comments get turned into containers for revisions
+ ::
+ :^ atom
+ post.node(contents ~, hash ~)
+ %graph
+ %+ gas:orm *graph:store
+ :_ ~ :- %0
+ :_ [%empty ~]
+ post.node(index (snoc index.post.node atom), hash ~)
+ ::
+ ++ convert-publish
+ %+ gas:orm *graph:store
+ %+ turn (tap:orm graph)
+ |= [=atom =node:store]
+ ^- [^atom node:store]
+ :: top-level
+ ::
+ :+ atom post.node
+ ?: ?=(%empty -.children.node)
+ [%empty ~]
+ :- %graph
+ %+ gas:orm *graph:store
+ %+ turn (tap:orm p.children.node)
+ |= [=^atom =node:store]
+ ^- [^^atom node:store]
+ :: existing container for publish note revisions
+ ::
+ ?+ atom !!
+ %1 [atom node]
+ %2
+ :+ atom post.node
+ ?: ?=(%empty -.children.node)
+ [%empty ~]
+ :- %graph
+ %+ gas:orm *graph:store
+ %+ turn (tap:orm p.children.node)
+ |= [=^^atom =node:store]
+ ^- [^^^atom node:store]
+ :+ atom post.node(contents ~, hash ~)
+ :- %graph
+ %+ gas:orm *graph:store
+ :_ ~ :- %1
+ :_ [%empty ~]
+ post.node(index (snoc index.post.node atom), hash ~)
+ ==
+ --
+ ::
+ ++ maybe-unix-to-da
+ |= =atom
+ ^- @
+ :: (bex 127) is roughly 226AD
+ ?. (lte atom (bex 127))
+ atom
+ (add ~1970.1.1 (div (mul ~s1 atom) 1.000))
+ ::
+ ++ convert-unix-timestamped-node
+ |= =node:store
+ ^- node:store
+ =. index.post.node
+ (convert-unix-timestamped-index index.post.node)
+ ?. ?=(%graph -.children.node)
+ node
+ :+ post.node
+ %graph
+ (convert-unix-timestamped-graph p.children.node)
+ ::
+ ++ convert-unix-timestamped-index
+ |= =index:store
+ (turn index maybe-unix-to-da)
+ ::
+ ++ convert-unix-timestamped-graph
+ |= =graph:store
+ %+ gas:orm *graph:store
+ %+ turn
+ (tap:orm graph)
+ |= [=atom =node:store]
+ ^- [^atom node:store]
+ :- (maybe-unix-to-da atom)
+ (convert-unix-timestamped-node node)
+ --
+ --
+++ import
+ |= [arc=* our=ship]
+ ^- (quip card:agent:gall [%6 network])
+ |^
+ =/ sty [%6 (remake-network ;;(tree-network +.arc))]
+ :_ sty
+ %+ turn ~(tap by graphs.sty)
+ |= [rid=resource =marked-graph]
+ ^- card:agent:gall
+ ?: =(our entity.rid)
+ =/ =cage [%push-hook-action !>([%add rid])]
+ [%pass / %agent [our %graph-push-hook] %poke cage]
+ (try-rejoin rid 0)
+ ::
+ +$ tree-network
+ $: graphs=tree-graphs
+ tag-queries=(tree [term (tree uid)])
+ update-logs=tree-update-logs
+ archive=tree-graphs
+ ~
+ ==
+ +$ tree-graphs (tree [resource tree-marked-graph])
+ +$ tree-marked-graph [p=tree-graph q=(unit ^mark)]
+ +$ tree-graph (tree [atom tree-node])
+ +$ tree-node [post=tree-maybe-post children=tree-internal-graph]
+ +$ tree-internal-graph
+ $~ [%empty ~]
+ $% [%graph p=tree-graph]
+ [%empty ~]
+ ==
+ +$ tree-update-logs (tree [resource tree-update-log])
+ +$ tree-update-log (tree [time tree-logged-update])
+ +$ tree-logged-update
+ $: p=time
+ $= q
+ $% [%add-graph =resource =tree-graph mark=(unit ^mark) ow=?]
+ [%add-nodes =resource nodes=(tree [index tree-node])]
+ [%remove-posts =resource indices=(tree index)]
+ [%add-signatures =uid signatures=tree-signatures]
+ [%remove-signatures =uid signatures=tree-signatures]
+ ==
+ ==
+ +$ tree-signatures (tree signature)
+ +$ tree-maybe-post (each tree-post hash)
+ +$ tree-post
+ $: author=ship
+ =index
+ time-sent=time
+ contents=(list content)
+ hash=(unit hash)
+ signatures=tree-signatures
+ ==
+ ::
+ ++ remake-network
+ |= t=tree-network
+ ^- network
+ :* (remake-graphs graphs.t)
+ (remake-jug:migrate tag-queries.t)
+ (remake-update-logs update-logs.t)
+ (remake-graphs archive.t)
+ ~
+ ==
+ ::
+ ++ remake-graphs
+ |= t=tree-graphs
+ ^- graphs
+ %- remake-map:migrate
+ (~(run by t) remake-marked-graph)
+ ::
+ ++ remake-marked-graph
+ |= t=tree-marked-graph
+ ^- marked-graph
+ [(remake-graph p.t) q.t]
+ ::
+ ++ remake-graph
+ |= t=tree-graph
+ ^- graph
+ %+ gas:orm *graph
+ %+ turn ~(tap by t)
+ |= [a=atom tn=tree-node]
+ ^- [atom node]
+ [a (remake-node tn)]
+ ::
+ ++ remake-internal-graph
+ |= t=tree-internal-graph
+ ^- internal-graph
+ ?: ?=(%empty -.t)
+ [%empty ~]
+ [%graph (remake-graph p.t)]
+ ::
+ ++ remake-node
+ |= t=tree-node
+ ^- node
+ :- (remake-post post.t)
+ (remake-internal-graph children.t)
+ ::
+ ++ remake-update-logs
+ |= t=tree-update-logs
+ ^- update-logs
+ %- remake-map:migrate
+ (~(run by t) remake-update-log)
+ ::
+ ++ remake-update-log
+ |= t=tree-update-log
+ ^- update-log
+ =/ ulm ((on time logged-update) gth)
+ %+ gas:ulm *update-log
+ %+ turn ~(tap by t)
+ |= [=time tlu=tree-logged-update]
+ ^- [^time logged-update]
+ [time (remake-logged-update tlu)]
+ ::
+ ++ remake-logged-update
+ |= t=tree-logged-update
+ ^- logged-update
+ :- p.t
+ ?- -.q.t
+ %add-graph
+ :* %add-graph
+ resource.q.t
+ (remake-graph tree-graph.q.t)
+ mark.q.t
+ ow.q.t
+ ==
+ ::
+ %add-nodes
+ :- %add-nodes
+ :- resource.q.t
+ %- remake-map:migrate
+ (~(run by nodes.q.t) remake-node)
+ ::
+ %remove-posts
+ [%remove-posts resource.q.t (remake-set:migrate indices.q.t)]
+ ::
+ %add-signatures
+ [%add-signatures uid.q.t (remake-set:migrate signatures.q.t)]
+ ::
+ %remove-signatures
+ [%remove-signatures uid.q.t (remake-set:migrate signatures.q.t)]
+ ==
+ ::
+ ++ remake-post
+ |= t=tree-maybe-post
+ ^- maybe-post
+ ?- -.t
+ %| t
+ %& t(signatures.p (remake-set:migrate signatures.p.t))
+ ==
+ ::
+ ++ try-rejoin
+ |= [rid=resource nack-count=@]
+ ^- card:agent:gall
+ =/ res-path (en-path:res rid)
+ =/ wire [%try-rejoin (scot %ud nack-count) res-path]
+ =/ =cage
+ :- %pull-hook-action
+ !> ^- action:pull-hook
+ [%add [entity .]:rid]
+ [%pass wire %agent [our %graph-pull-hook] %poke cage]
+ --
+--
diff --git a/zod/seax/lib/resource.hoon b/zod/seax/lib/resource.hoon
new file mode 100644
index 0000000..f84acb0
--- /dev/null
+++ b/zod/seax/lib/resource.hoon
@@ -0,0 +1,57 @@
+/- sur=resource
+=< resource
+|%
++$ resource resource:sur
+++ en-path
+ |= =resource
+ ^- path
+ ~[%ship (scot %p entity.resource) name.resource]
+::
+++ de-path
+ |= =path
+ ^- resource
+ (need (de-path-soft path))
+::
+++ de-path-soft
+ |= =path
+ ^- (unit resource)
+ ?. ?=([%ship @ @ *] path)
+ ~
+ =/ ship
+ (slaw %p i.t.path)
+ ?~ ship
+ ~
+ `[u.ship i.t.t.path]
+::
+++ enjs
+ |= =resource
+ ^- json
+ =, enjs:format
+ %- pairs
+ :~ ship+(ship entity.resource)
+ name+s+name.resource
+ ==
+::
+++ enjs-path
+ |= =resource
+ %- spat
+ (en-path resource)
+::
+++ dejs-path
+ %- su:dejs:format
+ ;~ pfix
+ (jest '/ship/')
+ ;~((glue fas) ;~(pfix sig fed:ag) urs:ab)
+ ==
+::
+++ dejs
+ =, dejs:format
+ ^- $-(json resource)
+ |= jon=json
+ ~| dejs+%resource
+ %. jon
+ %- ot
+ :~ ship+(su ;~(pfix sig fed:ag))
+ name+so
+ ==
+--
diff --git a/zod/seax/sur/diary-0.hoon b/zod/seax/sur/diary-0.hoon
new file mode 100644
index 0000000..da0d5c0
--- /dev/null
+++ b/zod/seax/sur/diary-0.hoon
@@ -0,0 +1,323 @@
+/- g=groups, c=cite, graph-store, e=epic
+/- metadata-store
+/+ lib-graph=graph-store
+|%
+++ okay `epic:e`0
+++ mar
+ |%
+ ++ act `mark`(rap 3 %diary-action '-' (scot %ud okay) ~)
+ ++ upd `mark`(rap 3 %diary-update '-' (scot %ud okay) ~)
+ ++ log `mark`(rap 3 %diary-logs '-' (scot %ud okay) ~)
+ --
+:: $flag: identifier for a diary channel
++$ flag (pair ship term)
+:: $feel: either an emoji identifier like :diff or a URL for custom
++$ feel @ta
+:: $view: the persisted display format for a diary
++$ view ?(%grid %list)
+:: $sort: the persisted sort type for a diary
++$ sort ?(%alpha %time %arranged)
+:: $shelf: my ship's diaries
++$ shelf (map flag diary)
+:: $said: used for references
++$ said (pair flag outline)
+:: $plan: index into diary state
+:: p: Note being referred to
+:: q: Quip being referred to, if any
+::
++$ plan
+ (pair time (unit time))
+::
+:: $diary: written longform communication
+::
+:: net: an indicator of whether I'm a host or subscriber
+:: log: the history of all modifications
+:: perm: holds the diary's permissions
+:: view: what format to display
+:: sort: how to order posts
+:: notes: the actual contents of the diary
+:: remark: what is the last thing we've read
+:: banter: comments organized by post
+::
++$ diary
+ $: =net
+ =log
+ =perm
+ =view
+ =sort
+ =notes
+ =remark
+ ==
+::
+:: $notes: a set of time ordered diary posts
+::
+++ notes
+ =< rock
+ |%
+ +$ rock
+ ((mop time note) lte)
+ ++ on
+ ((^on time note) lte)
+ +$ diff
+ (pair time delta)
+ +$ delta
+ $% [%add p=essay]
+ [%edit p=essay]
+ [%del ~]
+ [%quips p=diff:quips]
+ [%add-feel p=ship q=feel]
+ [%del-feel p=ship]
+ ==
+ --
+::
+:: $quips: a set of time ordered note comments
+::
+++ quips
+ =< rock
+ |%
+ +$ rock
+ ((mop time quip) lte)
+ ++ on
+ ((^on time quip) lte)
+ +$ diff
+ (pair time delta)
+ +$ delta
+ $% [%add p=memo]
+ [%del ~]
+ [%add-feel p=ship q=feel]
+ [%del-feel p=ship]
+ ==
+ --
+::
+:: $outline: abridged $note
+:: .quips: number of comments
+::
++$ outline
+ [quips=@ud quippers=(set ship) essay]
+::
+++ outlines
+ =< outlines
+ |%
+ +$ outlines ((mop time outline) lte)
+ ++ on ((^on time outline) lte)
+ --
+::
+:: $note: a diary post
+::
++$ note [seal essay]
+:: $quip: a post comment
+::
++$ quip [cork memo]
+::
+:: $seal: host-side data for a note
+::
++$ seal
+ $: =time
+ =quips
+ feels=(map ship feel)
+ ==
+::
+:: $cork: host-side data for a quip
+::
++$ cork
+ $: =time
+ feels=(map ship feel)
+ ==
+:: $essay: the post data itself
+::
+:: title: the name of the post
+:: image: a visual displayed as a header
+:: content: the body of the post
+:: author: the ship that wrote the post
+:: sent: the client-side time the post was made
+::
++$ essay
+ $: title=@t
+ image=@t
+ content=(list verse)
+ author=ship
+ sent=time
+ ==
++$ story (pair (list block) (list inline))
+:: $memo: the comment data itself
+::
+:: content: the body of the comment
+:: author: the ship that wrote the comment
+:: sent: the client-side time the comment was made
+::
++$ memo
+ $: content=story
+ author=ship
+ sent=time
+ ==
+:: $verse: a chunk of post content
+::
+:: blocks stand on their own. inlines come in groups and get wrapped
+:: into a paragraph
+::
++$ verse
+ $% [%block p=block]
+ [%inline p=(list inline)]
+ ==
+:: $listing: recursive type for infinitely nested
or
++$ listing
+ $% [%list p=?(%ordered %unordered) q=(list listing) r=(list inline)]
+ [%item p=(list inline)]
+ ==
+:: $block: post content that sits outside of the normal text
+::
+:: %image: a visual, we record dimensions for better rendering
+:: %cite: an Urbit reference
+:: %header: a traditional HTML heading, h1-h6
+:: %listing: a traditional HTML list, ul and ol
+:: %code: a block of code
+::
++$ block
+ $% [%image src=cord height=@ud width=@ud alt=cord]
+ [%cite =cite:c]
+ [%header p=?(%h1 %h2 %h3 %h4 %h5 %h6) q=(list inline)]
+ [%listing p=listing]
+ [%rule ~]
+ [%code code=cord lang=cord]
+ ==
+:: $inline: post content that flows within a paragraph
+::
+:: @t: plain text
+:: %italics: italic text
+:: %bold: bold text
+:: %strike: strikethrough text
+:: %inline-code: code formatting for small snippets
+:: %blockquote: blockquote surrounded content
+:: %block: link/reference to blocks
+:: %code: code formatting for large snippets
+:: %tag: tag gets special signifier
+:: %link: link to a URL with a face
+:: %break: line break
+::
++$ inline
+ $@ @t
+ $% [%italics p=(list inline)]
+ [%bold p=(list inline)]
+ [%strike p=(list inline)]
+ [%blockquote p=(list inline)]
+ [%inline-code p=cord]
+ [%ship p=ship]
+ [%block p=@ud q=cord]
+ [%code p=cord]
+ [%tag p=cord]
+ [%link p=cord q=cord]
+ [%break ~]
+ ==
+:: $log: a time ordered history of modifications to a diary
+::
++$ log
+ ((mop time diff) lte)
+++ log-on
+ ((on time diff) lte)
+::
+:: $action: the complete set of data required to modify a diary
+::
++$ action
+ (pair flag:g update)
+::
+:: $update: a representation in time of a modification to a diary
+::
++$ update
+ (pair time diff)
+::
+:: $diff: the full suite of modifications that can be made to a diary
+::
++$ diff
+ $% [%notes p=diff:notes]
+ ::
+ [%add-sects p=(set sect:g)]
+ [%del-sects p=(set sect:g)]
+ ::
+ [%create p=perm q=notes]
+ [%view p=view]
+ [%sort p=sort]
+ ::
+ ==
+::
+:: $net: an indicator of whether I'm a host or subscriber
+::
+:: %pub: am publisher/host with fresh log
+:: %sub: subscribed to the ship at saga
+::
++$ net
+ $% [%sub p=ship load=_| =saga:e]
+ [%pub ~] :: TODO: permissions?
+ ==
+::
+:: $briefs: a map of diary unread information
+::
+:: brief: the last time a diary was read, how many posts since,
+:: and the id of the last read note
+::
+++ briefs
+ =< briefs
+ |%
+ +$ briefs
+ (map flag brief)
+ +$ brief
+ [last=time count=@ud read-id=(unit time)]
+ +$ update
+ (pair flag brief)
+ --
+:: $remark: a marker representing the last note I've read
+::
++$ remark
+ [last-read=time watching=_| ~]
+::
++$ remark-action
+ (pair flag remark-diff)
+::
++$ remark-diff
+ $% [%read ~]
+ [%read-at p=time]
+ [?(%watch %unwatch) ~]
+ ==
+::
+:: $perm: represents the permissions for a diary channel and gives a
+:: pointer back to the group it belongs to.
+::
++$ perm
+ $: writers=(set sect:g)
+ group=flag:g
+ ==
+:: $join: a group + channel flag to join a channel, group required for perms
+::
++$ join
+ $: group=flag:g
+ chan=flag:g
+ ==
+:: $leave: a flag to pass for a channel leave
+::
++$ leave flag:g
+::
+:: $create: represents a request to create a channel
+::
+:: The name will be used as part of the flag which represents the
+:: channel. $create is consumed by the diary agent first and then
+:: passed to the groups agent to register the channel with the group.
+::
+:: Write permission is stored with the specific agent in the channel,
+:: read permission is stored with the group's data.
+::
++$ create
+ $: group=flag:g
+ name=term
+ title=cord
+ description=cord
+ readers=(set sect:g)
+ writers=(set sect:g)
+ ==
++$ import [writers=(set ship) =association:met =update-log:gra =graph:gra]
+::
++$ imports (map flag import)
+::
+++ gra graph-store
+++ orm-gra orm:lib-graph
+++ orm-log-gra orm-log:lib-graph
+++ met metadata-store
+--
diff --git a/zod/seax/sur/diary.hoon b/zod/seax/sur/diary.hoon
new file mode 100644
index 0000000..57716e5
--- /dev/null
+++ b/zod/seax/sur/diary.hoon
@@ -0,0 +1,335 @@
+/- g=groups, c=cite, graph-store, e=epic
+/- zer=diary-0
+/- metadata-store
+/+ lib-graph=graph-store
+|%
+++ old
+ |%
+ ++ zero zer
+ --
+::
+++ okay `epic:e`2
+++ mar
+ |%
+ ++ act `mark`(rap 3 %diary-action '-' (scot %ud okay) ~)
+ ++ upd `mark`(rap 3 %diary-update '-' (scot %ud okay) ~)
+ ++ log `mark`(rap 3 %diary-logs '-' (scot %ud okay) ~)
+ --
+:: $flag: identifier for a diary channel
++$ flag (pair ship term)
+:: $feel: either an emoji identifier like :diff or a URL for custom
++$ feel @ta
+:: $view: the persisted display format for a diary
++$ view ?(%grid %list)
+:: $sort: the persisted sort type for a diary
++$ sort ?(%alpha %time %arranged)
+:: $arranged-notes: an array of noteIds
++$ arranged-notes (unit (list time))
+:: $shelf: my ship's diaries
++$ shelf (map flag diary)
+:: $said: used for references
++$ said (pair flag outline)
+:: $plan: index into diary state
+:: p: Note being referred to
+:: q: Quip being referred to, if any
+::
++$ plan
+ (pair time (unit time))
+::
+:: $diary: written longform communication
+::
+:: arranged-notes: a list of noteIds, used for manual sorting
+:: net: an indicator of whether I'm a host or subscriber
+:: log: the history of all modifications
+:: perm: holds the diary's permissions
+:: view: what format to display
+:: sort: how to order posts
+:: notes: the actual contents of the diary
+:: remark: what is the last thing we've read
+:: banter: comments organized by post
+::
++$ diary
+ $: =arranged-notes
+ =net
+ =log
+ =perm
+ =view
+ =sort
+ =notes
+ =remark
+ ==
+::
+:: $notes: a set of time ordered diary posts
+::
+++ notes
+ =< rock
+ |%
+ +$ rock
+ ((mop time note) lte)
+ ++ on
+ ((^on time note) lte)
+ +$ diff
+ (pair time delta)
+ +$ delta
+ $% [%add p=essay]
+ [%edit p=essay]
+ [%del ~]
+ [%quips p=diff:quips]
+ [%add-feel p=ship q=feel]
+ [%del-feel p=ship]
+ ==
+ --
+::
+:: $quips: a set of time ordered note comments
+::
+++ quips
+ =< rock
+ |%
+ +$ rock
+ ((mop time quip) lte)
+ ++ on
+ ((^on time quip) lte)
+ +$ diff
+ (pair time delta)
+ +$ delta
+ $% [%add p=memo]
+ [%del ~]
+ [%add-feel p=ship q=feel]
+ [%del-feel p=ship]
+ ==
+ --
+::
+:: $outline: abridged $note
+:: .quips: number of comments
+::
++$ outline
+ [quips=@ud quippers=(set ship) essay]
+::
+++ outlines
+ =< outlines
+ |%
+ +$ outlines ((mop time outline) lte)
+ ++ on ((^on time outline) lte)
+ --
+::
+:: $note: a diary post
+::
++$ note [seal essay]
+:: $quip: a post comment
+::
++$ quip [cork memo]
+::
+:: $seal: host-side data for a note
+::
++$ seal
+ $: =time
+ =quips
+ feels=(map ship feel)
+ ==
+::
+:: $cork: host-side data for a quip
+::
++$ cork
+ $: =time
+ feels=(map ship feel)
+ ==
+:: $essay: the post data itself
+::
+:: title: the name of the post
+:: image: a visual displayed as a header
+:: content: the body of the post
+:: author: the ship that wrote the post
+:: sent: the client-side time the post was made
+::
++$ essay
+ $: title=@t
+ image=@t
+ content=(list verse)
+ author=ship
+ sent=time
+ ==
++$ story (pair (list block) (list inline))
+:: $memo: the comment data itself
+::
+:: content: the body of the comment
+:: author: the ship that wrote the comment
+:: sent: the client-side time the comment was made
+::
++$ memo
+ $: content=story
+ author=ship
+ sent=time
+ ==
+:: $verse: a chunk of post content
+::
+:: blocks stand on their own. inlines come in groups and get wrapped
+:: into a paragraph
+::
++$ verse
+ $% [%block p=block]
+ [%inline p=(list inline)]
+ ==
+:: $listing: recursive type for infinitely nested or
++$ listing
+ $% [%list p=?(%ordered %unordered %tasklist) q=(list listing) r=(list inline)]
+ [%item p=(list inline)]
+ ==
+:: $block: post content that sits outside of the normal text
+::
+:: %image: a visual, we record dimensions for better rendering
+:: %cite: an Urbit reference
+:: %header: a traditional HTML heading, h1-h6
+:: %listing: a traditional HTML list, ul and ol
+:: %code: a block of code
+::
++$ block
+ $% [%image src=cord height=@ud width=@ud alt=cord]
+ [%cite =cite:c]
+ [%header p=?(%h1 %h2 %h3 %h4 %h5 %h6) q=(list inline)]
+ [%listing p=listing]
+ [%rule ~]
+ [%code code=cord lang=cord]
+ ==
+:: $inline: post content that flows within a paragraph
+::
+:: @t: plain text
+:: %italics: italic text
+:: %bold: bold text
+:: %strike: strikethrough text
+:: %inline-code: code formatting for small snippets
+:: %blockquote: blockquote surrounded content
+:: %block: link/reference to blocks
+:: %code: code formatting for large snippets
+:: %tag: tag gets special signifier
+:: %link: link to a URL with a face
+:: %break: line break
+::
++$ inline
+ $@ @t
+ $% [%italics p=(list inline)]
+ [%bold p=(list inline)]
+ [%strike p=(list inline)]
+ [%blockquote p=(list inline)]
+ [%inline-code p=cord]
+ [%ship p=ship]
+ [%block p=@ud q=cord]
+ [%code p=cord]
+ [%tag p=cord]
+ [%link p=cord q=cord]
+ [%task p=?(%.y %.n) q=(list inline)]
+ [%break ~]
+ ==
+:: $log: a time ordered history of modifications to a diary
+::
++$ log
+ ((mop time diff) lte)
+++ log-on
+ ((on time diff) lte)
+::
+:: $action: the complete set of data required to modify a diary
+::
++$ action
+ (pair flag:g update)
+::
+:: $update: a representation in time of a modification to a diary
+::
++$ update
+ (pair time diff)
+::
+:: $diff: the full suite of modifications that can be made to a diary
+::
++$ diff
+ $% [%notes p=diff:notes]
+ ::
+ [%add-sects p=(set sect:g)]
+ [%del-sects p=(set sect:g)]
+ ::
+ [%create p=perm q=notes]
+ [%view p=view]
+ [%sort p=sort]
+ [%arranged-notes p=arranged-notes]
+ ::
+ ==
+::
+:: $net: an indicator of whether I'm a host or subscriber
+::
+:: %pub: am publisher/host with fresh log
+:: %sub: subscribed to the ship at saga
+::
++$ net
+ $% [%sub p=ship load=_| =saga:e]
+ [%pub ~] :: TODO: permissions?
+ ==
+::
+:: $briefs: a map of diary unread information
+::
+:: brief: the last time a diary was read, how many posts since,
+:: and the id of the last read note
+::
+++ briefs
+ =< briefs
+ |%
+ +$ briefs
+ (map flag brief)
+ +$ brief
+ [last=time count=@ud read-id=(unit time)]
+ +$ update
+ (pair flag brief)
+ --
+:: $remark: a marker representing the last note I've read
+::
++$ remark
+ [last-read=time watching=_| ~]
+::
++$ remark-action
+ (pair flag remark-diff)
+::
++$ remark-diff
+ $% [%read ~]
+ [%read-at p=time]
+ [?(%watch %unwatch) ~]
+ ==
+::
+:: $perm: represents the permissions for a diary channel and gives a
+:: pointer back to the group it belongs to.
+::
++$ perm
+ $: writers=(set sect:g)
+ group=flag:g
+ ==
+:: $join: a group + channel flag to join a channel, group required for perms
+::
++$ join
+ $: group=flag:g
+ chan=flag:g
+ ==
+:: $leave: a flag to pass for a channel leave
+::
++$ leave flag:g
+::
+:: $create: represents a request to create a channel
+::
+:: The name will be used as part of the flag which represents the
+:: channel. $create is consumed by the diary agent first and then
+:: passed to the groups agent to register the channel with the group.
+::
+:: Write permission is stored with the specific agent in the channel,
+:: read permission is stored with the group's data.
+::
++$ create
+ $: group=flag:g
+ name=term
+ title=cord
+ description=cord
+ readers=(set sect:g)
+ writers=(set sect:g)
+ ==
++$ import [writers=(set ship) =association:met =update-log:gra =graph:gra]
+::
++$ imports (map flag import)
+::
+++ gra graph-store
+++ orm-gra orm:lib-graph
+++ orm-log-gra orm-log:lib-graph
+++ met metadata-store
+--
diff --git a/zod/seax/sur/epic.hoon b/zod/seax/sur/epic.hoon
new file mode 100644
index 0000000..30d7f7e
--- /dev/null
+++ b/zod/seax/sur/epic.hoon
@@ -0,0 +1,15 @@
+|%
+:: $saga: version synchronisation state
+:: %dex: publisher is ahead
+:: %lev: we are ahead
+:: %chi: full sync
+::
++$ saga
+ $% [%dex ver=@ud]
+ [%lev ~]
+ [%chi ~]
+ ==
+
++$ epic @ud
+::
+--
diff --git a/zod/seax/sur/graph-store.hoon b/zod/seax/sur/graph-store.hoon
new file mode 100644
index 0000000..4824449
--- /dev/null
+++ b/zod/seax/sur/graph-store.hoon
@@ -0,0 +1,272 @@
+/- *post
+|%
++$ graph ((mop atom node) gth)
++$ marked-graph [p=graph q=(unit mark)]
+::
++$ maybe-post (each post hash)
++$ node [post=maybe-post children=internal-graph]
++$ graphs (map resource marked-graph)
+::
++$ tag-queries (jug term uid)
+::
++$ update-log ((mop time logged-update) gth)
++$ update-logs (map resource update-log)
+::
++$ internal-graph
+ $~ [%empty ~]
+ $% [%graph p=graph]
+ [%empty ~]
+ ==
+::
++$ network
+ $: =graphs
+ =tag-queries
+ =update-logs
+ archive=graphs
+ ~
+ ==
+::
++$ update [p=time q=action]
+::
++$ logged-update [p=time q=logged-action]
+
+::
++$ logged-action
+ $% [%add-graph =resource =graph mark=(unit mark) overwrite=?]
+ [%add-nodes =resource nodes=(map index node)]
+ [%remove-posts =resource indices=(set index)]
+ [%add-signatures =uid =signatures]
+ [%remove-signatures =uid =signatures]
+ ==
+::
++$ action
+ $% logged-action
+ [%remove-graph =resource]
+ ::
+ [%add-tag =term =uid]
+ [%remove-tag =term =uid]
+ ::
+ [%archive-graph =resource]
+ [%unarchive-graph =resource]
+ [%run-updates =resource =update-log]
+ ::
+ :: NOTE: cannot be sent as pokes
+ ::
+ [%keys =resources]
+ [%tags tags=(set term)]
+ [%tag-queries =tag-queries]
+ ==
+::
++$ permissions
+ [admin=permission-level writer=permission-level reader=permission-level]
+::
+:: $permission-level: levels of permissions in increasing order
+::
+:: %no: May not add/remove node
+:: %self: May only nodes beneath nodes that were added by
+:: the same pilot, may remove nodes that the pilot 'owns'
+:: %yes: May add a node or remove node
++$ permission-level
+ ?(%no %self %yes)
+::
+:: %graph-store types version 2
+::
+++ two
+ =< [. post-one]
+ =, post-one
+ |%
+ +$ maybe-post (each post hash)
+ ++ orm ((on atom node) gth)
+ ++ orm-log ((on time logged-update) gth)
+ ::
+ +$ graph ((mop atom node) gth)
+ +$ marked-graph [p=graph q=(unit mark)]
+ ::
+ +$ node [post=maybe-post children=internal-graph]
+ +$ graphs (map resource marked-graph)
+ ::
+ +$ tag-queries (jug term resource)
+ ::
+ +$ update-log ((mop time logged-update) gth)
+ +$ update-logs (map resource update-log)
+ ::
+ +$ internal-graph
+ $~ [%empty ~]
+ $% [%graph p=graph]
+ [%empty ~]
+ ==
+ ::
+ +$ network
+ $: =graphs
+ =tag-queries
+ =update-logs
+ archive=graphs
+ validators=(set mark)
+ ==
+ ::
+ +$ update [p=time q=action]
+ ::
+ +$ logged-update [p=time q=logged-action]
+ ::
+ +$ logged-action
+ $% [%add-graph =resource =graph mark=(unit mark) overwrite=?]
+ [%add-nodes =resource nodes=(map index node)]
+ [%remove-nodes =resource indices=(set index)]
+ [%add-signatures =uid =signatures]
+ [%remove-signatures =uid =signatures]
+ ==
+ ::
+ +$ action
+ $% logged-action
+ [%remove-graph =resource]
+ ::
+ [%add-tag =term =resource]
+ [%remove-tag =term =resource]
+ ::
+ [%archive-graph =resource]
+ [%unarchive-graph =resource]
+ [%run-updates =resource =update-log]
+ ::
+ :: NOTE: cannot be sent as pokes
+ ::
+ [%keys =resources]
+ [%tags tags=(set term)]
+ [%tag-queries =tag-queries]
+ ==
+ --
+::
+:: %graph-store types version 1
+::
+++ one
+ =< [. post-one]
+ =, post-one
+ |%
+ ++ orm ((on atom node) gth)
+ ++ orm-log ((on time logged-update) gth)
+ ::
+ +$ graph ((mop atom node) gth)
+ +$ marked-graph [p=graph q=(unit mark)]
+ ::
+ +$ node [=post children=internal-graph]
+ +$ graphs (map resource marked-graph)
+ ::
+ +$ tag-queries (jug term resource)
+ ::
+ +$ update-log ((mop time logged-update) gth)
+ +$ update-logs (map resource update-log)
+ ::
+ +$ internal-graph
+ $~ [%empty ~]
+ $% [%graph p=graph]
+ [%empty ~]
+ ==
+ ::
+ +$ network
+ $: =graphs
+ =tag-queries
+ =update-logs
+ archive=graphs
+ validators=(set mark)
+ ==
+ ::
+ +$ update [p=time q=action]
+ ::
+ +$ logged-update [p=time q=logged-action]
+ ::
+ +$ logged-action
+ $% [%add-graph =resource =graph mark=(unit mark) overwrite=?]
+ [%add-nodes =resource nodes=(map index node)]
+ [%remove-nodes =resource indices=(set index)]
+ [%add-signatures =uid =signatures]
+ [%remove-signatures =uid =signatures]
+ ==
+ ::
+ +$ action
+ $% logged-action
+ [%remove-graph =resource]
+ ::
+ [%add-tag =term =resource]
+ [%remove-tag =term =resource]
+ ::
+ [%archive-graph =resource]
+ [%unarchive-graph =resource]
+ [%run-updates =resource =update-log]
+ ::
+ :: NOTE: cannot be sent as pokes
+ ::
+ [%keys =resources]
+ [%tags tags=(set term)]
+ [%tag-queries =tag-queries]
+ ==
+ --
+::
+:: %graph-store types version 0
+::
+++ zero
+ =< [. post-zero]
+ =, post-zero
+ |%
+ ++ orm ((ordered-map atom node) gth)
+ ++ orm-log ((ordered-map time logged-update) gth)
+ ::
+ +$ graph ((mop atom node) gth)
+ +$ marked-graph [p=graph q=(unit mark)]
+ ::
+ +$ node [=post children=internal-graph]
+ +$ graphs (map resource marked-graph)
+ ::
+ +$ tag-queries (jug term resource)
+ ::
+ +$ update-log ((mop time logged-update) gth)
+ +$ update-logs (map resource update-log)
+ ::
+ ::
+ +$ internal-graph
+ $~ [%empty ~]
+ $% [%graph p=graph]
+ [%empty ~]
+ ==
+ ::
+ +$ network
+ $: =graphs
+ =tag-queries
+ =update-logs
+ archive=graphs
+ validators=(set mark)
+ ==
+ ::
+ +$ update
+ $% [%0 p=time q=update-0]
+ ==
+ ::
+ +$ logged-update
+ $% [%0 p=time q=logged-update-0]
+ ==
+ ::
+ +$ logged-update-0
+ $% [%add-graph =resource =graph mark=(unit mark) overwrite=?]
+ [%add-nodes =resource nodes=(map index node)]
+ [%remove-nodes =resource indices=(set index)]
+ [%add-signatures =uid =signatures]
+ [%remove-signatures =uid =signatures]
+ ==
+ ::
+ +$ update-0
+ $% logged-update-0
+ [%remove-graph =resource]
+ ::
+ [%add-tag =term =resource]
+ [%remove-tag =term =resource]
+ ::
+ [%archive-graph =resource]
+ [%unarchive-graph =resource]
+ [%run-updates =resource =update-log]
+ ::
+ :: NOTE: cannot be sent as pokes
+ ::
+ [%keys =resources]
+ [%tags tags=(set term)]
+ [%tag-queries =tag-queries]
+ ==
+ --
+--
diff --git a/zod/seax/sur/group-store.hoon b/zod/seax/sur/group-store.hoon
new file mode 100644
index 0000000..5a3931f
--- /dev/null
+++ b/zod/seax/sur/group-store.hoon
@@ -0,0 +1,39 @@
+/- *group, *resource
+^?
+|%
+::
+:: $action: request to change group-store state
+::
+:: %add-group: add a group
+:: %add-members: add members to a group
+:: %remove-members: remove members from a group
+:: %add-tag: add a tag to a set of ships
+:: %remove-tag: remove a tag from a set of ships
+:: %change-policy: change a group's policy
+:: %remove-group: remove a group from the store
+:: %expose: unset .hidden flag
+::
++$ action
+ $% [%add-group =resource =policy hidden=?]
+ [%add-members =resource ships=(set ship)]
+ [%remove-members =resource ships=(set ship)]
+ [%add-tag =resource =tag ships=(set ship)]
+ [%remove-tag =resource =tag ships=(set ship)]
+ [%change-policy =resource =diff:policy]
+ [%remove-group =resource ~]
+ [%expose =resource ~]
+ ==
+:: $update: a description of a processed state change
+::
+:: %initial: describe groups upon new subscription
+::
++$ update
+ $% initial
+ action
+ ==
++$ initial
+ $% [%initial-group =resource =group]
+ [%initial =groups]
+ ==
+--
+
diff --git a/zod/seax/sur/group.hoon b/zod/seax/sur/group.hoon
new file mode 100644
index 0000000..c580649
--- /dev/null
+++ b/zod/seax/sur/group.hoon
@@ -0,0 +1,109 @@
+/- *resource
+::
+^?
+|%
+::
+++ groups-state-one
+ |%
+ +$ groups (map resource group)
+ ::
+ +$ tag $@(group-tag [app=term tag=term])
+ ::
+ +$ tags (jug tag ship)
+ ::
+ +$ group
+ $: members=(set ship)
+ =tags
+ =policy
+ hidden=?
+ ==
+ --
+:: $groups: a mapping from group-ids to groups
+::
++$ groups (map resource group)
+:: $group-tag: an identifier used by groups
+::
+:: These tags should have precise semantics, as they are shared across all
+:: apps.
+::
++$ group-tag ?(role-tag)
+:: $tag: an identifier used to identify a subset of members
+::
+:: Tags may be used and recognised differently across apps.
+:: for example, you could use tags like `%author`, `%bot`, `%flagged`...
+::
++$ tag $@(group-tag [app=term =resource tag=term])
+:: $role-tag: a kind of $group-tag that identifies a privileged user
+::
+:: These roles are
+:: %admin: Administrator, can do everything except delete the group
+:: %moderator: Moderator, can add/remove/ban users
+:: %janitor: Has no special meaning inside group-store,
+:: but may be given additional privileges in other apps.
+::
++$ role-tag
+ ?(%admin %moderator %janitor)
+:: $tags: a mapping from a $tag to the members it identifies
+::
++$ tags (jug tag ship)
+:: $group: description of a group of users
+::
+:: .members: members of the group
+:: .tag-queries: a map of tags to subsets of members
+:: .policy: permissions for the group
+:: .hidden: is group unmanaged
++$ group
+ $: members=(set ship)
+ =tags
+ =policy
+ hidden=?
+ ==
+:: $policy: access control for a group
+::
+++ policy
+ =< policy
+ |%
+ ::
+ +$ policy
+ $% invite
+ open
+ ==
+ :: $diff: change group policy
+ +$ diff
+ $% [%invite diff:invite]
+ [%open diff:open]
+ [%replace =policy]
+ ==
+ :: $invite: allow only invited ships
+ ++ invite
+ =< invite-policy
+ |%
+ ::
+ +$ invite-policy
+ [%invite pending=(set ship)]
+ :: $diff: add or remove invites
+ ::
+ +$ diff
+ $% [%add-invites invitees=(set ship)]
+ [%remove-invites invitees=(set ship)]
+ ==
+ --
+ :: $open: allow all unbanned ships of approriate rank
+ ::
+ ++ open
+ =< open-policy
+ |%
+ ::
+ +$ open-policy
+ [%open ban-ranks=(set rank:title) banned=(set ship)]
+ :: $diff: ban or allow ranks and ships
+ ::
+ +$ diff
+ $% [%allow-ranks ranks=(set rank:title)]
+ [%ban-ranks ranks=(set rank:title)]
+ [%ban-ships ships=(set ship)]
+ [%allow-ships ships=(set ship)]
+ ==
+ --
+ --
+--
diff --git a/zod/seax/sur/groups.hoon b/zod/seax/sur/groups.hoon
new file mode 100644
index 0000000..0c495b8
--- /dev/null
+++ b/zod/seax/sur/groups.hoon
@@ -0,0 +1,364 @@
+/- meta, e=epic
+/- old=group
+/- grp=group-store
+/- metadata-store
+|%
+++ okay `epic:e`2
+++ mar
+ |%
+ ++ act `mark`(rap 3 %group-action '-' (scot %ud okay) ~)
+ ++ upd `mark`(rap 3 %group-update '-' (scot %ud okay) ~)
+ ++ log `mark`(rap 3 %group-log '-' (scot %ud okay) ~)
+ ++ int `mark`(rap 3 %group-init '-' (scot %ud okay) ~)
+ --
+:: $flag: ID for a group
+::
++$ flag (pair ship term)
+::
+:: $nest: ID for a channel, {app}/{ship}/{name}
+::
++$ nest (pair dude:gall flag)
+::
+:: $sect: ID for cabal, similar to a role
+::
++$ sect term
+::
+:: $zone: channel grouping
+::
+:: includes its own metadata for display and keeps the order of
+:: channels within.
+::
+:: zone: the term that represents the ID of a zone
+:: realm: the metadata representing the zone and the order of channels
+:: delta: the set of actions that can be taken on a zone
+:: %add: create a zone
+:: %del: delete the zone
+:: %edit: modify the zone metadata
+:: %mov: reorders the zone in the group
+:: %mov-nest: reorders a channel within the zone
+::
+++ zone
+ =< zone
+ |%
+ +$ zone @tas
+ +$ realm
+ $: met=data:meta
+ ord=(list nest)
+ ==
+ +$ diff (pair zone delta)
+ +$ delta
+ $% [%add meta=data:meta]
+ [%del ~]
+ [%edit meta=data:meta]
+ [%mov idx=@ud]
+ [%mov-nest =nest idx=@ud]
+ ==
+ --
+::
+:: $fleet: group members and their associated metadata
+::
+:: vessel: a user's set of sects or roles and the time that they joined
+:: @da default represents an admin added member that has yet to join
+::
+++ fleet
+ =< fleet
+ |%
+ +$ fleet (map ship vessel)
+ +$ vessel
+ $: sects=(set sect)
+ joined=time
+ ==
+ +$ diff
+ $% [%add ~]
+ [%del ~]
+ [%add-sects sects=(set sect)]
+ [%del-sects sects=(set sect)]
+ ==
+ --
+::
+:: $channel: a medium for interaction
+::
+++ channel
+ =< channel
+ |%
+ +$ preview
+ $: =nest
+ meta=data:meta
+ group=^preview
+ ==
+ ::
+ +$ channels (map nest channel)
+ ::
+ :: $channel: a collection of metadata about a specific agent integration
+ ::
+ :: meta: title, description, image, cover
+ :: added: when the channel was created
+ :: zone: what zone or section to bucket in
+ :: join: should the channel be joined by new members
+ :: readers: what sects can see the channel, empty means anyone
+ ::
+ +$ channel
+ $: meta=data:meta
+ added=time
+ =zone
+ join=?
+ readers=(set sect)
+ ==
+ ::
+ :: $diff: represents the set of actions you can take on a channel
+ ::
+ :: add: create a channel
+ :: edit: edit a channel
+ :: del: delete a channel
+ :: add-sects: add sects to readers
+ :: del-sects: delete sects from readers
+ :: zone: change the zone of the channel
+ :: join: toggle default join
+ ::
+ +$ diff
+ $% [%add =channel]
+ [%edit =channel]
+ [%del ~]
+ ::
+ [%add-sects sects=(set sect)]
+ [%del-sects sects=(set sect)]
+ ::
+ [%zone =zone]
+ ::
+ [%join join=_|]
+ ==
+ --
+::
+:: $group: collection of people and the pathways in which they interact
+::
+:: group holds all data around members, permissions, channel
+:: organization, and its own metadata to represent the group
+::
++$ group
+ $: =fleet
+ cabals=(map sect cabal)
+ zones=(map zone realm:zone)
+ zone-ord=(list zone)
+ =bloc
+ =channels:channel
+ imported=(set nest)
+ =cordon
+ secret=?
+ meta=data:meta
+ ==
+::
++$ group-ui [group saga=(unit saga:e)]
+:: $cabal: metadata representing a $sect or role
+::
+++ cabal
+ =< cabal
+ |%
+ ::
+ +$ cabal
+ [meta=data:meta ~]
+ ::
+ +$ diff
+ $% [%add meta=data:meta]
+ [%edit meta=data:meta]
+ [%del ~]
+ ==
+ --
+::
+:: $cordon: group entry and visibility permissions
+::
+++ cordon
+ =< cordon
+ |%
+ ::
+ :: $open: a group with open entry, only bans are barred entry
+ ::
+ ++ open
+ |%
+ :: $ban: set of ships and ranks/classes that are not allowed entry
+ ::
+ :: bans can either be done at the individual ship level or by the
+ :: rank level (comet/moon/etc.)
+ ::
+ +$ ban [ships=(set ship) ranks=(set rank:title)]
+ +$ diff
+ $% [%add-ships p=(set ship)]
+ [%del-ships p=(set ship)]
+ ::
+ [%add-ranks p=(set rank:title)]
+ [%del-ranks p=(set rank:title)]
+ ==
+ --
+ ::
+ :: $shut: a group with closed entry, everyone barred entry
+ ::
+ :: a shut cordon means that the group is closed, but still visible.
+ :: people may request entry and either be accepted or denied or
+ :: they may be invited directly
+ ::
+ :: ask: represents those requesting entry
+ :: pending: represents those who've been invited
+ ::
+ ++ shut
+ |%
+ +$ state [pend=(set ship) ask=(set ship)]
+ +$ kind ?(%ask %pending)
+ +$ diff
+ $% [%add-ships p=kind q=(set ship)]
+ [%del-ships p=kind q=(set ship)]
+ ==
+ --
+ ::
+ :: $cordon: a set of metadata to represent the entry policy for a group
+ ::
+ :: open: a group with open entry, only bans barred entry
+ :: shut: a group with closed entry, everyone barred entry
+ :: afar: a custom entry policy defined by another agent
+ ::
+ +$ cordon
+ $% [%shut state:shut]
+ [%afar =flag =path desc=@t]
+ [%open =ban:open]
+ ==
+ ::
+ :: $diff: the actions you can take on a cordon
+ ::
+ +$ diff
+ $% [%shut p=diff:shut]
+ [%open p=diff:open]
+ [%swap p=cordon]
+ ==
+ --
+::
+:: $bloc: superuser sects
+::
+:: sects in the bloc set are allowed to make modifications to the group
+:: and its various metadata and permissions
+::
+++ bloc
+ =< bloc
+ |%
+ +$ bloc (set sect)
+ +$ diff
+ $% [%add p=(set sect)]
+ [%del p=(set sect)]
+ ==
+ --
+::
+:: $diff: the general set of changes that can be made to a group
+::
++$ diff
+ $% [%fleet p=(set ship) q=diff:fleet]
+ [%cabal p=sect q=diff:cabal]
+ [%channel p=nest q=diff:channel]
+ [%bloc p=diff:bloc]
+ [%cordon p=diff:cordon]
+ [%zone p=diff:zone]
+ [%meta p=data:meta]
+ [%secret p=?]
+ [%create p=group]
+ [%del ~]
+ ==
+::
+:: $action: the complete set of data required to edit a group
+::
++$ action
+ (pair flag update)
+::
+:: $update: a representation in time of a modification of a group
+::
++$ update
+ (pair time diff)
+::
+:: $create: a request to make a group
+::
++$ create
+ $: name=term
+ title=cord
+ description=cord
+ image=cord
+ cover=cord
+ =cordon
+ members=(jug ship sect)
+ secret=?
+ ==
+::
++$ init [=time =group]
+::
+:: $groups-ui: map for frontend to display groups
++$ groups-ui
+ (map flag group-ui)
++$ groups
+ (map flag group)
++$ net-groups
+ (map flag [net group])
+::
+:: $log: a time ordered map of all modifications to groups
+::
++$ log
+ ((mop time diff) lte)
+::
+++ log-on
+ ((on time diff) lte)
+::
+:: $net: an indicator of whether I'm a host or subscriber
+::
++$ net
+ $~ [%pub ~]
+ $% [%pub p=log]
+ [%sub p=time load=_| =saga:e]
+ ==
+::
+:: $join: a join request, can elect to join all channels
+::
++$ join
+ $: =flag
+ join-all=?
+ ==
+::
+:: $knock: a request to enter a closed group
+::
++$ knock flag
+::
+:: $progress: the state of a group join
+::
++$ progress
+ ?(%knocking %adding %watching %done %error)
+::
+:: $claim: a mark for gangs to represent a join in progress
+::
++$ claim
+ $: join-all=?
+ =progress
+ ==
+::
+:: $preview: the metadata and entry policy for a group
+::
++$ preview
+ $: =flag
+ meta=data:meta
+ =cordon
+ =time
+ secret=?
+ ==
+::
++$ previews (map flag preview)
+::
+:: $invite: a marker to show you've been invited to a group
+::
++$ invite (pair flag ship)
+::
+:: $gang: view of foreign group
+::
++$ gang
+ $: cam=(unit claim)
+ pev=(unit preview)
+ vit=(unit invite)
+ ==
+::
++$ gangs (map flag gang)
+++ met metadata-store
+::
++$ import [self=association:met chan=(map flag =association:met) roles=(set flag) =group:old]
+::
++$ imports (map flag import)
+--
diff --git a/zod/seax/sur/meta.hoon b/zod/seax/sur/meta.hoon
new file mode 100644
index 0000000..d8abbfa
--- /dev/null
+++ b/zod/seax/sur/meta.hoon
@@ -0,0 +1,21 @@
+|%
+:: $data: generic metadata for various entities
+::
+:: title: the pretty text representing what something is called
+:: description: a longer text entry giving a detailed summary
+:: image: an image URL or color string used as an icon/avatar
+:: cover: an image URL or color string, used as a header
+::
++$ data
+ $: title=cord
+ description=cord
+ image=cord
+ cover=cord
+ ==
++$ diff
+ $% [%title =cord]
+ [%description =cord]
+ [%image =cord]
+ [%cover =cord]
+ ==
+--
diff --git a/zod/seax/sur/metadata-store.hoon b/zod/seax/sur/metadata-store.hoon
new file mode 100644
index 0000000..9979f3e
--- /dev/null
+++ b/zod/seax/sur/metadata-store.hoon
@@ -0,0 +1,138 @@
+/- *resource
+^?
+|%
+::
++$ app-name term
++$ md-resource [=app-name =resource]
++$ association [group=resource =metadatum]
++$ associations (map md-resource association)
++$ group-preview
+ $: group=resource
+ channels=associations
+ members=@ud
+ channel-count=@ud
+ =metadatum
+ ==
+::
++$ color @ux
++$ url @t
+::
+:: $vip-metadata: variation in permissions
+::
+:: This will be passed to the graph-permissions mark
+:: conversion to allow for custom permissions.
+::
+:: %reader-comments: Allow readers to comment, regardless
+:: of whether they can write. (notebook, collections)
+:: %member-metadata: Allow members to add channels (groups)
+:: %host-feed: Only host can post to group feed
+:: %admin-feed: Only admins and host can post to group feed
+:: %$: No variation
+::
++$ vip-metadata
+ $? %reader-comments
+ %member-metadata
+ %host-feed
+ %admin-feed
+ %$
+ ==
+::
++$ md-config
+ $~ [%empty ~]
+ $% [%group feed=(unit (unit md-resource))]
+ [%graph module=term]
+ [%empty ~]
+ ==
+::
++$ edit-field
+ $% [%title title=cord]
+ [%description description=cord]
+ [%color color=@ux]
+ [%picture =url]
+ [%preview preview=?]
+ [%hidden hidden=?]
+ [%vip vip=vip-metadata]
+ ==
+::
++$ metadatum
+ $: title=cord
+ description=cord
+ =color
+ date-created=time
+ creator=ship
+ config=md-config
+ picture=url
+ preview=?
+ hidden=?
+ vip=vip-metadata
+ ==
+::
++$ action
+ $% [%add group=resource resource=md-resource =metadatum]
+ [%remove group=resource resource=md-resource]
+ [%edit group=resource resource=md-resource =edit-field]
+ [%initial-group group=resource =associations]
+ ==
+::
++$ hook-update
+ $% [%req-preview group=resource]
+ [%preview group-preview]
+ ==
+::
++$ update
+ $% action
+ [%associations =associations]
+ $: %updated-metadata
+ group=resource
+ resource=md-resource
+ before=metadatum
+ =metadatum
+ ==
+ ==
+:: historical
+++ one
+ |%
+ ::
+ +$ action
+ $~ [%remove *resource *md-resource]
+ $< %edit ^action
+ ::
+ +$ update
+ $~ [%remove *resource *md-resource]
+ $< %edit ^update
+ ::
+ --
+++ zero
+ |%
+ ::
+ +$ association [group=resource =metadatum]
+ ::
+ +$ associations (map md-resource association)
+ ::
+ +$ metadatum
+ $: title=cord
+ description=cord
+ =color
+ date-created=time
+ creator=ship
+ module=term
+ picture=url
+ preview=?
+ vip=vip-metadata
+ ==
+ ::
+ +$ update
+ $% [%add group=resource resource=md-resource =metadatum]
+ [%remove group=resource resource=md-resource]
+ [%initial-group group=resource =associations]
+ [%associations =associations]
+ $: %updated-metadata
+ group=resource
+ resource=md-resource
+ before=metadatum
+ =metadatum
+ ==
+ ==
+ ::
+ --
+--
diff --git a/zod/seax/sur/notes.hoon b/zod/seax/sur/notes.hoon
new file mode 100644
index 0000000..41fe116
--- /dev/null
+++ b/zod/seax/sur/notes.hoon
@@ -0,0 +1,74 @@
+|%
++$ diary
+ $: *
+ *
+ *
+ *
+ *
+ =notes
+ *
+ ==
++$ seal
+ $: =time
+ * :: =quips
+ * :: feels=(map ship feel)
+ ==
++$ note [seal essay]
++$ verse
+ $% [%block p=block]
+ [%inline p=(list inline)]
+ ==
++$ listing
+ $% [%list p=?(%ordered %unordered) q=(list listing) r=(list inline)]
+ [%item p=(list inline)]
+ ==
++$ block
+ $% [%image src=cord height=@ud width=@ud alt=cord]
+ [%cite *] :: =cite:c]
+ [%header p=?(%h1 %h2 %h3 %h4 %h5 %h6) q=(list inline)]
+ [%listing p=listing]
+ [%rule ~]
+ [%code code=cord lang=cord]
+ ==
++$ inline
+ $@ @t
+ $% [%italics p=(list inline)]
+ [%bold p=(list inline)]
+ [%strike p=(list inline)]
+ [%blockquote p=(list inline)]
+ [%inline-code p=cord]
+ [%ship p=ship]
+ [%block p=@ud q=cord]
+ [%code p=cord]
+ [%tag p=cord]
+ [%link p=cord q=cord]
+ [%break ~]
+ ==
++$ essay
+ $: title=@t
+ image=@t
+ content=(list verse)
+ author=ship
+ sent=time
+ ==
+++ notes
+ =< rock
+ |%
+ +$ rock
+ ((mop time note) lte)
+ ++ on
+ ((^on time note) lte)
+ +$ diff
+ (pair time delta)
+ +$ delta
+ $% [%add p=essay]
+ [%edit p=essay]
+ [%del ~]
+ [%quips *] :: p=diff:quips]
+ [%add-feel p=ship *] :: q=feel]
+ [%del-feel p=ship]
+ ==
+ --
++$ shelf (map flag diary)
++$ flag (pair ship term)
+--
diff --git a/zod/seax/sur/post.hoon b/zod/seax/sur/post.hoon
new file mode 100644
index 0000000..2dacb65
--- /dev/null
+++ b/zod/seax/sur/post.hoon
@@ -0,0 +1,91 @@
+/- *resource
+|%
++$ index (list atom)
++$ uid [=resource =index]
+::
+:: +sham (half sha-256) hash of +validated-portion
++$ hash @ux
+::
++$ signature [p=@ux q=ship r=life]
++$ signatures (set signature)
++$ post
+ $: author=ship
+ =index
+ time-sent=time
+ contents=(list content)
+ hash=(unit hash)
+ =signatures
+ ==
+::
++$ indexed-post [a=atom p=post]
+::
++$ validated-portion
+ $: parent-hash=(unit hash)
+ author=ship
+ time-sent=time
+ contents=(list content)
+ ==
+::
++$ reference
+ $% [%graph group=resource =uid]
+ [%group group=resource]
+ [%app =ship =desk =path]
+ ==
+::
++$ content
+ $% [%text text=cord]
+ [%mention =ship]
+ [%url url=cord]
+ [%code expression=cord output=(list tank)]
+ [%reference =reference]
+ ==
+::
+++ post-one
+ |%
+ ::
+ +$ indexed-post [a=atom p=post]
+ ::
+ +$ post
+ $: author=ship
+ =index
+ time-sent=time
+ contents=(list content)
+ hash=(unit hash)
+ =signatures
+ ==
+ ::
+ +$ content
+ $% [%text text=cord]
+ [%mention =ship]
+ [%url url=cord]
+ [%code expression=cord output=(list tank)]
+ [%reference =reference]
+ ==
+ ::
+ +$ reference
+ $% [%graph group=resource =uid]
+ [%group group=resource]
+ ==
+ --
+::
+++ post-zero
+ |%
+ ::
+ +$ content
+ $% [%text text=cord]
+ [%mention =ship]
+ [%url url=cord]
+ [%code expression=cord output=(list tank)]
+ [%reference =uid]
+ ==
+ ::
+ +$ post
+ $: author=ship
+ =index
+ time-sent=time
+ contents=(list content)
+ hash=(unit hash)
+ =signatures
+ ==
+ --
+--
diff --git a/zod/seax/sur/resource.hoon b/zod/seax/sur/resource.hoon
new file mode 100644
index 0000000..fef7a7b
--- /dev/null
+++ b/zod/seax/sur/resource.hoon
@@ -0,0 +1,10 @@
+^?
+|%
++$ resource [=entity name=term]
++$ resources (set resource)
+::
++$ entity
+ $@ ship
+ $% !!
+ ==
+--