/- view-sur=group-view, group-store, *group, metadata=metadata-store, hark=hark-store /- inv=invite-store /+ default-agent, agentio, mdl=metadata, resource, dbug, grpl=group, conl=contact, verb |% ++ card card:agent:gall :: :: :: +$ state-zero [%0 *] :: +$ state-one [%1 *] :: +$ state-two [%2 *] :: +$ state-three [%3 joining=(map rid=resource request:view)] :: +$ versioned-state $% state-zero state-one state-two state-three == :: ++ view view-sur -- =| state-three =* state - :: %- agent:dbug %+ verb | ^- agent:gall =< |_ =bowl:gall +* this . def ~(. (default-agent this %|) bowl) gc ~(. +> bowl) io ~(. agentio bowl) ++ on-init `this ++ on-save !>(state) :: ++ on-load |= =vase =+ !<(old=versioned-state vase) =| cards=(list card) |- ?: ?=(%3 -.old) [cards this(state old)] $(old *state-three) :: ++ on-poke |= [=mark =vase] ^- (quip card _this) ?: ?=(%noun mark) =^ cards state poke-noun:gc [cards this] ?. ?=(%group-view-action mark) (on-poke:def mark vase) =+ !<(=action:view vase) =^ cards state ?+ -.action !! %join jn-abet:(jn-start:join:gc +.action) %abort jn-abet:(jn-abort:join:gc +.action) %done jn-abet:(jn-done:join:gc +.action) == [cards this] :: ++ on-watch |= =path ?+ path (on-watch:def path) [%all ~] :_ this :_ ~ %+ fact:io :- %group-view-update !>(`update:view`[%initial joining]) ~ == :: ++ on-peek on-peek:def :: ++ on-agent |= [=wire =sign:agent:gall] =^ cards state ?+ wire (on-agent:def:gc wire sign) [%join %ship @ @ *] =/ rid (de-path:resource t.wire) ?. (~(has by joining) rid) `state jn-abet:(jn-agent:(jn-abed:join:gc rid) t.t.t.t.wire sign) == [cards this] :: ++ on-arvo |= [=wire sign=sign-arvo] =^ cards state ?+ wire (on-arvo:def:gc wire sign) [%breach ~] ?> ?=([%jael %public-keys *] sign) ?. ?=(%breach -.public-keys-result.sign) `state (breach who.public-keys-result.sign) == [cards this] :: ++ on-leave on-leave:def ++ on-fail on-fail:def -- |_ =bowl:gall ++ met ~(. mdl bowl) ++ grp ~(. grpl bowl) ++ io ~(. agentio bowl) ++ con ~(. conl bowl) ++ def ~(. (default-agent state %|) bowl) ++ hide |= rid=resource ^- (quip card _state) =/ =request:view (~(got by joining) rid) ?: ?=(final:view progress.request) =. joining (~(del by joining) rid) :_ state (fact:io group-view-update+!>(`update:view`[%initial joining]) /all ~)^~ :- (fact:io group-view-update+!>([%hide rid]) /all ~)^~ state(joining (~(put by joining) rid request)) :: ++ is-tracking |= her=ship ^- ? %+ lien ~(tap in ~(key by joining)) |=([him=ship name=term] =(her him)) :: ++ breach |= who=ship ^- (quip card _state) =/ requests=(list [rid=resource =request:view]) ~(tap by joining) =| cards=(list card) |- ^- (quip card _state) ?~ requests [cards state] ?. =(entity.rid.i.requests who) $(requests t.requests) =^ crds state jn-abet:jn-breach:(jn-abed:join rid.i.requests) [(welp cards crds) state] :: ++ has-joined |= rid=resource =- ?=(^ -) ?~ grp=(peek-group:met %groups rid) (peek-group:met %graph rid) grp :: ++ poke-noun ^- (quip card _state) =; new-joining=(map resource request:view) `state(joining new-joining) %+ roll ~(tap by joining) |= [[rid=resource =request:view] out=_joining] ?. (has-joined rid) out (~(del by out) rid) :: ++ join |_ [rid=resource =ship cards=(list card)] ++ jn-core . ++ emit-many |= crds=(list card) jn-core(cards (weld (flop crds) cards)) :: ++ emit |= =card jn-core(cards [card cards]) :: ++ tx-progress |= =progress:view =. joining (~(jab by joining) rid |=(req=request:view req(progress progress))) =; =cage (emit (fact:io cage /all tx+(en-path:resource rid) ~)) group-view-update+!>([%progress rid progress]) :: ++ pass |% ++ pull-action pull-hook-action+!>([%add ship rid]) :: ++ listen-hark |= gr=resource %+ poke-our:pass:io %hark-graph-hook hark-graph-hook-action+!>([%listen gr /]) :: ++ watch-md (watch-our:(jn-pass-io /md) %metadata-store /updates) ++ watch-groups (watch-our:(jn-pass-io /groups) %group-store /groups) ++ watch-md-nacks (watch-our:(jn-pass-io /md-nacks) %metadata-pull-hook /nack) ++ watch-grp-nacks (watch-our:(jn-pass-io /grp-nacks) %group-pull-hook /nack) :: ++ add-us %+ poke:(jn-pass-io /add) [ship %group-push-hook] group-update-0+!>([%add-members rid (silt our.bowl ~)]) :: ++ del-us %+ poke:pass:io [ship %group-push-hook] group-update-0+!>([%remove-members rid (silt our.bowl ~)]) :: ++ remove-pull-groups (poke-our:pass:io %group-pull-hook pull-hook-action+!>([%remove rid])) :: ++ pull-groups (poke-our:(jn-pass-io /poke) %group-pull-hook pull-action) ++ pull-md (poke-our:(jn-pass-io /poke) %metadata-pull-hook pull-action) ++ pull-co (poke-our:(jn-pass-io /poke) %contact-pull-hook pull-action) :: ++ allow-co %+ poke-our:(jn-pass-io /poke) %contact-store contact-update-0+!>([%allow %group rid]) :: ++ share-co %+ poke:(jn-pass-io /poke) [entity.rid %contact-push-hook] [%contact-share !>([%share our.bowl])] :: ++ pull-gra |= gr=resource (poke-our:(jn-pass-io /poke) %graph-pull-hook pull-hook-action+!>([%add entity .]:gr)) :: ++ retry (poke-self:pass:io group-view-action+!>([%join rid ship])) ++ watch-breach (~(arvo pass:io /breach) %j %public-keys (silt ship ~)) ++ leave-breach (~(arvo pass:io /breach) %j %nuke (silt ship ~)) -- ++ jn-pass-io |= pax=path ~(. pass:io (welp join+(en-path:resource rid) pax)) :: ++ jn-abed |= r=resource =/ =request:view (~(got by joining) r) jn-core(rid r, ship ship.request) :: ++ jn-abet ^- (quip card _state) [(flop cards) state] :: ++ jn-start |= [rid=resource =^ship =app:view share-co=? autojoin=?] ^+ jn-core ?> ?= $@(~ [~ ?(%done %abort)]) (bind (~(get by joining) rid) |=(request:view progress)) =/ =request:view [now.bowl ship %start app share-co autojoin (get-invites app rid)] =. joining (~(put by joining) rid request) =. jn-core (jn-abed rid) =. jn-core %- emit %+ fact:io group-view-update+!>([%started rid (~(got by joining) rid)]) ~[/all] ?< ~|("already joined {<rid>}" (has-joined rid)) =. jn-core (emit add-us:pass) =. jn-core (tx-progress %start) =? jn-core !(is-tracking ship) (emit watch-breach:pass) => (emit watch-md:pass) => (emit watch-groups:pass) => (emit watch-grp-nacks:pass) => (emit watch-md-nacks:pass) (emit watch-breach:pass) :: ++ jn-breach =/ =request:view (~(got by joining) rid) ?. ?=(%start progress.request) :: no action required, subscriptions are sane across breaches jn-core (emit add-us:pass) :: ++ jn-abort |= r=resource ^+ jn-core =. jn-core (jn-abed r) (cleanup:rollback %abort) :: ++ jn-done |= r=resource =. joining (~(del by joining) r) jn-core :: ++ rollback |^ =/ =request:view (~(got by joining) rid) ?+ progress.request ~|(cannot-rollback/progress.request !!) %start start %added added %metadata metadata ?(%no-perms %strange %abort) error == ++ error jn-core ++ start jn-core ++ added (emit del-us:pass) ++ metadata (emit:added remove-pull-groups:pass) -- :: ++ get-invites |= [=app:view rid=resource] ^- (set uid:view) =+ .^(invit=(unit invitatory:inv) %gx (scry:io %invite-store /invitatory/[app]/noun)) ?~ invit ~ %- ~(gas in *(set uid:view)) %+ murn ~(tap by u.invit) |= [=uid:view =invite:inv] ?. =(rid resource.invite) ~ `uid :: ++ cleanup |= =progress:view =. jn-core (tx-progress progress) =. jn-core (emit (leave-our:(jn-pass-io /groups) %group-store)) =. jn-core (emit (leave-our:(jn-pass-io /md) %metadata-store)) =. jn-core (emit (leave-our:(jn-pass-io /md-nacks) %metadata-pull-hook)) =. jn-core (emit (leave-our:(jn-pass-io /grp-nacks) %group-pull-hook)) =/ =request:view (~(got by joining) rid) =. jn-core %- emit-many %+ turn ~(tap in invite.request) |= =uid:view %+ poke-our:pass:io %invite-store =- invite-action+!>(-) ^- action:inv [%accept `@tas`app.request uid] jn-core :: ++ jn-agent |= [=wire =sign:agent:gall] ^+ jn-core |^ ?+ -.wire ~|("bad %join wire" !!) %add :: join group ?> ?=(%poke-ack -.sign) ?^ p.sign (cleanup %no-perms) =. jn-core (tx-progress %added) (emit pull-groups:pass) :: %groups ?+ -.sign !! %fact (groups-fact +.sign) %watch-ack (ack +.sign) %kick (emit watch-groups:pass) == :: %poke ?> ?=(%poke-ack -.sign) (ack +.sign) :: %md ?+ -.sign !! %fact (md-fact +.sign) %watch-ack (ack +.sign) %kick (emit watch-md:pass) == :: %pull-graphs ?> ?=(%poke-ack -.sign) %- cleanup ?^(p.sign %strange %done) :: %md-nacks ?+ -.sign !! %watch-ack (ack +.sign) %kick (emit watch-md-nacks:pass) :: %fact ?. =(%resource p.cage.sign) jn-core =+ !<(nack=resource q.cage.sign) ?. =(nack rid) jn-core (cleanup %strange) == :: %grp-nacks ?+ -.sign !! %watch-ack (ack +.sign) %kick (emit watch-grp-nacks:pass) :: %fact ?. =(%resource p.cage.sign) jn-core =+ !<(nack=resource q.cage.sign) ?. =(nack rid) jn-core (cleanup %strange) == == :: ++ groups-fact |= =cage ?. ?=(%group-update-0 p.cage) jn-core =+ !<(=update:group-store q.cage) ?. ?=(%initial-group -.update) jn-core =/ =request:view (~(got by joining) rid) ?. =(rid resource.update) jn-core =. jn-core (emit pull-md:pass) =. jn-core (emit pull-co:pass) ?. |(share-co.request scry-is-public:con) jn-core ?: scry-is-public:con (emit share-co:pass) =. jn-core (emit allow-co:pass) (emit share-co:pass) :: ++ md-fact |= [=mark =vase] ?. ?=(%metadata-update-2 mark) jn-core =+ !<(=update:metadata vase) ?. ?=(%initial-group -.update) jn-core ?. =(group.update rid) jn-core |^ ^+ jn-core =/ =request:view (~(got by joining) rid) =/ feed feed-rid =. jn-core (cleanup %done) =/ hidden hidden:(need (scry-group:grp rid)) =? jn-core ?&(!hidden ?=(^ feed)) %- emit (pull-gra:pass (need feed)) =? jn-core |(hidden autojoin.request) %- emit-many (turn graphs pull-gra:pass) =? jn-core hidden %- emit-many (turn graphs listen-hark:pass) jn-core :: ++ feed-rid ^- (unit resource) =/ list-md=(list [=md-resource:metadata =association:metadata]) %+ skim ~(tap by associations.update) |= [=md-resource:metadata =association:metadata] =(app-name.md-resource %groups) ?~ list-md ~ =* metadatum metadatum.association.i.list-md ?. ?& ?=(%group -.config.metadatum) ?=([~ ~ *] feed.config.metadatum) == ~ `resource.u.u.feed.config.metadatum :: ++ graphs ^- (list resource) %+ murn ~(tap by associations.update) |= [=md-resource:metadata =association:metadata] ?. =(app-name.md-resource %graph) ~ `resource.md-resource -- :: ++ ack |= err=(unit tang) ?~ err jn-core %- (slog u.err) (cleanup %strange) :: -- -- --