Much work on error reporting architecture for validation

This commit is contained in:
Simon Brooke 2022-12-21 17:30:26 +00:00
parent 5593bb22d1
commit 25795cf364
43 changed files with 2024 additions and 1067 deletions

View file

@ -65,6 +65,10 @@ At present, only the duck-typing functions work. To play with them, use
(require '[dog-and-duck.quack.quack :as q])
```
## Documentation
Full documentation is [here](https://simon-brooke.github.io/dog-and-duck/).
## Testing
Prior to testing, you should clone [activitystreams-test-documents](https://github.com/w3c-social/activitystreams-test-documents) into the `resources` directory. You can then test with

View file

@ -1,112 +1,5 @@
# Using ActivityPub
```clojure
user=> (require '[clj-activitypub.core :as activitypub])
nil
user=> (require '[clj-activitypub.webfinger :as webfinger])
nil
user=> (require '[clojure.walk :refer [keywordize-keys]])
nil
user=> (require '[clojure.pprint :refer [pprint]])
nil
user=> (def base-domain "mastodon.scot")
#'user/base-domain
user=> (def account-handle "@simon_brooke@mastodon.scot")
#'user/account-handle
user=> (in-ns 'user)
#object[clojure.lang.Namespace 0x525575 "user"]
user=> (activitypub/parse-account account-handle )
{:domain "mastodon.scot", :username "simon_brooke"}
user=> (map *1 [:domain :username])
("mastodon.scot" "simon_brooke")
user=> (apply webfinger/fetch-user-id *1)
"https://mastodon.scot/users/simon_brooke"
user=> (activitypub/fetch-user *1)
{"followers" "https://mastodon.scot/users/simon_brooke/followers", "inbox" "https://mastodon.scot/users/simon_brooke/inbox", "url" "https://mastodon.scot/@simon_brooke", "@context" ["https://www.w3.org/ns/activitystreams" "https://w3id.org/security/v1" {"identityKey" {"@type" "@id", "@id" "toot:identityKey"}, "EncryptedMessage" "toot:EncryptedMessage", "Ed25519Key" "toot:Ed25519Key", "devices" {"@type" "@id", "@id" "toot:devices"}, "manuallyApprovesFollowers" "as:manuallyApprovesFollowers", "schema" "http://schema.org#", "PropertyValue" "schema:PropertyValue", "Curve25519Key" "toot:Curve25519Key", "claim" {"@type" "@id", "@id" "toot:claim"}, "value" "schema:value", "Hashtag" "as:Hashtag", "movedTo" {"@id" "as:movedTo", "@type" "@id"}, "discoverable" "toot:discoverable", "messageType" "toot:messageType", "messageFranking" "toot:messageFranking", "cipherText" "toot:cipherText", "toot" "http://joinmastodon.org/ns#", "alsoKnownAs" {"@id" "as:alsoKnownAs", "@type" "@id"}, "featured" {"@id" "toot:featured", "@type" "@id"}, "featuredTags" {"@id" "toot:featuredTags", "@type" "@id"}, "Ed25519Signature" "toot:Ed25519Signature", "focalPoint" {"@container" "@list", "@id" "toot:focalPoint"}, "fingerprintKey" {"@type" "@id", "@id" "toot:fingerprintKey"}, "Device" "toot:Device", "publicKeyBase64" "toot:publicKeyBase64", "deviceId" "toot:deviceId", "suspended" "toot:suspended"}], "devices" "https://mastodon.scot/users/simon_brooke/collections/devices", "manuallyApprovesFollowers" false, "image" {"type" "Image", "mediaType" "image/jpeg", "url" "https://media.mastodon.scot/mastodon-scot-public/accounts/headers/109/252/274/874/045/781/original/e1f1823c4361fa27.jpg"}, "endpoints" {"sharedInbox" "https://mastodon.scot/inbox"}, "id" "https://mastodon.scot/users/simon_brooke", "publicKey" {"id" "https://mastodon.scot/users/simon_brooke#main-key", "owner" "https://mastodon.scot/users/simon_brooke", "publicKeyPem" "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2/6GgLJgJlPhhqFm1tUQ\noSLnWxhDwq4HlZIHrBsVjkSvUAnHKqq42Q/hta+fkWB8rmTFpmjLXDj/Fi0uejvT\nBc+KrLwfX/yR8+G87afGCRS3CaumoLJ7zkBIlsFzIKMoIke1D3QuHX95yGGXs+hp\nmyxt/+CXRyZjK7u9NG7SMRUlpwvOlpD12Aei35Nb8NSr03JvY8/WVMIbWrecyI0b\nAlwj6axxHx7J15Yo+aEtKzZ2OFKXf+sh0QF9BEnYcmVKYlR6kiOglLFHKdCBUSYi\ni9Flv00TydqlGvR5fpShBqORiy0M/FVtNXlz2sNBEsGB2meipkjh+cRLzTbYo4KL\nJwIDAQAB\n-----END PUBLIC KEY-----\n"}, "summary" "<p>Anarcho-syndicalist, autistic, crofter, cyclist, depressive, entrepreneur, geek, Zapatista. Politics &amp; environment, especially <a href=\"https://mastodon.scot/tags/LandReform\" class=\"mention hashtag\" rel=\"tag\">#<span>LandReform</span></a>. he/him.</p><p>Twitter: <span class=\"h-card\"><a href=\"https://mastodon.scot/@simon_brooke\" class=\"u-url mention\">@<span>simon_brooke</span></a></span><br />GitHub: simon-brooke<br />FetLife: Simon_Brooke</p><p>Credo: Life is harsh. What we can do - and what we should do - is strive to make it less harsh for the people around us.</p>", "attachment" [{"type" "PropertyValue", "name" "Home Page", "value" "<a href=\"https://www.journeyman.cc/~simon/\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\"><span class=\"invisible\">https://www.</span><span class=\"\">journeyman.cc/~simon/</span><span class=\"invisible\"></span></a>"}], "name" "Simon Brooke", "tag" [{"type" "Hashtag", "href" "https://mastodon.scot/tags/landreform", "name" "#landreform"}], "published" "2022-10-29T00:00:00Z", "preferredUsername" "simon_brooke", "discoverable" true, "alsoKnownAs" ["https://mastodon.social/users/simon_brooke"], "featured" "https://mastodon.scot/users/simon_brooke/collections/featured", "featuredTags" "https://mastodon.scot/users/simon_brooke/collections/tags", "type" "Person", "outbox" "https://mastodon.scot/users/simon_brooke/outbox", "following" "https://mastodon.scot/users/simon_brooke/following", "icon" {"type" "Image", "mediaType" "image/png", "url" "https://media.mastodon.scot/mastodon-scot-public/accounts/avatars/109/252/274/874/045/781/original/172e8f7530627e87.png"}}
user=> (def sb (keywordize-keys *1))
#'user/sb
user=> (:outbox sb)
"https://mastodon.scot/users/simon_brooke/outbox"
user=> (require '[clojure.data.json :as json])
nil
user=> (slurp (:outbox sb))
Execution error (IOException) at sun.net.www.protocol.http.HttpURLConnection/getInputStream0 (HttpURLConnection.java:1894).
Server returned HTTP response code: 403 for URL: https://mastodon.scot/users/simon_brooke/outbox
user=> (pprint sb)
{:inbox "https://mastodon.scot/users/simon_brooke/inbox",
:name "Simon Brooke",
:@context
["https://www.w3.org/ns/activitystreams"
"https://w3id.org/security/v1"
{:schema "http://schema.org#",
:messageType "toot:messageType",
:messageFranking "toot:messageFranking",
:identityKey {:@type "@id", :@id "toot:identityKey"},
:Hashtag "as:Hashtag",
:deviceId "toot:deviceId",
:publicKeyBase64 "toot:publicKeyBase64",
:value "schema:value",
:Ed25519Key "toot:Ed25519Key",
:featured {:@id "toot:featured", :@type "@id"},
:Curve25519Key "toot:Curve25519Key",
:discoverable "toot:discoverable",
:focalPoint {:@container "@list", :@id "toot:focalPoint"},
:suspended "toot:suspended",
:fingerprintKey {:@type "@id", :@id "toot:fingerprintKey"},
:Ed25519Signature "toot:Ed25519Signature",
:cipherText "toot:cipherText",
:EncryptedMessage "toot:EncryptedMessage",
:alsoKnownAs {:@id "as:alsoKnownAs", :@type "@id"},
:featuredTags {:@id "toot:featuredTags", :@type "@id"},
:devices {:@type "@id", :@id "toot:devices"},
:toot "http://joinmastodon.org/ns#",
:movedTo {:@id "as:movedTo", :@type "@id"},
:Device "toot:Device",
:PropertyValue "schema:PropertyValue",
:manuallyApprovesFollowers "as:manuallyApprovesFollowers",
:claim {:@type "@id", :@id "toot:claim"}}],
:featured
"https://mastodon.scot/users/simon_brooke/collections/featured",
:type "Person",
:discoverable true,
:icon
{:type "Image",
:mediaType "image/png",
:url
"https://media.mastodon.scot/mastodon-scot-public/accounts/avatars/109/252/274/874/045/781/original/172e8f7530627e87.png"},
:following "https://mastodon.scot/users/simon_brooke/following",
:summary
"<p>Anarcho-syndicalist, autistic, crofter, cyclist, depressive, entrepreneur, geek, Zapatista. Politics &amp; environment, especially <a href=\"https://mastodon.scot/tags/LandReform\" class=\"mention hashtag\" rel=\"tag\">#<span>LandReform</span></a>. he/him.</p><p>Twitter: <span class=\"h-card\"><a href=\"https://mastodon.scot/@simon_brooke\" class=\"u-url mention\">@<span>simon_brooke</span></a></span><br />GitHub: simon-brooke<br />FetLife: Simon_Brooke</p><p>Credo: Life is harsh. What we can do - and what we should do - is strive to make it less harsh for the people around us.</p>",
:publicKey
{:id "https://mastodon.scot/users/simon_brooke#main-key",
:owner "https://mastodon.scot/users/simon_brooke",
:publicKeyPem
"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2/6GgLJgJlPhhqFm1tUQ\noSLnWxhDwq4HlZIHrBsVjkSvUAnHKqq42Q/hta+fkWB8rmTFpmjLXDj/Fi0uejvT\nBc+KrLwfX/yR8+G87afGCRS3CaumoLJ7zkBIlsFzIKMoIke1D3QuHX95yGGXs+hp\nmyxt/+CXRyZjK7u9NG7SMRUlpwvOlpD12Aei35Nb8NSr03JvY8/WVMIbWrecyI0b\nAlwj6axxHx7J15Yo+aEtKzZ2OFKXf+sh0QF9BEnYcmVKYlR6kiOglLFHKdCBUSYi\ni9Flv00TydqlGvR5fpShBqORiy0M/FVtNXlz2sNBEsGB2meipkjh+cRLzTbYo4KL\nJwIDAQAB\n-----END PUBLIC KEY-----\n"},
:endpoints {:sharedInbox "https://mastodon.scot/inbox"},
:preferredUsername "simon_brooke",
:id "https://mastodon.scot/users/simon_brooke",
:alsoKnownAs ["https://mastodon.social/users/simon_brooke"],
:outbox "https://mastodon.scot/users/simon_brooke/outbox",
:url "https://mastodon.scot/@simon_brooke",
:featuredTags
"https://mastodon.scot/users/simon_brooke/collections/tags",
:devices
"https://mastodon.scot/users/simon_brooke/collections/devices",
:image
{:type "Image",
:mediaType "image/jpeg",
:url
"https://media.mastodon.scot/mastodon-scot-public/accounts/headers/109/252/274/874/045/781/original/e1f1823c4361fa27.jpg"},
:tag
[{:type "Hashtag",
:href "https://mastodon.scot/tags/landreform",
:name "#landreform"}],
:followers "https://mastodon.scot/users/simon_brooke/followers",
:published "2022-10-29T00:00:00Z",
:manuallyApprovesFollowers false,
:attachment
[{:type "PropertyValue",
:name "Home Page",
:value
"<a href=\"https://www.journeyman.cc/~simon/\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\"><span class=\"invisible\">https://www.</span><span class=\"\">journeyman.cc/~simon/</span><span class=\"invisible\"></span></a>"}]}
```
## Introduction
I do not know what I am doing; I am learning, and playing. Nothing in this document should be treated as good advice; it simply relates to the current state of my knowledge.

61
doc/Validation_Faults.md Normal file
View file

@ -0,0 +1,61 @@
# Validation Faults in ActivityPub documents
## Motivation
This document is intended to provide an extension vocabulary for [ActivityStreams](https://www.w3.org/TR/activitystreams-core/) documents, which provides vocabulary for categorising and describing faults in [ActivityPub](https://www.w3.org/TR/activitypub/) documents.
The motivation is to be able to serialise a validation report on an ActivityPub document as an ActivityStreams document.
## Intepretation
### Conformance
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MAY, MUST, MUST NOT, SHOULD, and SHOULD NOT are to be interpreted as described in [RFC2119].
### 'the spec'
Where the phrase 'the spec' is used in this document, it refers to a concatenation of the ActivityStreams specification and the ActivityPub specification.
## The `Fault` object type
The `Fault` object type is a novel object type introduced by this document to describe validation faults. Objects with the `Fault` object type MUST have at least the following fields (additional fields are not required but are optional):
1. `:@context` whose value shall be the URL of a document specifying this vocabulary;
2. `:type` whose value shall be `Fault`;
3. `:severity` whose value shall be one of `minor`, `should`, `must` or `critical`;
4. `:fault` whose value shall be a unique token representing the particular fault type;
5. `:narrative` whose value shall be a natural language description of the fault type.
### The Fields
#### Context
The value of the `@context` field of a fault report object shall be the URL of this
document, currently `https://simon-brooke.github.io/dog-and-duck/codox/Validation_Faults.html`.
#### Type
The value of the `type` field of a fault report object MUST be `Fault`.
#### Severity
Each fault report object MUST have a `severity` field whose value MUST be one of
1. `:minor` things which I consider to be faults, but which
don't actually breach the spec;
2. `:should` instances where the spec says something SHOULD
be done, which isn't;
3. `:must` instances where the spec says something MUST
be done, which isn't;
4. `:critical` instances where I believe the fault means that
the object cannot be meaningfully processed.
#### Fault
Unique codes shall be assigned to each fault type, and shall be documented in this section.
It is intended that there should ultimately be a well known site at which the fault codes can be resolved to natural language explanations in as many natural languages as possible of the nature of the particular fault.

View file

@ -8,442 +8,451 @@
001&nbsp;&nbsp;(ns&nbsp;clj-activitypub.core
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
002&nbsp;&nbsp;&nbsp;&nbsp;(:require&nbsp;[clj-activitypub.internal.crypto&nbsp;:as&nbsp;crypto]
002&nbsp;&nbsp;&nbsp;&nbsp;&quot;copied&nbsp;from&nbsp;[Jahfer&#x27;s&nbsp;clj-activitypub&nbsp;library](https:&#x2F;&#x2F;github.com&#x2F;jahfer&#x2F;clj-activitypub).&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
003&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[clj-activitypub.internal.thread-cache&nbsp;:as&nbsp;thread-cache]
003&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;and&nbsp;when&nbsp;Jahfer&nbsp;issues&nbsp;a&nbsp;release&nbsp;of&nbsp;that&nbsp;library,&nbsp;this&nbsp;directory&nbsp;will&nbsp;be&nbsp;deleted&nbsp;and&nbsp;a&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
004&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[clj-activitypub.internal.http-util&nbsp;:as&nbsp;http]
004&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dependency&nbsp;on&nbsp;that&nbsp;library&nbsp;will&nbsp;be&nbsp;added&nbsp;to&nbsp;the&nbsp;project.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
005&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[clj-http.client&nbsp;:as&nbsp;client]
005&nbsp;&nbsp;&nbsp;&nbsp;(:require&nbsp;[clj-activitypub.internal.crypto&nbsp;:as&nbsp;crypto]
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
006&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[clojure.string&nbsp;:as&nbsp;str]))
006&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[clj-activitypub.internal.thread-cache&nbsp;:as&nbsp;thread-cache]
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
007&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[clj-activitypub.internal.http-util&nbsp;:as&nbsp;http]
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
008&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[clj-http.client&nbsp;:as&nbsp;client]
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
009&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[clojure.string&nbsp;:as&nbsp;str]))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
007&nbsp;&nbsp;
010&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
008&nbsp;&nbsp;(defn&nbsp;config
011&nbsp;&nbsp;(defn&nbsp;config
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
009&nbsp;&nbsp;&nbsp;&nbsp;&quot;Creates&nbsp;hash&nbsp;of&nbsp;computed&nbsp;data&nbsp;relevant&nbsp;for&nbsp;most&nbsp;ActivityPub&nbsp;utilities.&quot;
012&nbsp;&nbsp;&nbsp;&nbsp;&quot;Creates&nbsp;hash&nbsp;of&nbsp;computed&nbsp;data&nbsp;relevant&nbsp;for&nbsp;most&nbsp;ActivityPub&nbsp;utilities.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
010&nbsp;&nbsp;&nbsp;&nbsp;[{:keys&nbsp;[domain&nbsp;username&nbsp;username-route&nbsp;public-key&nbsp;private-key]
013&nbsp;&nbsp;&nbsp;&nbsp;[{:keys&nbsp;[domain&nbsp;username&nbsp;username-route&nbsp;public-key&nbsp;private-key]
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
011&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:or&nbsp;{username-route&nbsp;&quot;&#x2F;users&#x2F;&quot;
014&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:or&nbsp;{username-route&nbsp;&quot;&#x2F;users&#x2F;&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
012&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public-key&nbsp;nil
015&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public-key&nbsp;nil
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
013&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private-key&nbsp;nil}}]
016&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private-key&nbsp;nil}}]
</span><br/>
<span class="not-covered" title="0 out of 5 forms covered">
014&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[base-url&nbsp;(str&nbsp;&quot;https:&#x2F;&#x2F;&quot;&nbsp;domain)]
017&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[base-url&nbsp;(str&nbsp;&quot;https:&#x2F;&#x2F;&quot;&nbsp;domain)]
</span><br/>
<span class="not-covered" title="0 out of 8 forms covered">
015&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{:domain&nbsp;domain
018&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{:domain&nbsp;domain
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
016&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:base-url&nbsp;base-url
019&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:base-url&nbsp;base-url
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
017&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:username&nbsp;username
020&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:username&nbsp;username
</span><br/>
<span class="not-covered" title="0 out of 5 forms covered">
018&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:user-id&nbsp;(str&nbsp;base-url&nbsp;username-route&nbsp;username)
021&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:user-id&nbsp;(str&nbsp;base-url&nbsp;username-route&nbsp;username)
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
019&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:public-key&nbsp;public-key
022&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:public-key&nbsp;public-key
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
020&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:private-key&nbsp;(when&nbsp;private-key
023&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:private-key&nbsp;(when&nbsp;private-key
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
021&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(crypto&#x2F;private-key&nbsp;private-key))}))
024&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(crypto&#x2F;private-key&nbsp;private-key))}))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
022&nbsp;&nbsp;
025&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
023&nbsp;&nbsp;(defn&nbsp;parse-account
026&nbsp;&nbsp;(defn&nbsp;parse-account
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
024&nbsp;&nbsp;&nbsp;&nbsp;&quot;Given&nbsp;an&nbsp;ActivityPub&nbsp;handle&nbsp;(e.g.&nbsp;@jahfer@mastodon.social),&nbsp;produces
027&nbsp;&nbsp;&nbsp;&nbsp;&quot;Given&nbsp;an&nbsp;ActivityPub&nbsp;handle&nbsp;(e.g.&nbsp;@jahfer@mastodon.social),&nbsp;produces
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
025&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a&nbsp;map&nbsp;containing&nbsp;{:domain&nbsp;...&nbsp;:username&nbsp;...}.&quot;
028&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a&nbsp;map&nbsp;containing&nbsp;{:domain&nbsp;...&nbsp;:username&nbsp;...}.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
026&nbsp;&nbsp;&nbsp;&nbsp;[handle]
029&nbsp;&nbsp;&nbsp;&nbsp;[handle]
</span><br/>
<span class="covered" title="9 out of 9 forms covered">
027&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[[username&nbsp;domain]&nbsp;(filter&nbsp;#(not&nbsp;(str&#x2F;blank?&nbsp;%))
030&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[[username&nbsp;domain]&nbsp;(filter&nbsp;#(not&nbsp;(str&#x2F;blank?&nbsp;%))
</span><br/>
<span class="covered" title="4 out of 4 forms covered">
028&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(str&#x2F;split&nbsp;handle&nbsp;#&quot;@&quot;))]
031&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(str&#x2F;split&nbsp;handle&nbsp;#&quot;@&quot;))]
</span><br/>
<span class="covered" title="5 out of 5 forms covered">
029&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{:domain&nbsp;domain&nbsp;:username&nbsp;username}))
032&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{:domain&nbsp;domain&nbsp;:username&nbsp;username}))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
030&nbsp;&nbsp;
033&nbsp;&nbsp;
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
031&nbsp;&nbsp;(def&nbsp;^:private&nbsp;user-cache&nbsp;(thread-cache&#x2F;make))
034&nbsp;&nbsp;(def&nbsp;^:private&nbsp;user-cache&nbsp;(thread-cache&#x2F;make))
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
032&nbsp;&nbsp;(defn&nbsp;fetch-user
035&nbsp;&nbsp;(defn&nbsp;fetch-user
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
033&nbsp;&nbsp;&nbsp;&nbsp;&quot;Fetches&nbsp;the&nbsp;customer&nbsp;account&nbsp;details&nbsp;located&nbsp;at&nbsp;user-id&nbsp;from&nbsp;a&nbsp;remote
036&nbsp;&nbsp;&nbsp;&nbsp;&quot;Fetches&nbsp;the&nbsp;customer&nbsp;account&nbsp;details&nbsp;located&nbsp;at&nbsp;user-id&nbsp;from&nbsp;a&nbsp;remote
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
034&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;server.&nbsp;Will&nbsp;return&nbsp;cached&nbsp;results&nbsp;if&nbsp;they&nbsp;exist&nbsp;in&nbsp;memory.&quot;
037&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;server.&nbsp;Will&nbsp;return&nbsp;cached&nbsp;results&nbsp;if&nbsp;they&nbsp;exist&nbsp;in&nbsp;memory.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
035&nbsp;&nbsp;&nbsp;&nbsp;[user-id]
038&nbsp;&nbsp;&nbsp;&nbsp;[user-id]
</span><br/>
<span class="covered" title="5 out of 5 forms covered">
036&nbsp;&nbsp;&nbsp;&nbsp;((:get-v&nbsp;user-cache)
039&nbsp;&nbsp;&nbsp;&nbsp;((:get-v&nbsp;user-cache)
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
037&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user-id
040&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user-id
</span><br/>
<span class="covered" title="2 out of 2 forms covered">
038&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#(:body
041&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#(:body
</span><br/>
<span class="covered" title="11 out of 11 forms covered">
039&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(client&#x2F;get&nbsp;user-id&nbsp;{:as&nbsp;:json-string-keys
042&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(client&#x2F;get&nbsp;user-id&nbsp;{:as&nbsp;:json-string-keys
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
040&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:throw-exceptions&nbsp;false
043&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:throw-exceptions&nbsp;false
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
041&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:ignore-unknown-host?&nbsp;true
044&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:ignore-unknown-host?&nbsp;true
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
042&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:headers&nbsp;{&quot;Accept&quot;&nbsp;&quot;application&#x2F;activity+json&quot;}}))))
045&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:headers&nbsp;{&quot;Accept&quot;&nbsp;&quot;application&#x2F;activity+json&quot;}}))))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
043&nbsp;&nbsp;
046&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
044&nbsp;&nbsp;(defn&nbsp;actor
047&nbsp;&nbsp;(defn&nbsp;actor
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
045&nbsp;&nbsp;&nbsp;&nbsp;&quot;Accepts&nbsp;a&nbsp;config,&nbsp;and&nbsp;returns&nbsp;a&nbsp;map&nbsp;in&nbsp;the&nbsp;form&nbsp;expected&nbsp;by&nbsp;the&nbsp;ActivityPub
048&nbsp;&nbsp;&nbsp;&nbsp;&quot;Accepts&nbsp;a&nbsp;config,&nbsp;and&nbsp;returns&nbsp;a&nbsp;map&nbsp;in&nbsp;the&nbsp;form&nbsp;expected&nbsp;by&nbsp;the&nbsp;ActivityPub
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
046&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spec.&nbsp;See&nbsp;https:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;activitypub&#x2F;#actor-objects&nbsp;for&nbsp;reference.&quot;
049&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spec.&nbsp;See&nbsp;https:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;activitypub&#x2F;#actor-objects&nbsp;for&nbsp;reference.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
047&nbsp;&nbsp;&nbsp;&nbsp;[{:keys&nbsp;[user-id&nbsp;username&nbsp;public-key]}]
050&nbsp;&nbsp;&nbsp;&nbsp;[{:keys&nbsp;[user-id&nbsp;username&nbsp;public-key]}]
</span><br/>
<span class="not-covered" title="0 out of 12 forms covered">
048&nbsp;&nbsp;&nbsp;&nbsp;{&quot;@context&quot;&nbsp;[&quot;https:&#x2F;&#x2F;www.w3.org&#x2F;ns&#x2F;activitystreams&quot;
051&nbsp;&nbsp;&nbsp;&nbsp;{&quot;@context&quot;&nbsp;[&quot;https:&#x2F;&#x2F;www.w3.org&#x2F;ns&#x2F;activitystreams&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
049&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;https:&#x2F;&#x2F;w3id.org&#x2F;security&#x2F;v1&quot;]
052&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;https:&#x2F;&#x2F;w3id.org&#x2F;security&#x2F;v1&quot;]
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
050&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:id&nbsp;user-id
053&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:id&nbsp;user-id
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
051&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:type&nbsp;&quot;Person&quot;
054&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:type&nbsp;&quot;Person&quot;
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
052&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:preferredUsername&nbsp;username
055&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:preferredUsername&nbsp;username
</span><br/>
<span class="not-covered" title="0 out of 4 forms covered">
053&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:inbox&nbsp;(str&nbsp;user-id&nbsp;&quot;&#x2F;inbox&quot;)
056&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:inbox&nbsp;(str&nbsp;user-id&nbsp;&quot;&#x2F;inbox&quot;)
</span><br/>
<span class="not-covered" title="0 out of 4 forms covered">
054&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:outbox&nbsp;(str&nbsp;user-id&nbsp;&quot;&#x2F;outbox&quot;)
057&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:outbox&nbsp;(str&nbsp;user-id&nbsp;&quot;&#x2F;outbox&quot;)
</span><br/>
<span class="not-covered" title="0 out of 8 forms covered">
055&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:publicKey&nbsp;{:id&nbsp;(str&nbsp;user-id&nbsp;&quot;#main-key&quot;)
058&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:publicKey&nbsp;{:id&nbsp;(str&nbsp;user-id&nbsp;&quot;#main-key&quot;)
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
056&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:owner&nbsp;user-id
059&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:owner&nbsp;user-id
</span><br/>
<span class="not-covered" title="0 out of 6 forms covered">
057&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:publicKeyPem&nbsp;(or&nbsp;public-key&nbsp;&quot;&quot;)}})
060&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:publicKeyPem&nbsp;(or&nbsp;public-key&nbsp;&quot;&quot;)}})
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
058&nbsp;&nbsp;
061&nbsp;&nbsp;
</span><br/>
<span class="covered" title="6 out of 6 forms covered">
059&nbsp;&nbsp;(def&nbsp;signature-headers&nbsp;[&quot;(request-target)&quot;&nbsp;&quot;host&quot;&nbsp;&quot;date&quot;&nbsp;&quot;digest&quot;])
062&nbsp;&nbsp;(def&nbsp;signature-headers&nbsp;[&quot;(request-target)&quot;&nbsp;&quot;host&quot;&nbsp;&quot;date&quot;&nbsp;&quot;digest&quot;])
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
060&nbsp;&nbsp;
063&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
061&nbsp;&nbsp;(defn-&nbsp;str-for-signature&nbsp;[headers]
064&nbsp;&nbsp;(defn-&nbsp;str-for-signature&nbsp;[headers]
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
062&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[headers-xf&nbsp;(reduce-kv
065&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[headers-xf&nbsp;(reduce-kv
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
063&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fn&nbsp;[m&nbsp;k&nbsp;v]
066&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fn&nbsp;[m&nbsp;k&nbsp;v]
</span><br/>
<span class="not-covered" title="0 out of 9 forms covered">
064&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(assoc&nbsp;m&nbsp;(str&#x2F;lower-case&nbsp;k)&nbsp;v))&nbsp;{}&nbsp;headers)]
067&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(assoc&nbsp;m&nbsp;(str&#x2F;lower-case&nbsp;k)&nbsp;v))&nbsp;{}&nbsp;headers)]
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
065&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(-&gt;&gt;&nbsp;signature-headers
068&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(-&gt;&gt;&nbsp;signature-headers
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
066&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(select-keys&nbsp;headers-xf)
069&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(select-keys&nbsp;headers-xf)
</span><br/>
<span class="not-covered" title="0 out of 12 forms covered">
067&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(reduce-kv&nbsp;(fn&nbsp;[coll&nbsp;k&nbsp;v]&nbsp;(conj&nbsp;coll&nbsp;(str&nbsp;k&nbsp;&quot;:&nbsp;&quot;&nbsp;v)))&nbsp;[])
070&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(reduce-kv&nbsp;(fn&nbsp;[coll&nbsp;k&nbsp;v]&nbsp;(conj&nbsp;coll&nbsp;(str&nbsp;k&nbsp;&quot;:&nbsp;&quot;&nbsp;v)))&nbsp;[])
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
068&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(interpose&nbsp;&quot;\n&quot;)
071&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(interpose&nbsp;&quot;\n&quot;)
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
069&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(apply&nbsp;str))))
072&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(apply&nbsp;str))))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
070&nbsp;&nbsp;
073&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
071&nbsp;&nbsp;(defn&nbsp;gen-signature-header
074&nbsp;&nbsp;(defn&nbsp;gen-signature-header
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
072&nbsp;&nbsp;&nbsp;&nbsp;&quot;Generates&nbsp;a&nbsp;HTTP&nbsp;Signature&nbsp;string&nbsp;based&nbsp;on&nbsp;the&nbsp;provided&nbsp;map&nbsp;of&nbsp;headers.&quot;
075&nbsp;&nbsp;&nbsp;&nbsp;&quot;Generates&nbsp;a&nbsp;HTTP&nbsp;Signature&nbsp;string&nbsp;based&nbsp;on&nbsp;the&nbsp;provided&nbsp;map&nbsp;of&nbsp;headers.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
073&nbsp;&nbsp;&nbsp;&nbsp;[config&nbsp;headers]
076&nbsp;&nbsp;&nbsp;&nbsp;[config&nbsp;headers]
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
074&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[{:keys&nbsp;[user-id&nbsp;private-key]}&nbsp;config
077&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[{:keys&nbsp;[user-id&nbsp;private-key]}&nbsp;config
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
075&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string-to-sign&nbsp;(str-for-signature&nbsp;headers)
078&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string-to-sign&nbsp;(str-for-signature&nbsp;headers)
</span><br/>
<span class="not-covered" title="0 out of 6 forms covered">
076&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signature&nbsp;(crypto&#x2F;base64-encode&nbsp;(crypto&#x2F;sign&nbsp;string-to-sign&nbsp;private-key))
079&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signature&nbsp;(crypto&#x2F;base64-encode&nbsp;(crypto&#x2F;sign&nbsp;string-to-sign&nbsp;private-key))
</span><br/>
<span class="not-covered" title="0 out of 5 forms covered">
077&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sig-header-keys&nbsp;{&quot;keyId&quot;&nbsp;user-id
080&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sig-header-keys&nbsp;{&quot;keyId&quot;&nbsp;user-id
</span><br/>
<span class="not-covered" title="0 out of 4 forms covered">
078&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;headers&quot;&nbsp;(str&#x2F;join&nbsp;&quot;&nbsp;&quot;&nbsp;signature-headers)
081&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;headers&quot;&nbsp;(str&#x2F;join&nbsp;&quot;&nbsp;&quot;&nbsp;signature-headers)
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
079&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;signature&quot;&nbsp;signature}]
082&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;signature&quot;&nbsp;signature}]
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
080&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(-&gt;&gt;&nbsp;sig-header-keys
083&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(-&gt;&gt;&nbsp;sig-header-keys
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
081&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(reduce-kv&nbsp;(fn&nbsp;[m&nbsp;k&nbsp;v]
084&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(reduce-kv&nbsp;(fn&nbsp;[m&nbsp;k&nbsp;v]
</span><br/>
<span class="not-covered" title="0 out of 11 forms covered">
082&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(conj&nbsp;m&nbsp;(str&nbsp;k&nbsp;&quot;=&quot;&nbsp;&quot;\&quot;&quot;&nbsp;v&nbsp;&quot;\&quot;&quot;)))&nbsp;[])
085&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(conj&nbsp;m&nbsp;(str&nbsp;k&nbsp;&quot;=&quot;&nbsp;&quot;\&quot;&quot;&nbsp;v&nbsp;&quot;\&quot;&quot;)))&nbsp;[])
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
083&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(interpose&nbsp;&quot;,&quot;)
086&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(interpose&nbsp;&quot;,&quot;)
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
084&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(apply&nbsp;str))))
087&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(apply&nbsp;str))))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
085&nbsp;&nbsp;
088&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
086&nbsp;&nbsp;(defn&nbsp;auth-headers
089&nbsp;&nbsp;(defn&nbsp;auth-headers
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
087&nbsp;&nbsp;&nbsp;&nbsp;&quot;Given&nbsp;a&nbsp;config&nbsp;and&nbsp;request&nbsp;map&nbsp;of&nbsp;{:body&nbsp;...&nbsp;:headers&nbsp;...},&nbsp;returns&nbsp;the
090&nbsp;&nbsp;&nbsp;&nbsp;&quot;Given&nbsp;a&nbsp;config&nbsp;and&nbsp;request&nbsp;map&nbsp;of&nbsp;{:body&nbsp;...&nbsp;:headers&nbsp;...},&nbsp;returns&nbsp;the
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
088&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;original&nbsp;set&nbsp;of&nbsp;headers&nbsp;with&nbsp;Signature&nbsp;and&nbsp;Digest&nbsp;attributes&nbsp;appended.&quot;
091&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;original&nbsp;set&nbsp;of&nbsp;headers&nbsp;with&nbsp;Signature&nbsp;and&nbsp;Digest&nbsp;attributes&nbsp;appended.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
089&nbsp;&nbsp;&nbsp;&nbsp;[config&nbsp;{:keys&nbsp;[body&nbsp;headers]}]
092&nbsp;&nbsp;&nbsp;&nbsp;[config&nbsp;{:keys&nbsp;[body&nbsp;headers]}]
</span><br/>
<span class="not-covered" title="0 out of 4 forms covered">
090&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[digest&nbsp;(http&#x2F;digest&nbsp;body)
093&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[digest&nbsp;(http&#x2F;digest&nbsp;body)
</span><br/>
<span class="not-covered" title="0 out of 4 forms covered">
091&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;h&nbsp;(-&gt;&nbsp;headers
094&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;h&nbsp;(-&gt;&nbsp;headers
</span><br/>
<span class="not-covered" title="0 out of 4 forms covered">
092&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(assoc&nbsp;&quot;Digest&quot;&nbsp;digest)
095&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(assoc&nbsp;&quot;Digest&quot;&nbsp;digest)
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
093&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(assoc&nbsp;&quot;(request-target)&quot;&nbsp;&quot;post&nbsp;&#x2F;inbox&quot;))]
096&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(assoc&nbsp;&quot;(request-target)&quot;&nbsp;&quot;post&nbsp;&#x2F;inbox&quot;))]
</span><br/>
<span class="not-covered" title="0 out of 5 forms covered">
094&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(assoc&nbsp;headers
097&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(assoc&nbsp;headers
</span><br/>
<span class="not-covered" title="0 out of 4 forms covered">
095&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Signature&quot;&nbsp;(gen-signature-header&nbsp;config&nbsp;h)
098&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Signature&quot;&nbsp;(gen-signature-header&nbsp;config&nbsp;h)
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
096&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Digest&quot;&nbsp;digest)))
099&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Digest&quot;&nbsp;digest)))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
097&nbsp;&nbsp;
100&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
098&nbsp;&nbsp;(defmulti&nbsp;obj
101&nbsp;&nbsp;(defmulti&nbsp;obj
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
099&nbsp;&nbsp;&nbsp;&nbsp;&quot;Produces&nbsp;a&nbsp;map&nbsp;representing&nbsp;an&nbsp;ActivityPub&nbsp;object&nbsp;which&nbsp;can&nbsp;be&nbsp;serialized
102&nbsp;&nbsp;&nbsp;&nbsp;&quot;Produces&nbsp;a&nbsp;map&nbsp;representing&nbsp;an&nbsp;ActivityPub&nbsp;object&nbsp;which&nbsp;can&nbsp;be&nbsp;serialized
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
100&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;directly&nbsp;to&nbsp;JSON&nbsp;in&nbsp;the&nbsp;form&nbsp;expected&nbsp;by&nbsp;the&nbsp;ActivityStreams&nbsp;2.0&nbsp;spec.
103&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;directly&nbsp;to&nbsp;JSON&nbsp;in&nbsp;the&nbsp;form&nbsp;expected&nbsp;by&nbsp;the&nbsp;ActivityStreams&nbsp;2.0&nbsp;spec.
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;See&nbsp;https:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;activitystreams-vocabulary&#x2F;&nbsp;for&nbsp;reference.&quot;
104&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;See&nbsp;https:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;activitystreams-vocabulary&#x2F;&nbsp;for&nbsp;reference.&quot;
</span><br/>
<span class="partial" title="1 out of 4 forms covered">
102&nbsp;&nbsp;&nbsp;&nbsp;(fn&nbsp;[_config&nbsp;object-data]&nbsp;(:type&nbsp;object-data)))
105&nbsp;&nbsp;&nbsp;&nbsp;(fn&nbsp;[_config&nbsp;object-data]&nbsp;(:type&nbsp;object-data)))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
103&nbsp;&nbsp;
106&nbsp;&nbsp;
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
104&nbsp;&nbsp;(defmethod&nbsp;obj&nbsp;:note
107&nbsp;&nbsp;(defmethod&nbsp;obj&nbsp;:note
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
105&nbsp;&nbsp;&nbsp;&nbsp;[{:keys&nbsp;[user-id]}
108&nbsp;&nbsp;&nbsp;&nbsp;[{:keys&nbsp;[user-id]}
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
106&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{:keys&nbsp;[id&nbsp;published&nbsp;inReplyTo&nbsp;content&nbsp;to]
109&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{:keys&nbsp;[id&nbsp;published&nbsp;inReplyTo&nbsp;content&nbsp;to]
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
107&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:or&nbsp;{published&nbsp;(http&#x2F;date)
110&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:or&nbsp;{published&nbsp;(http&#x2F;date)
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
108&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inReplyTo&nbsp;&quot;&quot;
111&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inReplyTo&nbsp;&quot;&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
109&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;&quot;https:&#x2F;&#x2F;www.w3.org&#x2F;ns&#x2F;activitystreams#Public&quot;}}]
112&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;&quot;https:&#x2F;&#x2F;www.w3.org&#x2F;ns&#x2F;activitystreams#Public&quot;}}]
</span><br/>
<span class="not-covered" title="0 out of 14 forms covered">
110&nbsp;&nbsp;&nbsp;&nbsp;{&quot;id&quot;&nbsp;(str&nbsp;user-id&nbsp;&quot;&#x2F;notes&#x2F;&quot;&nbsp;id)
113&nbsp;&nbsp;&nbsp;&nbsp;{&quot;id&quot;&nbsp;(str&nbsp;user-id&nbsp;&quot;&#x2F;notes&#x2F;&quot;&nbsp;id)
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
111&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;type&quot;&nbsp;&quot;Note&quot;
114&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;type&quot;&nbsp;&quot;Note&quot;
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
112&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;published&quot;&nbsp;published
115&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;published&quot;&nbsp;published
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
113&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;attributedTo&quot;&nbsp;user-id
116&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;attributedTo&quot;&nbsp;user-id
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
114&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;inReplyTo&quot;&nbsp;inReplyTo
117&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;inReplyTo&quot;&nbsp;inReplyTo
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
115&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;content&quot;&nbsp;content
118&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;content&quot;&nbsp;content
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
116&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;to&quot;&nbsp;to})
119&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;to&quot;&nbsp;to})
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
117&nbsp;&nbsp;
120&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
118&nbsp;&nbsp;(defmulti&nbsp;activity
121&nbsp;&nbsp;(defmulti&nbsp;activity
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
119&nbsp;&nbsp;&nbsp;&nbsp;&quot;Produces&nbsp;a&nbsp;map&nbsp;representing&nbsp;an&nbsp;ActivityPub&nbsp;activity&nbsp;which&nbsp;can&nbsp;be&nbsp;serialized
122&nbsp;&nbsp;&nbsp;&nbsp;&quot;Produces&nbsp;a&nbsp;map&nbsp;representing&nbsp;an&nbsp;ActivityPub&nbsp;activity&nbsp;which&nbsp;can&nbsp;be&nbsp;serialized
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
120&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;directly&nbsp;to&nbsp;JSON&nbsp;in&nbsp;the&nbsp;form&nbsp;expected&nbsp;by&nbsp;the&nbsp;ActivityStreams&nbsp;2.0&nbsp;spec.
123&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;directly&nbsp;to&nbsp;JSON&nbsp;in&nbsp;the&nbsp;form&nbsp;expected&nbsp;by&nbsp;the&nbsp;ActivityStreams&nbsp;2.0&nbsp;spec.
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
121&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;See&nbsp;https:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;activitystreams-vocabulary&#x2F;&nbsp;for&nbsp;reference.&quot;
124&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;See&nbsp;https:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;activitystreams-vocabulary&#x2F;&nbsp;for&nbsp;reference.&quot;
</span><br/>
<span class="partial" title="1 out of 2 forms covered">
122&nbsp;&nbsp;&nbsp;&nbsp;(fn&nbsp;[_config&nbsp;activity-type&nbsp;_data]&nbsp;activity-type))
125&nbsp;&nbsp;&nbsp;&nbsp;(fn&nbsp;[_config&nbsp;activity-type&nbsp;_data]&nbsp;activity-type))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
123&nbsp;&nbsp;
126&nbsp;&nbsp;
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
124&nbsp;&nbsp;(defmethod&nbsp;activity&nbsp;:create&nbsp;[{:keys&nbsp;[user-id]}&nbsp;_&nbsp;data]
127&nbsp;&nbsp;(defmethod&nbsp;activity&nbsp;:create&nbsp;[{:keys&nbsp;[user-id]}&nbsp;_&nbsp;data]
</span><br/>
<span class="not-covered" title="0 out of 9 forms covered">
125&nbsp;&nbsp;&nbsp;&nbsp;{&quot;@context&quot;&nbsp;[&quot;https:&#x2F;&#x2F;www.w3.org&#x2F;ns&#x2F;activitystreams&quot;
128&nbsp;&nbsp;&nbsp;&nbsp;{&quot;@context&quot;&nbsp;[&quot;https:&#x2F;&#x2F;www.w3.org&#x2F;ns&#x2F;activitystreams&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
126&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;https:&#x2F;&#x2F;w3id.org&#x2F;security&#x2F;v1&quot;]
129&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;https:&#x2F;&#x2F;w3id.org&#x2F;security&#x2F;v1&quot;]
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
127&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;type&quot;&nbsp;&quot;Create&quot;
130&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;type&quot;&nbsp;&quot;Create&quot;
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
128&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;actor&quot;&nbsp;user-id
131&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;actor&quot;&nbsp;user-id
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
129&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;object&quot;&nbsp;data})
132&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;object&quot;&nbsp;data})
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
130&nbsp;&nbsp;
133&nbsp;&nbsp;
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
131&nbsp;&nbsp;(defmethod&nbsp;activity&nbsp;:delete&nbsp;[{:keys&nbsp;[user-id]}&nbsp;_&nbsp;data]
134&nbsp;&nbsp;(defmethod&nbsp;activity&nbsp;:delete&nbsp;[{:keys&nbsp;[user-id]}&nbsp;_&nbsp;data]
</span><br/>
<span class="not-covered" title="0 out of 9 forms covered">
132&nbsp;&nbsp;&nbsp;&nbsp;{&quot;@context&quot;&nbsp;[&quot;https:&#x2F;&#x2F;www.w3.org&#x2F;ns&#x2F;activitystreams&quot;
135&nbsp;&nbsp;&nbsp;&nbsp;{&quot;@context&quot;&nbsp;[&quot;https:&#x2F;&#x2F;www.w3.org&#x2F;ns&#x2F;activitystreams&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
133&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;https:&#x2F;&#x2F;w3id.org&#x2F;security&#x2F;v1&quot;]
136&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;https:&#x2F;&#x2F;w3id.org&#x2F;security&#x2F;v1&quot;]
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
134&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;type&quot;&nbsp;&quot;Delete&quot;
137&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;type&quot;&nbsp;&quot;Delete&quot;
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
135&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;actor&quot;&nbsp;user-id
138&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;actor&quot;&nbsp;user-id
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
136&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;object&quot;&nbsp;data})
139&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;object&quot;&nbsp;data})
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
137&nbsp;&nbsp;
140&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
138&nbsp;&nbsp;(defn&nbsp;with-config
141&nbsp;&nbsp;(defn&nbsp;with-config
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
139&nbsp;&nbsp;&nbsp;&nbsp;&quot;Returns&nbsp;curried&nbsp;forms&nbsp;of&nbsp;the&nbsp;#activity&nbsp;and&nbsp;#obj&nbsp;multimethods&nbsp;in&nbsp;the&nbsp;form
142&nbsp;&nbsp;&nbsp;&nbsp;&quot;Returns&nbsp;curried&nbsp;forms&nbsp;of&nbsp;the&nbsp;#activity&nbsp;and&nbsp;#obj&nbsp;multimethods&nbsp;in&nbsp;the&nbsp;form
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
140&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{:activity&nbsp;...&nbsp;:obj&nbsp;...},&nbsp;with&nbsp;the&nbsp;initial&nbsp;parameter&nbsp;set&nbsp;to&nbsp;config.&quot;
143&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{:activity&nbsp;...&nbsp;:obj&nbsp;...},&nbsp;with&nbsp;the&nbsp;initial&nbsp;parameter&nbsp;set&nbsp;to&nbsp;config.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
141&nbsp;&nbsp;&nbsp;&nbsp;[config]
144&nbsp;&nbsp;&nbsp;&nbsp;[config]
</span><br/>
<span class="not-covered" title="0 out of 5 forms covered">
142&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[f&nbsp;(juxt
145&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[f&nbsp;(juxt
</span><br/>
<span class="not-covered" title="0 out of 4 forms covered">
143&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#(partial&nbsp;activity&nbsp;%)
146&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#(partial&nbsp;activity&nbsp;%)
</span><br/>
<span class="not-covered" title="0 out of 4 forms covered">
144&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#(partial&nbsp;obj&nbsp;%))
147&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#(partial&nbsp;obj&nbsp;%))
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
145&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[activity-fn&nbsp;obj-fn]&nbsp;(f&nbsp;config)]
148&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[activity-fn&nbsp;obj-fn]&nbsp;(f&nbsp;config)]
</span><br/>
<span class="not-covered" title="0 out of 4 forms covered">
146&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{:activity&nbsp;activity-fn
149&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{:activity&nbsp;activity-fn
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
147&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:obj&nbsp;obj-fn}))
150&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:obj&nbsp;obj-fn}))
</span><br/>
</body>
</html>

View file

@ -8,109 +8,118 @@
001&nbsp;&nbsp;(ns&nbsp;clj-activitypub.internal.crypto
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
002&nbsp;&nbsp;&nbsp;&nbsp;(:require&nbsp;[clojure.java.io&nbsp;:as&nbsp;io])
002&nbsp;&nbsp;&nbsp;&nbsp;&quot;copied&nbsp;from&nbsp;[Jahfer&#x27;s&nbsp;clj-activitypub&nbsp;library](https:&#x2F;&#x2F;github.com&#x2F;jahfer&#x2F;clj-activitypub).&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
003&nbsp;&nbsp;&nbsp;&nbsp;(:import&nbsp;(java.util&nbsp;Base64)
003&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;and&nbsp;when&nbsp;Jahfer&nbsp;issues&nbsp;a&nbsp;release&nbsp;of&nbsp;that&nbsp;library,&nbsp;this&nbsp;directory&nbsp;will&nbsp;be&nbsp;deleted&nbsp;and&nbsp;a&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
004&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(java.security&nbsp;MessageDigest&nbsp;SecureRandom&nbsp;Signature)))
004&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dependency&nbsp;on&nbsp;that&nbsp;library&nbsp;will&nbsp;be&nbsp;added&nbsp;to&nbsp;the&nbsp;project.&quot;
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
005&nbsp;&nbsp;
<span class="not-tracked" title="0 out of 0 forms covered">
005&nbsp;&nbsp;&nbsp;&nbsp;(:require&nbsp;[clojure.java.io&nbsp;:as&nbsp;io])
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
006&nbsp;&nbsp;(java.security.Security&#x2F;addProvider
<span class="not-tracked" title="0 out of 0 forms covered">
006&nbsp;&nbsp;&nbsp;&nbsp;(:import&nbsp;(java.util&nbsp;Base64)
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
007&nbsp;&nbsp;&nbsp;(org.bouncycastle.jce.provider.BouncyCastleProvider.))
<span class="not-tracked" title="0 out of 0 forms covered">
007&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(java.security&nbsp;MessageDigest&nbsp;SecureRandom&nbsp;Signature)))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
008&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
009&nbsp;&nbsp;(defn-&nbsp;keydata&nbsp;[reader]
009&nbsp;&nbsp;(java.security.Security&#x2F;addProvider
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
010&nbsp;&nbsp;&nbsp;(org.bouncycastle.jce.provider.BouncyCastleProvider.))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
011&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
012&nbsp;&nbsp;(defn-&nbsp;keydata&nbsp;[reader]
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
010&nbsp;&nbsp;&nbsp;&nbsp;(-&gt;&gt;&nbsp;reader
013&nbsp;&nbsp;&nbsp;&nbsp;(-&gt;&gt;&nbsp;reader
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
011&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(org.bouncycastle.openssl.PEMParser.)
014&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(org.bouncycastle.openssl.PEMParser.)
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
012&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.readObject)))
015&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.readObject)))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
013&nbsp;&nbsp;
016&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
014&nbsp;&nbsp;(defn-&nbsp;pem-string-&gt;key-pair&nbsp;[string]
017&nbsp;&nbsp;(defn-&nbsp;pem-string-&gt;key-pair&nbsp;[string]
</span><br/>
<span class="not-covered" title="0 out of 6 forms covered">
015&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[kd&nbsp;(keydata&nbsp;(io&#x2F;reader&nbsp;(.getBytes&nbsp;string)))]
018&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[kd&nbsp;(keydata&nbsp;(io&#x2F;reader&nbsp;(.getBytes&nbsp;string)))]
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
016&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.getKeyPair&nbsp;(org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter.)&nbsp;kd)))
019&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.getKeyPair&nbsp;(org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter.)&nbsp;kd)))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
017&nbsp;&nbsp;
020&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
018&nbsp;&nbsp;(defn&nbsp;private-key&nbsp;[private-pem-str]
021&nbsp;&nbsp;(defn&nbsp;private-key&nbsp;[private-pem-str]
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
019&nbsp;&nbsp;&nbsp;&nbsp;(-&gt;&nbsp;private-pem-str
022&nbsp;&nbsp;&nbsp;&nbsp;(-&gt;&nbsp;private-pem-str
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
020&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(pem-string-&gt;key-pair)
023&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(pem-string-&gt;key-pair)
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
021&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.getPrivate)))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
022&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
023&nbsp;&nbsp;(defn&nbsp;base64-encode&nbsp;[bytes]
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
024&nbsp;&nbsp;&nbsp;&nbsp;(.encodeToString&nbsp;(Base64&#x2F;getEncoder)&nbsp;bytes))
024&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.getPrivate)))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
025&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
026&nbsp;&nbsp;(defn&nbsp;sha256-base64&nbsp;[data]
</span><br/>
<span class="not-covered" title="0 out of 5 forms covered">
027&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[digest&nbsp;(.digest&nbsp;(MessageDigest&#x2F;getInstance&nbsp;&quot;SHA-256&quot;)&nbsp;(.getBytes&nbsp;data))]
026&nbsp;&nbsp;(defn&nbsp;base64-encode&nbsp;[bytes]
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
028&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(base64-encode&nbsp;digest)))
027&nbsp;&nbsp;&nbsp;&nbsp;(.encodeToString&nbsp;(Base64&#x2F;getEncoder)&nbsp;bytes))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
029&nbsp;&nbsp;
028&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
030&nbsp;&nbsp;(defn&nbsp;sign&nbsp;[data&nbsp;private-key]&nbsp;
029&nbsp;&nbsp;(defn&nbsp;sha256-base64&nbsp;[data]
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
031&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[bytes&nbsp;(.getBytes&nbsp;data)
</span><br/>
<span class="not-covered" title="0 out of 4 forms covered">
032&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signer&nbsp;(doto&nbsp;(Signature&#x2F;getInstance&nbsp;&quot;SHA256withRSA&quot;)
<span class="not-covered" title="0 out of 5 forms covered">
030&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[digest&nbsp;(.digest&nbsp;(MessageDigest&#x2F;getInstance&nbsp;&quot;SHA-256&quot;)&nbsp;(.getBytes&nbsp;data))]
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
033&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.initSign&nbsp;private-key&nbsp;(SecureRandom.))
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
034&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.update&nbsp;bytes))]
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
035&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.sign&nbsp;signer)))
031&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(base64-encode&nbsp;digest)))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
036&nbsp;&nbsp;
032&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
033&nbsp;&nbsp;(defn&nbsp;sign&nbsp;[data&nbsp;private-key]
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
034&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[bytes&nbsp;(.getBytes&nbsp;data)
</span><br/>
<span class="not-covered" title="0 out of 4 forms covered">
035&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signer&nbsp;(doto&nbsp;(Signature&#x2F;getInstance&nbsp;&quot;SHA256withRSA&quot;)
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
036&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.initSign&nbsp;private-key&nbsp;(SecureRandom.))
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
037&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.update&nbsp;bytes))]
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
038&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.sign&nbsp;signer)))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
039&nbsp;&nbsp;
</span><br/>
</body>
</html>

View file

@ -8,76 +8,85 @@
001&nbsp;&nbsp;(ns&nbsp;clj-activitypub.internal.http-util
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
002&nbsp;&nbsp;&nbsp;&nbsp;(:require&nbsp;[clj-activitypub.internal.crypto&nbsp;:as&nbsp;crypto])
002&nbsp;&nbsp;&nbsp;&nbsp;&quot;copied&nbsp;from&nbsp;[Jahfer&#x27;s&nbsp;clj-activitypub&nbsp;library](https:&#x2F;&#x2F;github.com&#x2F;jahfer&#x2F;clj-activitypub).&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
003&nbsp;&nbsp;&nbsp;&nbsp;(:import&nbsp;(java.net&nbsp;URLEncoder)
003&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;and&nbsp;when&nbsp;Jahfer&nbsp;issues&nbsp;a&nbsp;release&nbsp;of&nbsp;that&nbsp;library,&nbsp;this&nbsp;directory&nbsp;will&nbsp;be&nbsp;deleted&nbsp;and&nbsp;a&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
004&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(java.time&nbsp;OffsetDateTime&nbsp;ZoneOffset)
004&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dependency&nbsp;on&nbsp;that&nbsp;library&nbsp;will&nbsp;be&nbsp;added&nbsp;to&nbsp;the&nbsp;project.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
005&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(java.time.format&nbsp;DateTimeFormatter)))
005&nbsp;&nbsp;&nbsp;&nbsp;(:require&nbsp;[clj-activitypub.internal.crypto&nbsp;:as&nbsp;crypto])
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
006&nbsp;&nbsp;&nbsp;&nbsp;(:import&nbsp;(java.net&nbsp;URLEncoder)
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
007&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(java.time&nbsp;OffsetDateTime&nbsp;ZoneOffset)
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
008&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(java.time.format&nbsp;DateTimeFormatter)))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
006&nbsp;&nbsp;
009&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
007&nbsp;&nbsp;(defn&nbsp;encode-url-params&nbsp;[params]
010&nbsp;&nbsp;(defn&nbsp;encode-url-params&nbsp;[params]
</span><br/>
<span class="covered" title="2 out of 2 forms covered">
008&nbsp;&nbsp;&nbsp;&nbsp;(-&gt;&gt;&nbsp;params
011&nbsp;&nbsp;&nbsp;&nbsp;(-&gt;&gt;&nbsp;params
</span><br/>
<span class="covered" title="2 out of 2 forms covered">
009&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(reduce-kv
012&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(reduce-kv
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
010&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fn&nbsp;[coll&nbsp;k&nbsp;v]
013&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fn&nbsp;[coll&nbsp;k&nbsp;v]
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
011&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(conj&nbsp;coll
014&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(conj&nbsp;coll
</span><br/>
<span class="covered" title="11 out of 11 forms covered">
012&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(str&nbsp;(URLEncoder&#x2F;encode&nbsp;(name&nbsp;k))&nbsp;&quot;=&quot;&nbsp;(URLEncoder&#x2F;encode&nbsp;(str&nbsp;v)))))
015&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(str&nbsp;(URLEncoder&#x2F;encode&nbsp;(name&nbsp;k))&nbsp;&quot;=&quot;&nbsp;(URLEncoder&#x2F;encode&nbsp;(str&nbsp;v)))))
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
013&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[])
016&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[])
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
014&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(interpose&nbsp;&quot;&amp;&quot;)
017&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(interpose&nbsp;&quot;&amp;&quot;)
</span><br/>
<span class="covered" title="2 out of 2 forms covered">
015&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(apply&nbsp;str)))
018&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(apply&nbsp;str)))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
016&nbsp;&nbsp;
019&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
017&nbsp;&nbsp;(defn&nbsp;date&nbsp;[]
020&nbsp;&nbsp;(defn&nbsp;date&nbsp;[]
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
018&nbsp;&nbsp;&nbsp;&nbsp;(-&gt;&nbsp;(OffsetDateTime&#x2F;now&nbsp;(ZoneOffset&#x2F;UTC))
021&nbsp;&nbsp;&nbsp;&nbsp;(-&gt;&nbsp;(OffsetDateTime&#x2F;now&nbsp;(ZoneOffset&#x2F;UTC))
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
019&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.format&nbsp;DateTimeFormatter&#x2F;RFC_1123_DATE_TIME)))
022&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.format&nbsp;DateTimeFormatter&#x2F;RFC_1123_DATE_TIME)))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
020&nbsp;&nbsp;
023&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
021&nbsp;&nbsp;(defn&nbsp;digest
024&nbsp;&nbsp;(defn&nbsp;digest
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
022&nbsp;&nbsp;&nbsp;&nbsp;&quot;Accepts&nbsp;body&nbsp;from&nbsp;HTTP&nbsp;request&nbsp;and&nbsp;generates&nbsp;string
025&nbsp;&nbsp;&nbsp;&nbsp;&quot;Accepts&nbsp;body&nbsp;from&nbsp;HTTP&nbsp;request&nbsp;and&nbsp;generates&nbsp;string
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
023&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;use&nbsp;in&nbsp;HTTP&nbsp;`Digest`&nbsp;request&nbsp;header.&quot;
026&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;use&nbsp;in&nbsp;HTTP&nbsp;`Digest`&nbsp;request&nbsp;header.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
024&nbsp;&nbsp;&nbsp;&nbsp;[body]
027&nbsp;&nbsp;&nbsp;&nbsp;[body]
</span><br/>
<span class="not-covered" title="0 out of 6 forms covered">
025&nbsp;&nbsp;&nbsp;&nbsp;(str&nbsp;&quot;sha-256=&quot;&nbsp;(crypto&#x2F;sha256-base64&nbsp;body)))
028&nbsp;&nbsp;&nbsp;&nbsp;(str&nbsp;&quot;sha-256=&quot;&nbsp;(crypto&#x2F;sha256-base64&nbsp;body)))
</span><br/>
</body>
</html>

View file

@ -5,136 +5,145 @@
</head>
<body>
<span class="covered" title="1 out of 1 forms covered">
001&nbsp;&nbsp;(ns&nbsp;clj-activitypub.internal.thread-cache)
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
002&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
003&nbsp;&nbsp;(defn-&nbsp;current-time&nbsp;
001&nbsp;&nbsp;(ns&nbsp;clj-activitypub.internal.thread-cache
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
004&nbsp;&nbsp;&nbsp;&nbsp;&quot;Returns&nbsp;current&nbsp;time&nbsp;using&nbsp;UNIX&nbsp;epoch.&quot;
002&nbsp;&nbsp;&nbsp;&nbsp;&quot;copied&nbsp;from&nbsp;[Jahfer&#x27;s&nbsp;clj-activitypub&nbsp;library](https:&#x2F;&#x2F;github.com&#x2F;jahfer&#x2F;clj-activitypub).&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
005&nbsp;&nbsp;&nbsp;&nbsp;[]
003&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;and&nbsp;when&nbsp;Jahfer&nbsp;issues&nbsp;a&nbsp;release&nbsp;of&nbsp;that&nbsp;library,&nbsp;this&nbsp;directory&nbsp;will&nbsp;be&nbsp;deleted&nbsp;and&nbsp;a&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
006&nbsp;&nbsp;&nbsp;&nbsp;(System&#x2F;currentTimeMillis))
<span class="not-tracked" title="0 out of 0 forms covered">
004&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dependency&nbsp;on&nbsp;that&nbsp;library&nbsp;will&nbsp;be&nbsp;added&nbsp;to&nbsp;the&nbsp;project.&quot;)
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
007&nbsp;&nbsp;
005&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
008&nbsp;&nbsp;(defn-&nbsp;update-read-at&nbsp;[store&nbsp;k&nbsp;v]
006&nbsp;&nbsp;(defn-&nbsp;current-time
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
007&nbsp;&nbsp;&nbsp;&nbsp;&quot;Returns&nbsp;current&nbsp;time&nbsp;using&nbsp;UNIX&nbsp;epoch.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
008&nbsp;&nbsp;&nbsp;&nbsp;[]
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
009&nbsp;&nbsp;&nbsp;&nbsp;(System&#x2F;currentTimeMillis))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
010&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
011&nbsp;&nbsp;(defn-&nbsp;update-read-at&nbsp;[store&nbsp;k&nbsp;v]
</span><br/>
<span class="covered" title="2 out of 2 forms covered">
009&nbsp;&nbsp;&nbsp;&nbsp;(dosync
012&nbsp;&nbsp;&nbsp;&nbsp;(dosync
</span><br/>
<span class="covered" title="5 out of 5 forms covered">
010&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(commute&nbsp;store&nbsp;assoc&nbsp;k
013&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(commute&nbsp;store&nbsp;assoc&nbsp;k
</span><br/>
<span class="covered" title="7 out of 7 forms covered">
011&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(merge&nbsp;v&nbsp;{:read-at&nbsp;(current-time)}))))
014&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(merge&nbsp;v&nbsp;{:read-at&nbsp;(current-time)}))))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
012&nbsp;&nbsp;
015&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
013&nbsp;&nbsp;(defn&nbsp;make&nbsp;
016&nbsp;&nbsp;(defn&nbsp;make
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
014&nbsp;&nbsp;&nbsp;&nbsp;&quot;Creates&nbsp;a&nbsp;thread-local&nbsp;cache.&quot;
017&nbsp;&nbsp;&nbsp;&nbsp;&quot;Creates&nbsp;a&nbsp;thread-local&nbsp;cache.&quot;
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
015&nbsp;&nbsp;&nbsp;&nbsp;([]&nbsp;(make&nbsp;false))
018&nbsp;&nbsp;&nbsp;&nbsp;([]&nbsp;(make&nbsp;false))
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
016&nbsp;&nbsp;&nbsp;&nbsp;([cache-if-nil]
019&nbsp;&nbsp;&nbsp;&nbsp;([cache-if-nil]
</span><br/>
<span class="covered" title="4 out of 4 forms covered">
017&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[store&nbsp;(ref&nbsp;{})]
020&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[store&nbsp;(ref&nbsp;{})]
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
018&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(letfn&nbsp;[(cache-kv&nbsp;([k&nbsp;v]
021&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(letfn&nbsp;[(cache-kv&nbsp;([k&nbsp;v]
</span><br/>
<span class="covered" title="2 out of 2 forms covered">
019&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(dosync
022&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(dosync
</span><br/>
<span class="covered" title="5 out of 5 forms covered">
020&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(commute&nbsp;store&nbsp;assoc&nbsp;k
023&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(commute&nbsp;store&nbsp;assoc&nbsp;k
</span><br/>
<span class="covered" title="6 out of 6 forms covered">
021&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{:write-at&nbsp;(current-time)&nbsp;
024&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{:write-at&nbsp;(current-time)
</span><br/>
<span class="covered" title="2 out of 2 forms covered">
022&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:read-at&nbsp;(current-time)&nbsp;
025&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:read-at&nbsp;(current-time)
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
023&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:value&nbsp;v})
026&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:value&nbsp;v})
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
024&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v)))
027&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v)))
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
025&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(get-v&nbsp;([k]
028&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(get-v&nbsp;([k]
</span><br/>
<span class="covered" title="11 out of 11 forms covered">
026&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(when-let&nbsp;[data&nbsp;(get&nbsp;@store&nbsp;k)]
029&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(when-let&nbsp;[data&nbsp;(get&nbsp;@store&nbsp;k)]
</span><br/>
<span class="covered" title="5 out of 5 forms covered">
027&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(update-read-at&nbsp;store&nbsp;k&nbsp;data)
030&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(update-read-at&nbsp;store&nbsp;k&nbsp;data)
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
028&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(:value&nbsp;data)))
031&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(:value&nbsp;data)))
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
029&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;([k&nbsp;compute-fn]
032&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;([k&nbsp;compute-fn]
</span><br/>
<span class="covered" title="4 out of 4 forms covered">
030&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[storage&nbsp;@store]
033&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[storage&nbsp;@store]
</span><br/>
<span class="covered" title="5 out of 5 forms covered">
031&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if&nbsp;(contains?&nbsp;storage&nbsp;k)
034&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if&nbsp;(contains?&nbsp;storage&nbsp;k)
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
032&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(get-v&nbsp;k)
035&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(get-v&nbsp;k)
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
033&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[v&nbsp;(compute-fn)]
036&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[v&nbsp;(compute-fn)]
</span><br/>
<span class="partial" title="11 out of 12 forms covered">
034&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(when&nbsp;(or&nbsp;(not&nbsp;(nil?&nbsp;v))&nbsp;cache-if-nil)
037&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(when&nbsp;(or&nbsp;(not&nbsp;(nil?&nbsp;v))&nbsp;cache-if-nil)
</span><br/>
<span class="covered" title="4 out of 4 forms covered">
035&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(cache-kv&nbsp;k&nbsp;v)
038&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(cache-kv&nbsp;k&nbsp;v)
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
036&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(get-v&nbsp;k)))))))
039&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(get-v&nbsp;k)))))))
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
037&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(lru&nbsp;([]
040&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(lru&nbsp;([]
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
038&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(mapv
041&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(mapv
</span><br/>
<span class="not-covered" title="0 out of 6 forms covered">
039&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fn&nbsp;[[k&nbsp;v]]&nbsp;[k&nbsp;(:value&nbsp;v)])
042&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fn&nbsp;[[k&nbsp;v]]&nbsp;[k&nbsp;(:value&nbsp;v)])
</span><br/>
<span class="not-covered" title="0 out of 12 forms covered">
040&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(sort-by&nbsp;#(-&gt;&nbsp;%&nbsp;val&nbsp;:read-at)&nbsp;&lt;&nbsp;@store))))]
043&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(sort-by&nbsp;#(-&gt;&nbsp;%&nbsp;val&nbsp;:read-at)&nbsp;&lt;&nbsp;@store))))]
</span><br/>
<span class="covered" title="6 out of 6 forms covered">
041&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{:cache-kv&nbsp;cache-kv&nbsp;
044&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{:cache-kv&nbsp;cache-kv
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
042&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:get-v&nbsp;get-v
045&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:get-v&nbsp;get-v
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
043&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:cache-if-nil&nbsp;cache-if-nil
046&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:cache-if-nil&nbsp;cache-if-nil
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
044&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:lru&nbsp;lru}))))
047&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:lru&nbsp;lru}))))
</span><br/>
</body>
</html>

View file

@ -8,97 +8,106 @@
001&nbsp;&nbsp;(ns&nbsp;clj-activitypub.webfinger
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
002&nbsp;&nbsp;&nbsp;&nbsp;(:require&nbsp;[clj-http.client&nbsp;:as&nbsp;client]
002&nbsp;&nbsp;&nbsp;&nbsp;&quot;copied&nbsp;from&nbsp;[Jahfer&#x27;s&nbsp;clj-activitypub&nbsp;library](https:&#x2F;&#x2F;github.com&#x2F;jahfer&#x2F;clj-activitypub).&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
003&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[clj-activitypub.internal.http-util&nbsp;:as&nbsp;http]
003&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;and&nbsp;when&nbsp;Jahfer&nbsp;issues&nbsp;a&nbsp;release&nbsp;of&nbsp;that&nbsp;library,&nbsp;this&nbsp;directory&nbsp;will&nbsp;be&nbsp;deleted&nbsp;and&nbsp;a&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
004&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[clj-activitypub.internal.thread-cache&nbsp;:as&nbsp;thread-cache]))
004&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dependency&nbsp;on&nbsp;that&nbsp;library&nbsp;will&nbsp;be&nbsp;added&nbsp;to&nbsp;the&nbsp;project.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
005&nbsp;&nbsp;&nbsp;&nbsp;(:require&nbsp;[clj-http.client&nbsp;:as&nbsp;client]
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
006&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[clj-activitypub.internal.http-util&nbsp;:as&nbsp;http]
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
007&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[clj-activitypub.internal.thread-cache&nbsp;:as&nbsp;thread-cache]))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
005&nbsp;&nbsp;
008&nbsp;&nbsp;
</span><br/>
<span class="covered" title="2 out of 2 forms covered">
006&nbsp;&nbsp;(def&nbsp;remote-uri-path&nbsp;&quot;&#x2F;.well-known&#x2F;webfinger&quot;)
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
007&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
008&nbsp;&nbsp;(defn-&nbsp;resource-str&nbsp;[domain&nbsp;username]
</span><br/>
<span class="covered" title="6 out of 6 forms covered">
009&nbsp;&nbsp;&nbsp;&nbsp;(str&nbsp;&quot;acct:&quot;&nbsp;username&nbsp;&quot;@&quot;&nbsp;domain))
009&nbsp;&nbsp;(def&nbsp;remote-uri-path&nbsp;&quot;&#x2F;.well-known&#x2F;webfinger&quot;)
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
010&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
011&nbsp;&nbsp;(defn&nbsp;resource-url
011&nbsp;&nbsp;(defn-&nbsp;resource-str&nbsp;[domain&nbsp;username]
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
012&nbsp;&nbsp;&nbsp;&nbsp;&quot;Builds&nbsp;a&nbsp;URL&nbsp;pointing&nbsp;to&nbsp;the&nbsp;user&#x27;s&nbsp;account&nbsp;on&nbsp;the&nbsp;remote&nbsp;server.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
013&nbsp;&nbsp;&nbsp;&nbsp;[domain&nbsp;username&nbsp;&amp;&nbsp;[params]]
</span><br/>
<span class="covered" title="5 out of 5 forms covered">
014&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[resource&nbsp;(resource-str&nbsp;domain&nbsp;username)
</span><br/>
<span class="covered" title="8 out of 8 forms covered">
015&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query-str&nbsp;(http&#x2F;encode-url-params&nbsp;(merge&nbsp;params&nbsp;{:resource&nbsp;resource}))]
</span><br/>
<span class="covered" title="7 out of 7 forms covered">
016&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(str&nbsp;&quot;https:&#x2F;&#x2F;&quot;&nbsp;domain&nbsp;remote-uri-path&nbsp;&quot;?&quot;&nbsp;query-str)))
<span class="covered" title="6 out of 6 forms covered">
012&nbsp;&nbsp;&nbsp;&nbsp;(str&nbsp;&quot;acct:&quot;&nbsp;username&nbsp;&quot;@&quot;&nbsp;domain))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
017&nbsp;&nbsp;
013&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
018&nbsp;&nbsp;(def&nbsp;^:private&nbsp;user-id-cache
014&nbsp;&nbsp;(defn&nbsp;resource-url
</span><br/>
<span class="covered" title="2 out of 2 forms covered">
019&nbsp;&nbsp;&nbsp;&nbsp;(thread-cache&#x2F;make))
<span class="not-tracked" title="0 out of 0 forms covered">
015&nbsp;&nbsp;&nbsp;&nbsp;&quot;Builds&nbsp;a&nbsp;URL&nbsp;pointing&nbsp;to&nbsp;the&nbsp;user&#x27;s&nbsp;account&nbsp;on&nbsp;the&nbsp;remote&nbsp;server.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
016&nbsp;&nbsp;&nbsp;&nbsp;[domain&nbsp;username&nbsp;&amp;&nbsp;[params]]
</span><br/>
<span class="covered" title="5 out of 5 forms covered">
017&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[resource&nbsp;(resource-str&nbsp;domain&nbsp;username)
</span><br/>
<span class="covered" title="8 out of 8 forms covered">
018&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query-str&nbsp;(http&#x2F;encode-url-params&nbsp;(merge&nbsp;params&nbsp;{:resource&nbsp;resource}))]
</span><br/>
<span class="covered" title="7 out of 7 forms covered">
019&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(str&nbsp;&quot;https:&#x2F;&#x2F;&quot;&nbsp;domain&nbsp;remote-uri-path&nbsp;&quot;?&quot;&nbsp;query-str)))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
020&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
021&nbsp;&nbsp;(defn&nbsp;fetch-user-id
021&nbsp;&nbsp;(def&nbsp;^:private&nbsp;user-id-cache
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
022&nbsp;&nbsp;&nbsp;&nbsp;&quot;Follows&nbsp;the&nbsp;webfinger&nbsp;request&nbsp;to&nbsp;a&nbsp;remote&nbsp;domain,&nbsp;retrieving&nbsp;the&nbsp;ID&nbsp;of&nbsp;the&nbsp;requested
<span class="covered" title="2 out of 2 forms covered">
022&nbsp;&nbsp;&nbsp;&nbsp;(thread-cache&#x2F;make))
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
023&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;account.&nbsp;Typically&nbsp;returns&nbsp;a&nbsp;string&nbsp;in&nbsp;the&nbsp;form&nbsp;of&nbsp;a&nbsp;URL.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
024&nbsp;&nbsp;&nbsp;&nbsp;[domain&nbsp;username]
</span><br/>
<span class="covered" title="4 out of 4 forms covered">
025&nbsp;&nbsp;&nbsp;&nbsp;((:get-v&nbsp;user-id-cache)
</span><br/>
<span class="covered" title="5 out of 5 forms covered">
026&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(str&nbsp;domain&nbsp;&quot;@&quot;&nbsp;username)&nbsp;;;&nbsp;cache&nbsp;key
<span class="blank" title="0 out of 0 forms covered">
023&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
027&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fn&nbsp;[]
</span><br/>
<span class="partial" title="15 out of 16 forms covered">
028&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[response&nbsp;(some-&gt;&nbsp;(resource-url&nbsp;domain&nbsp;username&nbsp;{:rel&nbsp;&quot;self&quot;})
</span><br/>
<span class="covered" title="8 out of 8 forms covered">
029&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(client&#x2F;get&nbsp;{:as&nbsp;:json&nbsp;:throw-exceptions&nbsp;false&nbsp;:ignore-unknown-host?&nbsp;true}))]
</span><br/>
<span class="partial" title="27 out of 31 forms covered">
030&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(some-&gt;&gt;&nbsp;response&nbsp;:body&nbsp;:links
</span><br/>
<span class="covered" title="12 out of 12 forms covered">
031&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(some&nbsp;#(when&nbsp;(=&nbsp;(:type&nbsp;%)&nbsp;&quot;application&#x2F;activity+json&quot;)&nbsp;%))
024&nbsp;&nbsp;(defn&nbsp;fetch-user-id
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
032&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:href)))))
025&nbsp;&nbsp;&nbsp;&nbsp;&quot;Follows&nbsp;the&nbsp;webfinger&nbsp;request&nbsp;to&nbsp;a&nbsp;remote&nbsp;domain,&nbsp;retrieving&nbsp;the&nbsp;ID&nbsp;of&nbsp;the&nbsp;requested
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
026&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;account.&nbsp;Typically&nbsp;returns&nbsp;a&nbsp;string&nbsp;in&nbsp;the&nbsp;form&nbsp;of&nbsp;a&nbsp;URL.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
027&nbsp;&nbsp;&nbsp;&nbsp;[domain&nbsp;username]
</span><br/>
<span class="covered" title="4 out of 4 forms covered">
028&nbsp;&nbsp;&nbsp;&nbsp;((:get-v&nbsp;user-id-cache)
</span><br/>
<span class="covered" title="5 out of 5 forms covered">
029&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(str&nbsp;domain&nbsp;&quot;@&quot;&nbsp;username)&nbsp;;;&nbsp;cache&nbsp;key
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
030&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fn&nbsp;[]
</span><br/>
<span class="partial" title="15 out of 16 forms covered">
031&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[response&nbsp;(some-&gt;&nbsp;(resource-url&nbsp;domain&nbsp;username&nbsp;{:rel&nbsp;&quot;self&quot;})
</span><br/>
<span class="covered" title="8 out of 8 forms covered">
032&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(client&#x2F;get&nbsp;{:as&nbsp;:json&nbsp;:throw-exceptions&nbsp;false&nbsp;:ignore-unknown-host?&nbsp;true}))]
</span><br/>
<span class="partial" title="27 out of 31 forms covered">
033&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(some-&gt;&gt;&nbsp;response&nbsp;:body&nbsp;:links
</span><br/>
<span class="covered" title="12 out of 12 forms covered">
034&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(some&nbsp;#(when&nbsp;(=&nbsp;(:type&nbsp;%)&nbsp;&quot;application&#x2F;activity+json&quot;)&nbsp;%))
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
035&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:href)))))
</span><br/>
</body>
</html>

View file

@ -1,54 +1,73 @@
{"coverage":
{"dog_and_duck/quack/quack.clj":
[null, 1, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, 1, null,
null, null, null, null, null, null, null, null, null, null, null,
17, null, 1, null, null, null, null, null, true, 5, null, null, 1,
null, 1, null, null, null, null, 1, null, null, null, null, null, 1,
null, null, 4, null, 1, null, null, null, null, 1, null, null, null,
null, 1, null, null, 4, null, 1, null, null, null, null, 1, null,
null, null, null, null, null, true, 10, 9, true, 2, null, null,
null, true, 2, null, 1, null, null, true, 2, 2, 0, 0, 0, null, null,
1, null, null, 0, 0, 0, 0, 0, 0, 0, null, null, null, 1, null, null,
0, 0, 0, null, null, 1, null, null, null, null, null, 0, 0, 0, null,
null, 1, null, null, null, null, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
null, null, 0, 0, null, 1, null, null, 0, null, 1, null, null, 0,
null, 1, null, null, 0, null, 1, null, null, 0, null, null],
null, null, null, null, null, null, null, null, null, null, null,
null, null, null, 1, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null,
40, null, 0, null, 1, null, null, null, null, null, true, 4, null,
null, null, null, 1, null, null, null, null, 1, null, null, null,
null, null, true, null, null, 5, null, true, null, 1, null, null,
null, null, 1, null, null, null, null, true, null, null, 5, null,
null, 1, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, true, 2, 2, 0, 0, 0, null, null, 1, null,
null, null, null, null, null, null, 0, 0, 0, null, null, 1, null,
null, 0, 0, 0, 0, 0, 0, 0, null, null, null, 1, null, null, 0, 0, 0,
null, null, 1, null, null, null, null, null, 0, 0, 0, null, null, 1,
null, null, null, null, null, true, true, true, true, 2, 1, null, 1,
1, true, true, 1, null, null, null, null, null, null, null, null, 0,
0, 0, 0, null, null, 1, null, null, 0, null, 1, null, null, 0, null,
1, null, null, 0, null, 1, null, null, 2, null, null],
"dog_and_duck/utils/process.clj":
[null, 1, null, null, 1, null, null, null, null, 1, 1, 1, null, true,
null, null, null, null, null, null, null, null, null, 1],
"clj_activitypub/internal/http_util.clj":
[null, 1, null, null, null, null, null, 1, 1, 1, 1, 2, 2, 1, 1, 1,
null, 1, 0, 0, null, 1, null, null, null, 0],
[null, 1, null, null, null, null, null, null, null, null, 1, 1, 1, 1,
2, 2, 1, 1, 1, null, 1, 0, 0, null, 1, null, null, null, 0],
"clj_activitypub/internal/thread_cache.clj":
[null, 1, null, 1, null, null, 8, null, 1, 4, 4, 4, null, 1, null, 2,
null, 2, 2, 2, 2, 2, 2, 2, 2, null, 4, 4, 4, null, 4, 4, 2, 2, true,
2, 2, null, 0, 0, 0, 2, 2, 2, 2],
[null, 1, null, null, null, null, 1, null, null, 8, null, 1, 4, 4, 4,
null, 1, null, 2, null, 2, 2, 2, 2, 2, 2, 2, 2, null, 4, 4, 4, null,
4, 4, 2, 2, true, 2, 2, null, 0, 0, 0, 2, 2, 2, 2],
"dog_and_duck/scratch/parser.clj":
[null, 1, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null,
null, 1, null, null, null, 7, 7, 7, 7, 7, true, 0, null, 1, null, 1,
0, 0, 0, 0, 0, 0, 1],
null, 1, null, null, null, 10, 10, 10, 10, 10, true, 0, null, 1,
null, 1, 0, 0, 0, 0, 0, 0, 1, null, 1],
"clj_activitypub/core.clj":
[null, 1, null, null, null, null, null, null, 1, null, null, null,
null, null, 0, 0, 0, 0, 0, 0, 0, 0, null, 1, null, null, null, 6, 2,
2, null, 1, 1, null, null, null, 1, 1, 1, 1, null, null, 1, null, 1,
null, null, null, 0, null, 0, null, 0, 0, 0, 0, 0, 0, null, 1, null,
1, 0, 0, 0, 0, 0, 0, 0, 0, null, 1, null, null, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, null, 1, null, null, null, 0, 0, 0, 0, 0, 0, 0, null, 1,
null, null, null, true, null, 1, null, null, null, null, null, 0,
null, 0, 0, 0, 0, 0, null, 1, null, null, null, true, null, 1, 0,
null, null, 0, 0, null, 1, 0, null, null, 0, 0, null, 1, null, null,
null, 0, 0, 0, 0, 0, 0],
[null, 1, null, null, null, null, null, null, null, null, null, 1,
null, null, null, null, null, 0, 0, 0, 0, 0, 0, 0, 0, null, 1, null,
null, null, 6, 2, 2, null, 1, 1, null, null, null, 1, 1, 1, 1, null,
null, 1, null, 1, null, null, null, 0, null, 0, null, 0, 0, 0, 0, 0,
0, null, 1, null, 1, 0, 0, 0, 0, 0, 0, 0, 0, null, 1, null, null, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, null, 1, null, null, null, 0, 0, 0, 0,
0, 0, 0, null, 1, null, null, null, true, null, 1, null, null, null,
null, null, 0, null, 0, 0, 0, 0, 0, null, 1, null, null, null, true,
null, 1, 0, null, null, 0, 0, null, 1, 0, null, null, 0, 0, null, 1,
null, null, null, 0, 0, 0, 0, 0, 0],
"clj_activitypub/internal/crypto.clj":
[null, 1, null, null, null, null, 1, 1, null, 1, 0, 0, null, null, 1,
0, 0, null, 1, 0, 0, null, null, 1, 0, null, 1, 0, 0, null, 1, 0, 0,
0, 0, 0, null],
[null, 1, null, null, null, null, null, null, null, 1, 1, null, 1, 0,
0, null, null, 1, 0, 0, null, 1, 0, 0, null, null, 1, 0, null, 1, 0,
0, null, 1, 0, 0, 0, 0, 0, null],
"dog_and_duck/quack/picky.clj":
[null, 1, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, 1, null, null, null, null,
null, null, null, null, null, null, 1, null, 1, null, 1, 1, 1, 1, 1,
null, 1, null, null, null, 0, 0, 0, 0, 0, 0, 0, 0, null, 1, null,
null, null, null, 1, null, null, null, null, 1, null, null, null,
null, null, null, true, 10, 9, true, 2, null, null, null, true,
null, null, 3, null, null, null, 1, null, null, null, null, null,
null, 0, 0, 0, 0, null, 0, null, 0, null, 0, 0, 0, null, 1, null, 0,
0, 0, 0, 0, 0, null, null, null, null, null, 0, 0, null, null, null,
null, 0, 0, null, null, null, null, null, null, null],
"dog_and_duck/scratch/core.clj":[null, 1, null, 1, null, null, 0],
"clj_activitypub/webfinger.clj":
[null, 1, null, null, null, null, 1, null, 1, 1, null, 1, null, null,
1, 1, 1, null, 1, 1, null, 1, null, null, null, 3, 3, 3, true, 1,
true, 2, null],
[null, 1, null, null, null, null, null, null, null, 1, null, 1, 1,
null, 1, null, null, 1, 1, 1, null, 1, 1, null, 1, null, null, null,
3, 3, 3, true, 1, true, 2, null],
"dog_and_duck/scratch/scratch.clj":
[null, 1, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, 1, null, 1, 1, 1, null, null, null,
null, 1, null, 1, 1, 1, 1, null, null, 1, null, null, 1, 1, null,
null, null, null, 1, 1, 1, 1, 1, 1, null]}}
null, null, null, 1, 1, 1, 1, 1, 1, null, null]}}

View file

@ -1 +1 @@
<?xml version="1.0" encoding="UTF-8"?><report><stats><packages value="9"/><methods value="1223"/><srcfiles value="9"/><srclines value="284"/></stats><data><all name="total"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="52% (631/1223)"/><coverage type="line, %" value="54% (153/284)"/><package name="dog-and-duck.scratch.scratch"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="100% (75/75)"/><coverage type="line, %" value="100% (19/19)"/></package><package name="clj-activitypub.internal.thread-cache"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="83% (105/126)"/><coverage type="line, %" value="88% (30/34)"/></package><package name="clj-activitypub.internal.crypto"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="19% (9/48)"/><coverage type="line, %" value="39% (9/23)"/></package><package name="dog-and-duck.quack.quack"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="44% (199/448)"/><coverage type="line, %" value="46% (31/68)"/></package><package name="clj-activitypub.webfinger"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="96% (107/112)"/><coverage type="line, %" value="89% (16/18)"/></package><package name="clj-activitypub.internal.http-util"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="74% (29/39)"/><coverage type="line, %" value="80% (12/15)"/></package><package name="dog-and-duck.scratch.core"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="33% (2/6)"/><coverage type="line, %" value="67% (2/3)"/></package><package name="dog-and-duck.scratch.parser"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="50% (34/68)"/><coverage type="line, %" value="56% (10/18)"/></package><package name="clj-activitypub.core"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="24% (71/301)"/><coverage type="line, %" value="28% (24/86)"/></package></all></data></report>
<?xml version="1.0" encoding="UTF-8"?><report><stats><packages value="11"/><methods value="1530"/><srcfiles value="11"/><srclines value="340"/></stats><data><all name="total"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="53% (816/1530)"/><coverage type="line, %" value="52% (177/340)"/><package name="dog-and-duck.scratch.scratch"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="100% (75/75)"/><coverage type="line, %" value="100% (19/19)"/></package><package name="clj-activitypub.internal.thread-cache"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="83% (105/126)"/><coverage type="line, %" value="88% (30/34)"/></package><package name="clj-activitypub.internal.crypto"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="19% (9/48)"/><coverage type="line, %" value="39% (9/23)"/></package><package name="dog-and-duck.quack.quack"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="48% (237/490)"/><coverage type="line, %" value="43% (29/67)"/></package><package name="clj-activitypub.webfinger"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="96% (107/112)"/><coverage type="line, %" value="89% (16/18)"/></package><package name="dog-and-duck.quack.picky"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="50% (113/227)"/><coverage type="line, %" value="39% (19/49)"/></package><package name="clj-activitypub.internal.http-util"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="74% (29/39)"/><coverage type="line, %" value="80% (12/15)"/></package><package name="dog-and-duck.scratch.core"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="33% (2/6)"/><coverage type="line, %" value="67% (2/3)"/></package><package name="dog-and-duck.utils.process"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="86% (25/29)"/><coverage type="line, %" value="86% (6/7)"/></package><package name="dog-and-duck.scratch.parser"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="56% (43/77)"/><coverage type="line, %" value="58% (11/19)"/></package><package name="clj-activitypub.core"><coverage type="class, %" value="0% (0/1)"/><coverage type="method, %" value="0% (0/1)"/><coverage type="block, %" value="24% (71/301)"/><coverage type="line, %" value="28% (24/86)"/></package></all></data></report>

View file

@ -0,0 +1,437 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" href="../../coverage.css"/> <title> dog_and_duck/quack/picky.clj </title>
</head>
<body>
<span class="covered" title="1 out of 1 forms covered">
001&nbsp;&nbsp;(ns&nbsp;dog-and-duck.quack.picky&nbsp;&quot;Fault-finder&nbsp;for&nbsp;ActivityPub&nbsp;documents.&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
002&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
003&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Generally,&nbsp;each&nbsp;`-faults`&nbsp;function&nbsp;will&nbsp;return:
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
004&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.&nbsp;`nil`&nbsp;if&nbsp;no&nbsp;faults&nbsp;were&nbsp;found;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
005&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.&nbsp;a&nbsp;sequence&nbsp;of&nbsp;fault&nbsp;objects&nbsp;if&nbsp;faults&nbsp;were&nbsp;found.
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
006&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
007&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Each&nbsp;fault&nbsp;object&nbsp;shall&nbsp;have&nbsp;the&nbsp;properties:
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
008&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.&nbsp;`:@context`&nbsp;whose&nbsp;value&nbsp;shall&nbsp;be&nbsp;the&nbsp;URL&nbsp;of&nbsp;a&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
009&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;document&nbsp;specifying&nbsp;this&nbsp;vocabulary;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
010&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.&nbsp;`:type`&nbsp;whose&nbsp;value&nbsp;shall&nbsp;be&nbsp;`Fault`;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
011&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.&nbsp;`:severity`&nbsp;whose&nbsp;value&nbsp;shall&nbsp;be&nbsp;one&nbsp;of&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
012&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`minor`,&nbsp;`should`,&nbsp;`must`&nbsp;or&nbsp;`critical`;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
013&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4.&nbsp;`:fault`&nbsp;whose&nbsp;value&nbsp;shall&nbsp;be&nbsp;a&nbsp;unique&nbsp;token
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
014&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;representing&nbsp;the&nbsp;particular&nbsp;fault&nbsp;type;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
015&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5.&nbsp;`:narrative`&nbsp;whose&nbsp;value&nbsp;shall&nbsp;be&nbsp;a&nbsp;natural
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
016&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;language&nbsp;description&nbsp;of&nbsp;the&nbsp;fault&nbsp;type.
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
017&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
018&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Note&nbsp;that&nbsp;the&nbsp;reason&nbsp;for&nbsp;the&nbsp;`:fault`&nbsp;property&nbsp;is
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
019&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;be&nbsp;able&nbsp;to&nbsp;have&nbsp;a&nbsp;well&nbsp;known&nbsp;place,&nbsp;linked&nbsp;to
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
020&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from&nbsp;the&nbsp;@context&nbsp;URL,&nbsp;which&nbsp;allows&nbsp;narratives&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
021&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;each&nbsp;fault&nbsp;type&nbsp;to&nbsp;be&nbsp;served&nbsp;in&nbsp;as&nbsp;many
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
022&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;natural&nbsp;languages&nbsp;as&nbsp;possible.
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
023&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
024&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The&nbsp;idea&nbsp;further&nbsp;is&nbsp;that&nbsp;it&nbsp;should&nbsp;ultimately&nbsp;be
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
025&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;possible&nbsp;to&nbsp;serialise&nbsp;a&nbsp;fault&nbsp;report&nbsp;as&nbsp;a&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
026&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;document&nbsp;which&nbsp;in&nbsp;its&nbsp;own&nbsp;right&nbsp;conforms&nbsp;to&nbsp;the
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
027&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ActivityStreams&nbsp;spec.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
028&nbsp;&nbsp;&nbsp;(:require&nbsp;[dog-and-duck.utils.process&nbsp;:refer&nbsp;[pid]]))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
029&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
030&nbsp;&nbsp;(def&nbsp;^:const&nbsp;severity
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
031&nbsp;&nbsp;&nbsp;&nbsp;&quot;Severity&nbsp;of&nbsp;faults&nbsp;found,&nbsp;as&nbsp;follows:
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
032&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
033&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.&nbsp;`:minor`&nbsp;things&nbsp;which&nbsp;I&nbsp;consider&nbsp;to&nbsp;be&nbsp;faults,&nbsp;but&nbsp;which&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
034&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;don&#x27;t&nbsp;actually&nbsp;breach&nbsp;the&nbsp;spec;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
035&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.&nbsp;`:should`&nbsp;instances&nbsp;where&nbsp;the&nbsp;spec&nbsp;says&nbsp;something&nbsp;SHOULD
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
036&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;be&nbsp;done,&nbsp;which&nbsp;isn&#x27;t;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
037&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.&nbsp;`:must`&nbsp;instances&nbsp;where&nbsp;the&nbsp;spec&nbsp;says&nbsp;something&nbsp;MUST
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
038&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;be&nbsp;done,&nbsp;which&nbsp;isn&#x27;t;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
039&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4.&nbsp;`:critical`&nbsp;instances&nbsp;where&nbsp;I&nbsp;believe&nbsp;the&nbsp;fault&nbsp;means&nbsp;that
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
040&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the&nbsp;object&nbsp;cannot&nbsp;be&nbsp;meaningfully&nbsp;processed.&quot;
</span><br/>
<span class="covered" title="5 out of 5 forms covered">
041&nbsp;&nbsp;&nbsp;&nbsp;#{:minor&nbsp;:should&nbsp;:must&nbsp;:critical})
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
042&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
043&nbsp;&nbsp;(def&nbsp;^:const&nbsp;severity-filters
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
044&nbsp;&nbsp;&nbsp;&nbsp;&quot;Hack&nbsp;for&nbsp;implementing&nbsp;a&nbsp;severity&nbsp;hierarchy&quot;
</span><br/>
<span class="covered" title="7 out of 7 forms covered">
045&nbsp;&nbsp;&nbsp;&nbsp;{:all&nbsp;#{}
</span><br/>
<span class="covered" title="2 out of 2 forms covered">
046&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:minor&nbsp;#{:minor}
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
047&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:should&nbsp;#{:minor&nbsp;:should}
</span><br/>
<span class="covered" title="4 out of 4 forms covered">
048&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:must&nbsp;#{:minor&nbsp;:should&nbsp;:must}
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
049&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:critical&nbsp;severity})
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
050&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
051&nbsp;&nbsp;(defn&nbsp;filter-severity
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
052&nbsp;&nbsp;&nbsp;&nbsp;&quot;Return&nbsp;a&nbsp;list&nbsp;of&nbsp;reports&nbsp;taken&nbsp;from&nbsp;these&nbsp;`reports`&nbsp;where&nbsp;the&nbsp;severity
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
053&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;of&nbsp;the&nbsp;report&nbsp;is&nbsp;greater&nbsp;than&nbsp;this&nbsp;`severity`.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
054&nbsp;&nbsp;&nbsp;&nbsp;[reports&nbsp;severity]
</span><br/>
<span class="not-covered" title="0 out of 11 forms covered">
055&nbsp;&nbsp;&nbsp;&nbsp;(assert&nbsp;
</span><br/>
<span class="not-covered" title="0 out of 10 forms covered">
056&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(and&nbsp;
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
057&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(coll?&nbsp;reports)&nbsp;
</span><br/>
<span class="not-covered" title="0 out of 4 forms covered">
058&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(every?&nbsp;map?&nbsp;reports)&nbsp;
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
059&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(every?&nbsp;:severity&nbsp;reports)))
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
060&nbsp;&nbsp;&nbsp;&nbsp;(remove&nbsp;
</span><br/>
<span class="not-covered" title="0 out of 7 forms covered">
061&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#((severity-filters&nbsp;severity)&nbsp;(:severity&nbsp;%))
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
062&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reports))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
063&nbsp;&nbsp;
</span><br/>
<span class="covered" title="2 out of 2 forms covered">
064&nbsp;&nbsp;(def&nbsp;^:const&nbsp;activitystreams-context-uri
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
065&nbsp;&nbsp;&nbsp;&nbsp;&quot;The&nbsp;URI&nbsp;of&nbsp;the&nbsp;context&nbsp;of&nbsp;an&nbsp;ActivityStreams&nbsp;object&nbsp;is&nbsp;expected&nbsp;to&nbsp;be&nbsp;this
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
066&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;literal&nbsp;string.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
067&nbsp;&nbsp;&nbsp;&nbsp;&quot;https:&#x2F;&#x2F;www.w3.org&#x2F;ns&#x2F;activitystreams&quot;)
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
068&nbsp;&nbsp;
</span><br/>
<span class="covered" title="2 out of 2 forms covered">
069&nbsp;&nbsp;(def&nbsp;^:const&nbsp;validation-fault-context-uri
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
070&nbsp;&nbsp;&nbsp;&nbsp;&quot;The&nbsp;URI&nbsp;of&nbsp;the&nbsp;context&nbsp;of&nbsp;a&nbsp;validation&nbsp;fault&nbsp;report&nbsp;object&nbsp;shall&nbsp;be&nbsp;this
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
071&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;literal&nbsp;string.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
072&nbsp;&nbsp;&nbsp;&nbsp;&quot;https:&#x2F;&#x2F;simon-brooke.github.io&#x2F;dog-and-duck&#x2F;codox&#x2F;Validation_Faults.html&quot;)
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
073&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
074&nbsp;&nbsp;(defn&nbsp;context?
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
075&nbsp;&nbsp;&nbsp;&nbsp;&quot;Returns&nbsp;`true`&nbsp;iff&nbsp;`x`&nbsp;quacks&nbsp;like&nbsp;an&nbsp;ActivityStreams&nbsp;context,&nbsp;else&nbsp;false.
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
076&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
077&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;context&nbsp;is&nbsp;either
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
078&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.&nbsp;the&nbsp;URI&nbsp;(actually&nbsp;an&nbsp;IRI)&nbsp;`activitystreams-context-uri`,&nbsp;or
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
079&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.&nbsp;a&nbsp;collection&nbsp;comprising&nbsp;that&nbsp;URI&nbsp;and&nbsp;a&nbsp;map.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
080&nbsp;&nbsp;&nbsp;&nbsp;[x]
</span><br/>
<span class="partial" title="4 out of 6 forms covered">
081&nbsp;&nbsp;&nbsp;&nbsp;(cond
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
082&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(nil?&nbsp;x)&nbsp;false
</span><br/>
<span class="covered" title="11 out of 11 forms covered">
083&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(string?&nbsp;x)&nbsp;(and&nbsp;(=&nbsp;x&nbsp;activitystreams-context-uri)&nbsp;true)
</span><br/>
<span class="partial" title="19 out of 20 forms covered">
084&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(coll?&nbsp;x)&nbsp;(and&nbsp;(context?&nbsp;(first&nbsp;(remove&nbsp;map?&nbsp;x)))
</span><br/>
<span class="covered" title="4 out of 4 forms covered">
085&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(=&nbsp;(count&nbsp;x)&nbsp;2)
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
086&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;true)
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
087&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:else&nbsp;false))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
088&nbsp;&nbsp;
</span><br/>
<span class="partial" title="38 out of 40 forms covered">
089&nbsp;&nbsp;(defmacro&nbsp;has-context?
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
090&nbsp;&nbsp;&nbsp;&nbsp;&quot;True&nbsp;if&nbsp;`x`&nbsp;is&nbsp;an&nbsp;ActivityStreams&nbsp;object&nbsp;with&nbsp;a&nbsp;valid&nbsp;context,&nbsp;else&nbsp;`false`.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
091&nbsp;&nbsp;&nbsp;&nbsp;[x]
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
092&nbsp;&nbsp;&nbsp;&nbsp;`(context?&nbsp;((keyword&nbsp;&quot;@context&quot;)&nbsp;~x)))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
093&nbsp;&nbsp;
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
094&nbsp;&nbsp;
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
095&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
096&nbsp;&nbsp;(defn&nbsp;make-fault-object
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
097&nbsp;&nbsp;&nbsp;&nbsp;&quot;Return&nbsp;a&nbsp;fault&nbsp;object&nbsp;with&nbsp;these&nbsp;`severity`,&nbsp;`fault`&nbsp;and&nbsp;`narrative`&nbsp;values.
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
098&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
099&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;An&nbsp;ActivityPub&nbsp;object&nbsp;MUST&nbsp;have&nbsp;a&nbsp;globally&nbsp;unique&nbsp;ID.&nbsp;Whether&nbsp;this&nbsp;is&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
100&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;meaningful&nbsp;depends&nbsp;on&nbsp;whether&nbsp;we&nbsp;persist&nbsp;fault&nbsp;report&nbsp;objects&nbsp;and&nbsp;serve
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;them,&nbsp;which&nbsp;at&nbsp;present&nbsp;I&nbsp;have&nbsp;no&nbsp;plans&nbsp;to&nbsp;do.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
102&nbsp;&nbsp;&nbsp;&nbsp;[severity&nbsp;fault&nbsp;narrative]
</span><br/>
<span class="not-covered" title="0 out of 9 forms covered">
103&nbsp;&nbsp;&nbsp;&nbsp;(assoc&nbsp;{}
</span><br/>
<span class="not-covered" title="0 out of 4 forms covered">
104&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(keyword&nbsp;&quot;@context&quot;)&nbsp;validation-fault-context-uri
</span><br/>
<span class="not-covered" title="0 out of 5 forms covered">
105&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:id&nbsp;(str&nbsp;&quot;https:&#x2F;&#x2F;&quot;
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
106&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(..&nbsp;java.net.InetAddress&nbsp;getLocalHost&nbsp;getHostName)
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
107&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&#x2F;fault&#x2F;&quot;
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
108&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pid
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
109&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;:&quot;
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
110&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(inst-ms&nbsp;(java.util.Date.)))
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
111&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:type&nbsp;&quot;Fault&quot;
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
112&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:severity&nbsp;severity
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
113&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:fault&nbsp;fault
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
114&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:narrative&nbsp;narrative))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
115&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
116&nbsp;&nbsp;(defn&nbsp;object-faults
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
117&nbsp;&nbsp;&nbsp;&nbsp;[x]
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
118&nbsp;&nbsp;&nbsp;&nbsp;(remove&nbsp;
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
119&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;empty?
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
120&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(list
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
121&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(when-not
</span><br/>
<span class="not-covered" title="0 out of 5 forms covered">
122&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(has-context?&nbsp;x)
</span><br/>
<span class="not-covered" title="0 out of 5 forms covered">
123&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(make-fault-object&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
124&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:should&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
125&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:no-context&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
126&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Section&nbsp;3&nbsp;of&nbsp;the&nbsp;ActivityPub&nbsp;specification&nbsp;states&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
127&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`Implementers&nbsp;SHOULD&nbsp;include&nbsp;the&nbsp;ActivityPub&nbsp;context&nbsp;in&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
128&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;their&nbsp;object&nbsp;definitions`.&quot;)
</span><br/>
<span class="not-covered" title="0 out of 6 forms covered">
129&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(when-not&nbsp;(:type&nbsp;x)&nbsp;
</span><br/>
<span class="not-covered" title="0 out of 5 forms covered">
130&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(make-fault-object&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
131&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:minor&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
132&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:no-type
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
133&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;The&nbsp;ActivityPub&nbsp;specification&nbsp;states&nbsp;that&nbsp;the&nbsp;`type`&nbsp;field&nbsp;is
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
134&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional,&nbsp;but&nbsp;it&nbsp;is&nbsp;hard&nbsp;to&nbsp;process&nbsp;objects&nbsp;with&nbsp;no&nbsp;known&nbsp;type.&quot;))
</span><br/>
<span class="not-covered" title="0 out of 7 forms covered">
135&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(when-not&nbsp;(contains?&nbsp;x&nbsp;:id)
</span><br/>
<span class="not-covered" title="0 out of 5 forms covered">
136&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(make-fault-object
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
137&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:minor
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
138&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:no-id-transient
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
139&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;The&nbsp;ActivityPub&nbsp;specification&nbsp;allows&nbsp;objects&nbsp;without&nbsp;`id`&nbsp;fields
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
140&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;only&nbsp;if&nbsp;they&nbsp;are&nbsp;intentionally&nbsp;transient;&nbsp;even&nbsp;so&nbsp;it&nbsp;is&nbsp;preferred
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
141&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;that&nbsp;the&nbsp;object&nbsp;should&nbsp;have&nbsp;an&nbsp;explicit&nbsp;null&nbsp;id.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
142&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;))
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
143&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;))))
</span><br/>
</body>
</html>

File diff suppressed because it is too large Load diff

View file

@ -139,5 +139,11 @@
<span class="covered" title="5 out of 5 forms covered">
045&nbsp;&nbsp;&nbsp;(file-seq&nbsp;(file&nbsp;&quot;resources&#x2F;activitystreams-test-documents&quot;)))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
046&nbsp;&nbsp;
</span><br/>
<span class="covered" title="9 out of 9 forms covered">
047&nbsp;&nbsp;(-&gt;&nbsp;&quot;resources&#x2F;activitystreams-test-documents&#x2F;simple0020.json&quot;&nbsp;slurp&nbsp;clean&nbsp;first&nbsp;:actor)
</span><br/>
</body>
</html>

View file

@ -137,7 +137,7 @@
044&nbsp;&nbsp;;;;&nbsp;examine&nbsp;what&nbsp;you&nbsp;got&nbsp;back!
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
045&nbsp;&nbsp;(:outbox&nbsp;account)
045&nbsp;&nbsp;(:inbox&nbsp;account)
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
046&nbsp;&nbsp;
@ -184,5 +184,8 @@
<span class="not-tracked" title="0 out of 0 forms covered">
060&nbsp;&nbsp;&nbsp;&nbsp;)
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
061&nbsp;&nbsp;
</span><br/>
</body>
</html>

View file

@ -0,0 +1,77 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" href="../../coverage.css"/> <title> dog_and_duck/utils/process.clj </title>
</head>
<body>
<span class="covered" title="1 out of 1 forms covered">
001&nbsp;&nbsp;(ns&nbsp;dog-and-duck.utils.process
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
002&nbsp;&nbsp;&nbsp;&nbsp;(:require&nbsp;[clojure.string&nbsp;:refer&nbsp;[split]]))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
003&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
004&nbsp;&nbsp;(def&nbsp;pid
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
005&nbsp;&nbsp;&nbsp;&nbsp;&quot;OK,&nbsp;this&nbsp;is&nbsp;hacky&nbsp;as&nbsp;fuck,&nbsp;but&nbsp;I&nbsp;hope&nbsp;it&nbsp;works.&nbsp;The&nbsp;problem&nbsp;is&nbsp;that&nbsp;the
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
006&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;way&nbsp;to&nbsp;get&nbsp;the&nbsp;process&nbsp;id&nbsp;has&nbsp;changed&nbsp;several&nbsp;times&nbsp;during&nbsp;the&nbsp;history
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
007&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;of&nbsp;Java&nbsp;development,&nbsp;and&nbsp;the&nbsp;code&nbsp;for&nbsp;one&nbsp;version&nbsp;of&nbsp;Java&nbsp;won&#x27;t&nbsp;even&nbsp;compile
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
008&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;in&nbsp;a&nbsp;different&nbsp;version.&quot;
</span><br/>
<span class="covered" title="9 out of 9 forms covered">
009&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[java-version&nbsp;(read-string&nbsp;(apply&nbsp;str&nbsp;(take&nbsp;2
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
010&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(split
</span><br/>
<span class="covered" title="2 out of 2 forms covered">
011&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(System&#x2F;getProperty&nbsp;&quot;java.version&quot;)
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
012&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&quot;[_\.]&quot;))))
</span><br/>
<span class="partial" title="4 out of 8 forms covered">
013&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmd&nbsp;(case&nbsp;java-version
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
014&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;18&nbsp;&quot;(let&nbsp;[[_&nbsp;pid&nbsp;hostname]
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
015&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(re-find
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
016&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#\&quot;^(\\d+)@(.*)\&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
017&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.getName
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
018&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(java.lang.management.ManagementFactory&#x2F;getRuntimeMXBean)))]
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
019&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pid)&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
020&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(19&nbsp;110)&nbsp;&quot;(.pid&nbsp;(java.lang.ProcessHandle&#x2F;current))&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
021&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;111&nbsp;&quot;(.getPid&nbsp;(java.lang.management.ManagementFactory&#x2F;getRuntimeMXBean))&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
022&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;:default&quot;)]
</span><br/>
<span class="covered" title="5 out of 5 forms covered">
023&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(eval&nbsp;(read-string&nbsp;cmd))))
</span><br/>
</body>
</html>

View file

@ -29,7 +29,7 @@
style="width:69.76744186046511%;
float:left;"> 60 </div></td>
<td class="with-number">30.23 %</td>
<td class="with-number">147</td><td class="with-number">14</td><td class="with-number">86</td>
<td class="with-number">150</td><td class="with-number">14</td><td class="with-number">86</td>
</tr>
<tr>
<td><a href="clj_activitypub/internal/crypto.clj.html">clj-activitypub.internal.crypto</a></td><td class="with-bar"><div class="covered"
@ -44,7 +44,7 @@
style="width:60.869565217391305%;
float:left;"> 14 </div></td>
<td class="with-number">39.13 %</td>
<td class="with-number">36</td><td class="with-number">8</td><td class="with-number">23</td>
<td class="with-number">39</td><td class="with-number">8</td><td class="with-number">23</td>
</tr>
<tr>
<td><a href="clj_activitypub/internal/http_util.clj.html">clj-activitypub.internal.http-util</a></td><td class="with-bar"><div class="covered"
@ -59,7 +59,7 @@
style="width:20.0%;
float:left;"> 3 </div></td>
<td class="with-number">80.00 %</td>
<td class="with-number">25</td><td class="with-number">3</td><td class="with-number">15</td>
<td class="with-number">28</td><td class="with-number">3</td><td class="with-number">15</td>
</tr>
<tr>
<td><a href="clj_activitypub/internal/thread_cache.clj.html">clj-activitypub.internal.thread-cache</a></td><td class="with-bar"><div class="covered"
@ -76,7 +76,7 @@
style="width:8.823529411764707%;
float:left;"> 3 </div></td>
<td class="with-number">91.18 %</td>
<td class="with-number">44</td><td class="with-number">3</td><td class="with-number">34</td>
<td class="with-number">47</td><td class="with-number">3</td><td class="with-number">34</td>
</tr>
<tr>
<td><a href="clj_activitypub/webfinger.clj.html">clj-activitypub.webfinger</a></td><td class="with-bar"><div class="covered"
@ -91,24 +91,41 @@
style="width:11.11111111111111%;
float:left;"> 2 </div></td>
<td class="with-number">100.00 %</td>
<td class="with-number">32</td><td class="with-number">5</td><td class="with-number">18</td>
<td class="with-number">35</td><td class="with-number">5</td><td class="with-number">18</td>
</tr>
<tr>
<td><a href="dog_and_duck/quack/picky.clj.html">dog-and-duck.quack.picky</a></td><td class="with-bar"><div class="covered"
style="width:49.779735682819386%;
float:left;"> 113 </div><div class="not-covered"
style="width:50.220264317180614%;
float:left;"> 114 </div></td>
<td class="with-number">49.78 %</td>
<td class="with-bar"><div class="covered"
style="width:38.775510204081634%;
float:left;"> 19 </div><div class="partial"
style="width:6.122448979591836%;
float:left;"> 3 </div><div class="not-covered"
style="width:55.10204081632653%;
float:left;"> 27 </div></td>
<td class="with-number">44.90 %</td>
<td class="with-number">143</td><td class="with-number">11</td><td class="with-number">49</td>
</tr>
<tr>
<td><a href="dog_and_duck/quack/quack.clj.html">dog-and-duck.quack.quack</a></td><td class="with-bar"><div class="covered"
style="width:44.419642857142854%;
float:left;"> 199 </div><div class="not-covered"
style="width:55.580357142857146%;
float:left;"> 249 </div></td>
<td class="with-number">44.42 %</td>
style="width:48.36734693877551%;
float:left;"> 237 </div><div class="not-covered"
style="width:51.63265306122449%;
float:left;"> 253 </div></td>
<td class="with-number">48.37 %</td>
<td class="with-bar"><div class="covered"
style="width:45.588235294117645%;
float:left;"> 31 </div><div class="partial"
style="width:7.352941176470588%;
float:left;"> 5 </div><div class="not-covered"
style="width:47.05882352941177%;
float:left;"> 32 </div></td>
<td class="with-number">52.94 %</td>
<td class="with-number">187</td><td class="with-number">26</td><td class="with-number">68</td>
style="width:43.28358208955224%;
float:left;"> 29 </div><div class="partial"
style="width:16.417910447761194%;
float:left;"> 11 </div><div class="not-covered"
style="width:40.298507462686565%;
float:left;"> 27 </div></td>
<td class="with-number">59.70 %</td>
<td class="with-number">227</td><td class="with-number">26</td><td class="with-number">67</td>
</tr>
<tr>
<td><a href="dog_and_duck/scratch/core.clj.html">dog-and-duck.scratch.core</a></td><td class="with-bar"><div class="covered"
@ -127,20 +144,20 @@
</tr>
<tr>
<td><a href="dog_and_duck/scratch/parser.clj.html">dog-and-duck.scratch.parser</a></td><td class="with-bar"><div class="covered"
style="width:50.0%;
float:left;"> 34 </div><div class="not-covered"
style="width:50.0%;
style="width:55.84415584415584%;
float:left;"> 43 </div><div class="not-covered"
style="width:44.15584415584416%;
float:left;"> 34 </div></td>
<td class="with-number">50.00 %</td>
<td class="with-number">55.84 %</td>
<td class="with-bar"><div class="covered"
style="width:55.55555555555556%;
float:left;"> 10 </div><div class="partial"
style="width:5.555555555555555%;
style="width:57.89473684210526%;
float:left;"> 11 </div><div class="partial"
style="width:5.2631578947368425%;
float:left;"> 1 </div><div class="not-covered"
style="width:38.888888888888886%;
style="width:36.8421052631579%;
float:left;"> 7 </div></td>
<td class="with-number">61.11 %</td>
<td class="with-number">45</td><td class="with-number">7</td><td class="with-number">18</td>
<td class="with-number">63.16 %</td>
<td class="with-number">47</td><td class="with-number">8</td><td class="with-number">19</td>
</tr>
<tr>
<td><a href="dog_and_duck/scratch/scratch.clj.html">dog-and-duck.scratch.scratch</a></td><td class="with-bar"><div class="covered"
@ -151,13 +168,28 @@
style="width:100.0%;
float:left;"> 19 </div></td>
<td class="with-number">100.00 %</td>
<td class="with-number">60</td><td class="with-number">9</td><td class="with-number">19</td>
<td class="with-number">61</td><td class="with-number">10</td><td class="with-number">19</td>
</tr>
<tr>
<td><a href="dog_and_duck/utils/process.clj.html">dog-and-duck.utils.process</a></td><td class="with-bar"><div class="covered"
style="width:86.20689655172414%;
float:left;"> 25 </div><div class="not-covered"
style="width:13.793103448275861%;
float:left;"> 4 </div></td>
<td class="with-number">86.21 %</td>
<td class="with-bar"><div class="covered"
style="width:85.71428571428571%;
float:left;"> 6 </div><div class="partial"
style="width:14.285714285714286%;
float:left;"> 1 </div></td>
<td class="with-number">100.00 %</td>
<td class="with-number">23</td><td class="with-number">1</td><td class="with-number">7</td>
</tr>
<tr><td>Totals:</td>
<td class="with-bar"></td>
<td class="with-number">51.59 %</td>
<td class="with-number">53.33 %</td>
<td class="with-bar"></td>
<td class="with-number">57.75 %</td>
<td class="with-number">58.24 %</td>
</tr>
</table>
</body>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View file

@ -1,14 +1,25 @@
<html>
<head>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>The Old Dog and Duck: Documentation</title>
<link rel="stylesheet" type="text/css" href="codox/css/default.css" />
</head>
<body>
</head>
<body>
<h1>The Old Dog and Duck: Documentation</h1>
<img src="images/Dog_and_Duck_tavern.jpg" alt="Victorian painting by Thomas H. Shepherd, based on a 1646 drawing">
<p>'The Old Dog and Duck' is a fairly common pub name;
<a href="https://en.wikipedia.org/wiki/Dog_and_Duck,_St_George%27s_Fields">
the instance in the picture</a>
stood in St George's Fields, London from the seventeenth century
until 1812, when the site was cleared to make way for the new Bethlehem
Hospital.
</p>
<ul>
<li><a href="codox/index.html">Primary documentaion</a></li>
<li><a href="codox/index.html">Primary documentation</a></li>
<li><a href="cloverage/index.html">Test coverage</a></li>
</ul>
</body>
</body>
</html>

View file

@ -6,8 +6,7 @@
:doc/format :markdown}
:output-path "docs/codox"
:source-uri "https://github.com/simon-brooke/dog-and-duck/blob/master/{filepath}#L{line}"}
:description "A Clojure library designed to implement the ActivityPub protocol."
:description "A playground for hacking ActivityPub stuff."
:dependencies [[org.clojure/clojure "1.11.1"]
[org.clojure/data.json "2.4.0"]
[org.clojure/math.numeric-tower "0.0.5"]

View file

@ -0,0 +1,14 @@
{
"id": "https://mastodon.scot/users/simon_brooke/statuses/109545810804143431/activity",
"type": "Announce",
"actor": "https://mastodon.scot/users/simon_brooke",
"published": "2022-12-20T11:40:19Z",
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"cc": [
"https://mastodon.social/users/borkdude",
"https://mastodon.scot/users/simon_brooke/followers"
],
"object": "https://mastodon.social/users/borkdude/statuses/109545794618575668"
}

View file

@ -0,0 +1,63 @@
{
"id": "https://mastodon.scot/users/simon_brooke/statuses/109545806233872328/activity",
"type": "Create",
"actor": "https://mastodon.scot/users/simon_brooke",
"published": "2022-12-20T11:39:10Z",
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"cc": [
"https://mastodon.scot/users/simon_brooke/followers"
],
"object": {
"inReplyTo": null,
"content": "<p>I&#39;m still looking for a repository of <a href=\"https://mastodon.scot/tags/ActivityPub\" class=\"mention hashtag\" rel=\"tag\">#<span>ActivityPub</span></a> sample documents to run tests against. There&#39;s one of <a href=\"https://mastodon.scot/tags/ActivityStreams\" class=\"mention hashtag\" rel=\"tag\">#<span>ActivityStreams</span></a> documents here</p><p><a href=\"https://github.com/w3c-social/activitystreams-test-documents\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><span class=\"invisible\">https://</span><span class=\"ellipsis\">github.com/w3c-social/activity</span><span class=\"invisible\">streams-test-documents</span></a></p><p>but they don&#39;t conform to the ActivityPub specification. Please, has anyone got pointers?</p><p>Captures of actual live interchanges between ActivityPub servers would be especially useful.</p><p><a href=\"https://mastodon.scot/tags/ActivityPubInClojure\" class=\"mention hashtag\" rel=\"tag\">#<span>ActivityPubInClojure</span></a></p>",
"sensitive": false,
"cc": [
"https://mastodon.scot/users/simon_brooke/followers"
],
"type": "Note",
"attributedTo": "https://mastodon.scot/users/simon_brooke",
"summary": null,
"replies": {
"id": "https://mastodon.scot/users/simon_brooke/statuses/109545806233872328/replies",
"type": "Collection",
"first": {
"type": "CollectionPage",
"next": "https://mastodon.scot/users/simon_brooke/statuses/109545806233872328/replies?only_other_accounts=true&page=true",
"partOf": "https://mastodon.scot/users/simon_brooke/statuses/109545806233872328/replies",
"items": []
}
},
"id": "https://mastodon.scot/users/simon_brooke/statuses/109545806233872328",
"contentMap": {
"en": "<p>I&#39;m still looking for a repository of <a href=\"https://mastodon.scot/tags/ActivityPub\" class=\"mention hashtag\" rel=\"tag\">#<span>ActivityPub</span></a> sample documents to run tests against. There&#39;s one of <a href=\"https://mastodon.scot/tags/ActivityStreams\" class=\"mention hashtag\" rel=\"tag\">#<span>ActivityStreams</span></a> documents here</p><p><a href=\"https://github.com/w3c-social/activitystreams-test-documents\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><span class=\"invisible\">https://</span><span class=\"ellipsis\">github.com/w3c-social/activity</span><span class=\"invisible\">streams-test-documents</span></a></p><p>but they don&#39;t conform to the ActivityPub specification. Please, has anyone got pointers?</p><p>Captures of actual live interchanges between ActivityPub servers would be especially useful.</p><p><a href=\"https://mastodon.scot/tags/ActivityPubInClojure\" class=\"mention hashtag\" rel=\"tag\">#<span>ActivityPubInClojure</span></a></p>"
},
"conversation": "tag:mastodon.scot,2022-12-20:objectId=39176769:objectType=Conversation",
"url": "https://mastodon.scot/@simon_brooke/109545806233872328",
"inReplyToAtomUri": null,
"tag": [
{
"type": "Hashtag",
"href": "https://mastodon.scot/tags/activitypubinclojure",
"name": "#activitypubinclojure"
},
{
"type": "Hashtag",
"href": "https://mastodon.scot/tags/activitystreams",
"name": "#activitystreams"
},
{
"type": "Hashtag",
"href": "https://mastodon.scot/tags/activitypub",
"name": "#activitypub"
}
],
"atomUri": "https://mastodon.scot/users/simon_brooke/statuses/109545806233872328",
"published": "2022-12-20T11:39:10Z",
"attachment": [],
"to": [
"https://www.w3.org/ns/activitystreams#Public"
]
}
}

View file

@ -0,0 +1,8 @@
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://mastodon.scot/users/simon_brooke/outbox",
"type": "OrderedCollection",
"totalItems": 2881,
"first": "https://mastodon.scot/users/simon_brooke/outbox?page=true",
"last": "https://mastodon.scot/users/simon_brooke/outbox?min_id=0\u0026page=true"
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,143 @@
(ns dog-and-duck.quack.picky "Fault-finder for ActivityPub documents.
Generally, each `-faults` function will return:
1. `nil` if no faults were found;
2. a sequence of fault objects if faults were found.
Each fault object shall have the properties:
1. `:@context` whose value shall be the URL of a
document specifying this vocabulary;
2. `:type` whose value shall be `Fault`;
3. `:severity` whose value shall be one of
`minor`, `should`, `must` or `critical`;
4. `:fault` whose value shall be a unique token
representing the particular fault type;
5. `:narrative` whose value shall be a natural
language description of the fault type.
Note that the reason for the `:fault` property is
to be able to have a well known place, linked to
from the @context URL, which allows narratives
for each fault type to be served in as many
natural languages as possible.
The idea further is that it should ultimately be
possible to serialise a fault report as a
document which in its own right conforms to the
ActivityStreams spec."
(:require [dog-and-duck.utils.process :refer [pid]]))
(def ^:const severity
"Severity of faults found, as follows:
1. `:minor` things which I consider to be faults, but which
don't actually breach the spec;
2. `:should` instances where the spec says something SHOULD
be done, which isn't;
3. `:must` instances where the spec says something MUST
be done, which isn't;
4. `:critical` instances where I believe the fault means that
the object cannot be meaningfully processed."
#{:minor :should :must :critical})
(def ^:const severity-filters
"Hack for implementing a severity hierarchy"
{:all #{}
:minor #{:minor}
:should #{:minor :should}
:must #{:minor :should :must}
:critical severity})
(defn filter-severity
"Return a list of reports taken from these `reports` where the severity
of the report is greater than this `severity`."
[reports severity]
(assert
(and
(coll? reports)
(every? map? reports)
(every? :severity reports)))
(remove
#((severity-filters severity) (:severity %))
reports))
(def ^:const activitystreams-context-uri
"The URI of the context of an ActivityStreams object is expected to be this
literal string."
"https://www.w3.org/ns/activitystreams")
(def ^:const validation-fault-context-uri
"The URI of the context of a validation fault report object shall be this
literal string."
"https://simon-brooke.github.io/dog-and-duck/codox/Validation_Faults.html")
(defn context?
"Returns `true` iff `x` quacks like an ActivityStreams context, else false.
A context is either
1. the URI (actually an IRI) `activitystreams-context-uri`, or
2. a collection comprising that URI and a map."
[x]
(cond
(nil? x) false
(string? x) (and (= x activitystreams-context-uri) true)
(coll? x) (and (context? (first (remove map? x)))
(= (count x) 2)
true)
:else false))
(defmacro has-context?
"True if `x` is an ActivityStreams object with a valid context, else `false`."
[x]
`(context? ((keyword "@context") ~x)))
(defn make-fault-object
"Return a fault object with these `severity`, `fault` and `narrative` values.
An ActivityPub object MUST have a globally unique ID. Whether this is
meaningful depends on whether we persist fault report objects and serve
them, which at present I have no plans to do."
[severity fault narrative]
(assoc {}
(keyword "@context") validation-fault-context-uri
:id (str "https://"
(.. java.net.InetAddress getLocalHost getHostName)
"/fault/"
pid
":"
(inst-ms (java.util.Date.)))
:type "Fault"
:severity severity
:fault fault
:narrative narrative))
(defn object-faults
[x]
(remove
empty?
(list
(when-not
(has-context? x)
(make-fault-object
:should
:no-context
"Section 3 of the ActivityPub specification states
`Implementers SHOULD include the ActivityPub context in
their object definitions`.")
(when-not (:type x)
(make-fault-object
:minor
:no-type
"The ActivityPub specification states that the `type` field is
optional, but it is hard to process objects with no known type."))
(when-not (contains? x :id)
(make-fault-object
:minor
:no-id-transient
"The ActivityPub specification allows objects without `id` fields
only if they are intentionally transient; even so it is preferred
that the object should have an explicit null id."
))
))))

View file

@ -1,6 +1,21 @@
(ns dog-and-duck.quack.quack
"Validator for ActivityPub objects: if it walks like a duck, and it quacks like a duck..."
"Validator for ActivityPub objects: if it walks like a duck, and it quacks
like a duck...
**NOTE THAT the ActivityPub spec
[says](https://www.w3.org/TR/activitypub/#obj)
> Servers SHOULD validate the content they receive to avoid content
> spoofing attacks
but in practice ActivityPub content collected in the wild bears only
a hazy relationship to the spec, so this is difficult. I suspect that
I may have to implement a `*strict*` dynamic variable, so that users can
toggle some checks off."
;;(:require [clojure.spec.alpha as s])
(:require [dog-and-duck.quack.picky :refer [filter-severity has-context?
object-faults]])
(:import [java.net URI URISyntaxException]))
;;; Copyright (C) Simon Brooke, 2022
@ -30,9 +45,18 @@
But we are *just not having that*, because otherwise we're flying blind.
We *shall* reject objects lacking at least `:type`. Missing `:id` keys are
tolerable because they represent transient objects, which we expect to
handle."
[x]
handle.
**NOTE THAT** The ActivityPub spec [says](https://www.w3.org/TR/activitypub/#obj)
> Implementers SHOULD include the ActivityPub context in their object
> definitions
but in samples found in the wild they typically don't."
([x]
(and (map? x) (:type x) true))
([x severity]
(empty? (filter-severity (object-faults x) severity))))
(defn persistent-object?
"`true` iff `x` is a persistent object.
@ -44,7 +68,7 @@
(and (object? x) (uri? (URI. (:id x))))
(catch URISyntaxException _ false)))
(persistent-object? {:type "test" :id "https://mastodon.scot/@barfilfarm"})
;; (persistent-object? {:type "test" :id "https://mastodon.scot/@barfilfarm"})
(def ^:const actor-types
"The set of types we will accept as actors.
@ -57,10 +81,12 @@
"Person"
"Service"})
(defn actor-type?
;; TODO: better as a macro
[x]
(if (actor-types x) true false))
(defmacro actor-type?
"Return `true` iff the `x` is a recognised actor type, else `false`."
[^String x]
`(if (actor-types ~x) true false))
;; (actor-type? "Group")
(def ^:const verb-types
"The set of types we will accept as verbs.
@ -72,47 +98,14 @@
"Offer" "Question" "Reject" "Read" "Remove" "TentativeAccept"
"TentativeReject" "Travel" "Undo" "Update" "View"})
(defn verb-type?
(defmacro verb-type?
;; TODO: better as a macro
[x]
(if (verb-types x) true false))
[^String x]
`(if (verb-types ~x) true false))
(def ^:const activitystreams-context-uri
"The URI of the context of an ActivityStreams object is expected to be this
literal string."
"https://www.w3.org/ns/activitystreams")
(defn context?
"Returns `true` iff `x` quacks like an ActivityStreams context, else false.
A context is either
1. the URI (actually an IRI) `activitystreams-context-uri`, or
2. a collection comprising that URI and a map."
[x]
(cond
(nil? x) false
(string? x) (and (= x activitystreams-context-uri) true)
(coll? x) (and (context? (first (remove map? x)))
(= (count x) 2)
true)
:else false))
(defmacro has-context? [x]
`(context? ((keyword "@context") ~x)))
(defn actor?
"Returns `true` if `x` quacks like an actor, else false."
[x]
(and
(object? x)
(has-context? x)
(uri? (URI. (:inbox x)))
(uri? (URI. (:outbox x)))
(actor-type? (:type x))
true))
(defn activity?
"`true` iff `x` quacks like an activity, else false.
"Returns `true` if `x` quacks like an actor, else false.
**NOTE THAT** [Section 4.1 of the spec]
(https://www.w3.org/TR/activitypub/#actor-objects) says explicitly that
@ -126,11 +119,35 @@
However, none of the provided examples in the [activitystreams-test-documents repository]() does in fact have these properties"
[x]
(and
(object? x)
(has-context? x)
(uri? (URI. (:inbox x)))
(uri? (URI. (:outbox x)))
(actor-type? (:type x))
true))
(defn actor-or-uri?
"`true` if `x` is either a URI or an actor.
**TODO**: I need to decide about whether to reify referenced objects
before validation or after. After reification, every reference to an actor
*must be* to an actor object, but before, may only be to a URI pointing to
one."
[x]
(and
(cond (string? x) (uri? (URI. x))
:else (actor? x))
true))
(defn activity?
"`true` iff `x` quacks like an activity, else false."
[x]
(try
(and (object? x)
(has-context? x)
(string? (:summary x))
(actor? (:actor x))
(actor-or-uri? (:actor x))
(verb-type? (:type x))
(or (object? (:object x)) (uri? (URI. (:object x))))
true)
@ -156,35 +173,46 @@
true))
(defn collection?
"`true` iff `x` quacks like a collection of type `type`, else `false`.
"`true` iff `x` quacks like a collection of type `object-type`, else `false`.
With one argument, will recognise plain collections and ordered collections,
but (currently) not collection pages."
([x type]
([x ^String object-type]
(let [items (or (:items x) (:orderedItems x))]
(and
(cond
(:items x) (nil? (:orderedItems x))
(:orderedItems x) (nil? (:items x))) ;; can't have both properties
(:orderedItems x) (nil? (:items x)) ;; can't have both properties
(integer? (:totalItems x)) true ;; can have neither, provided it has totalItems.
:else false)
(object? x)
(= (:type x) type)
(coll? items)
(every? object? items)
(= (:type x) object-type)
(if items
(and (coll? items)
(every? object? items) ;; if there are items, they must form a
;; collection of objects.
true)
true) ;; but it's OK if there aren't.
true)
;; test for totalItems not done here, because collection pages don't
;; have it.
))
([x]
(and
(or (collection? x "Collection")
(collection? x "OrderedCollection"))
(integer? (:totalItems x))
true)))
([x]
(or (collection? x "Collection")
(collection? x "OrderedCollection"))))
(defn unordered-collection?
"`true` iff `x` quacks like an unordered collection, else `false`."
[x]
(collection? x "Collection"))
(and (collection? x "Collection") (integer? (:totalItems x)) true))
(defn ordered-collection?
"`true` iff `x` quacks like an ordered collection, else `false`."
[x]
(collection? x "OrderedCollection"))
(and (collection? x "OrderedCollection") (integer? (:totalItems x)) true))
(defn collection-page?
"`true` iff `x` quacks like a page in a paged collection, else `false`."

View file

@ -42,7 +42,7 @@
(apply webfinger/fetch-user-id (map handle [:domain :username]))))))
;;; examine what you got back!
(:outbox account)
(:inbox account)
(def rsa (pgp-gen/rsa-keypair-generator 2048))

View file

@ -0,0 +1,23 @@
(ns dog-and-duck.utils.process
(:require [clojure.string :refer [split]]))
(def pid
"OK, this is hacky as fuck, but I hope it works. The problem is that the
way to get the process id has changed several times during the history
of Java development, and the code for one version of Java won't even compile
in a different version."
(let [java-version (read-string (apply str (take 2
(split
(System/getProperty "java.version")
#"[_\.]"))))
cmd (case java-version
18 "(let [[_ pid hostname]
(re-find
#\"^(\\d+)@(.*)\"
(.getName
(java.lang.management.ManagementFactory/getRuntimeMXBean)))]
pid)"
(19 110) "(.pid (java.lang.ProcessHandle/current))"
111 "(.getPid (java.lang.management.ManagementFactory/getRuntimeMXBean))"
":default")]
(eval (read-string cmd))))

View file

@ -1,8 +1,10 @@
(ns dog-and-duck.quack.quack-test
(:require [clojure.test :refer [deftest is testing]]
[dog-and-duck.quack.quack :refer [activitystreams-context-uri
actor? actor-type? context?
object? persistent-object?
[dog-and-duck.quack.picky :refer [activitystreams-context-uri
context?]]
[dog-and-duck.quack.quack :refer [actor? actor-type?
object? ordered-collection-page?
persistent-object?
verb-type?]]
[dog-and-duck.scratch.parser :refer [clean]]))
@ -127,3 +129,13 @@
actual (actor? (-> "resources/activitystreams-test-documents/simple0020.json" slurp clean first :actor))]
(is (= actual expected) "A Person is an actor"))
))
(deftest ordered-collection-page-test
(testing "identification of ordered collection pages."
(let [expected false
actual (ordered-collection-page? (-> "resources/activitystreams-test-documents/simple0020.json" slurp clean first))]
(is (= actual expected) "A Note is not an ordered collection page."))
(let [expected true
actual (ordered-collection-page? (-> "resources/test_documents/outbox_page.json" slurp clean first))]
(is (= actual expected) "A page from an outbox is an ordered collection page."))
))