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]) (require '[dog-and-duck.quack.quack :as q])
``` ```
## Documentation
Full documentation is [here](https://simon-brooke.github.io/dog-and-duck/).
## Testing ## 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 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 # Using ActivityPub
```clojure ## Introduction
user=> (require '[clj-activitypub.core :as activitypub])
nil 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.
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>"}]}
```

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 001&nbsp;&nbsp;(ns&nbsp;clj-activitypub.core
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
007&nbsp;&nbsp; 010&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 5 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 8 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 5 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 3 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 3 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
022&nbsp;&nbsp; 025&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="covered" title="9 out of 9 forms covered"> <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><br/>
<span class="covered" title="4 out of 4 forms covered"> <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><br/>
<span class="covered" title="5 out of 5 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
030&nbsp;&nbsp; 033&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="3 out of 3 forms covered"> <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><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="covered" title="5 out of 5 forms covered"> <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><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="covered" title="2 out of 2 forms covered"> <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><br/>
<span class="covered" title="11 out of 11 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="covered" title="3 out of 3 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
043&nbsp;&nbsp; 046&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 12 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 4 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 4 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 8 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 6 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
058&nbsp;&nbsp; 061&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="6 out of 6 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
060&nbsp;&nbsp; 063&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 3 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 9 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 2 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 3 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 12 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 3 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 2 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
070&nbsp;&nbsp; 073&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 2 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 3 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 6 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 5 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 4 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 2 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 3 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 11 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 3 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 2 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
085&nbsp;&nbsp; 088&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 4 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 4 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 4 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 5 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 4 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
097&nbsp;&nbsp; 100&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="partial" title="1 out of 4 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
103&nbsp;&nbsp; 106&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="3 out of 3 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 14 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
117&nbsp;&nbsp; 120&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="partial" title="1 out of 2 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
123&nbsp;&nbsp; 126&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="3 out of 3 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 9 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
130&nbsp;&nbsp; 133&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="3 out of 3 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 9 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
137&nbsp;&nbsp; 140&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 5 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 4 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 4 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 3 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 4 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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/> </span><br/>
</body> </body>
</html> </html>

View file

@ -8,109 +8,118 @@
001&nbsp;&nbsp;(ns&nbsp;clj-activitypub.internal.crypto 001&nbsp;&nbsp;(ns&nbsp;clj-activitypub.internal.crypto
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
005&nbsp;&nbsp; 005&nbsp;&nbsp;&nbsp;&nbsp;(:require&nbsp;[clojure.java.io&nbsp;:as&nbsp;io])
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
006&nbsp;&nbsp;(java.security.Security&#x2F;addProvider 006&nbsp;&nbsp;&nbsp;&nbsp;(:import&nbsp;(java.util&nbsp;Base64)
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
007&nbsp;&nbsp;&nbsp;(org.bouncycastle.jce.provider.BouncyCastleProvider.)) 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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
008&nbsp;&nbsp; 008&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 2 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
013&nbsp;&nbsp; 016&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 6 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 3 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
017&nbsp;&nbsp; 020&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 2 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 2 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
021&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.getPrivate))) 024&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))
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
025&nbsp;&nbsp; 025&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <span class="covered" title="1 out of 1 forms covered">
026&nbsp;&nbsp;(defn&nbsp;sha256-base64&nbsp;[data] 026&nbsp;&nbsp;(defn&nbsp;base64-encode&nbsp;[bytes]
</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))]
</span><br/> </span><br/>
<span class="not-covered" title="0 out of 3 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
029&nbsp;&nbsp; 028&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 2 forms covered"> <span class="not-covered" title="0 out of 5 forms covered">
031&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[bytes&nbsp;(.getBytes&nbsp;data) 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 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><br/> </span><br/>
<span class="not-covered" title="0 out of 3 forms covered"> <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.)) 031&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(base64-encode&nbsp;digest)))
</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)))
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <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/> </span><br/>
</body> </body>
</html> </html>

View file

@ -8,76 +8,85 @@
001&nbsp;&nbsp;(ns&nbsp;clj-activitypub.internal.http-util 001&nbsp;&nbsp;(ns&nbsp;clj-activitypub.internal.http-util
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
006&nbsp;&nbsp; 009&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="covered" title="2 out of 2 forms covered"> <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><br/>
<span class="covered" title="2 out of 2 forms covered"> <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><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="covered" title="3 out of 3 forms covered"> <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><br/>
<span class="covered" title="11 out of 11 forms covered"> <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><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="covered" title="3 out of 3 forms covered"> <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><br/>
<span class="covered" title="2 out of 2 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
016&nbsp;&nbsp; 019&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 3 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 1 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
020&nbsp;&nbsp; 023&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 6 forms covered"> <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/> </span><br/>
</body> </body>
</html> </html>

View file

@ -5,136 +5,145 @@
</head> </head>
<body> <body>
<span class="covered" title="1 out of 1 forms covered"> <span class="covered" title="1 out of 1 forms covered">
001&nbsp;&nbsp;(ns&nbsp;clj-activitypub.internal.thread-cache) 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;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="covered" title="1 out of 1 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
006&nbsp;&nbsp;&nbsp;&nbsp;(System&#x2F;currentTimeMillis)) 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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
007&nbsp;&nbsp; 005&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="covered" title="2 out of 2 forms covered"> <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><br/>
<span class="covered" title="5 out of 5 forms covered"> <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><br/>
<span class="covered" title="7 out of 7 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
012&nbsp;&nbsp; 015&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="covered" title="3 out of 3 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="covered" title="4 out of 4 forms covered"> <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><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="covered" title="2 out of 2 forms covered"> <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><br/>
<span class="covered" title="5 out of 5 forms covered"> <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><br/>
<span class="covered" title="6 out of 6 forms covered"> <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><br/>
<span class="covered" title="2 out of 2 forms covered"> <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><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="covered" title="11 out of 11 forms covered"> <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><br/>
<span class="covered" title="5 out of 5 forms covered"> <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><br/>
<span class="covered" title="3 out of 3 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="covered" title="4 out of 4 forms covered"> <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><br/>
<span class="covered" title="5 out of 5 forms covered"> <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><br/>
<span class="covered" title="3 out of 3 forms covered"> <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><br/>
<span class="covered" title="3 out of 3 forms covered"> <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><br/>
<span class="partial" title="11 out of 12 forms covered"> <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><br/>
<span class="covered" title="4 out of 4 forms covered"> <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><br/>
<span class="covered" title="3 out of 3 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 2 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 6 forms covered"> <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><br/>
<span class="not-covered" title="0 out of 12 forms covered"> <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><br/>
<span class="covered" title="6 out of 6 forms covered"> <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><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="covered" title="1 out of 1 forms covered"> <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/> </span><br/>
</body> </body>
</html> </html>

View file

@ -8,97 +8,106 @@
001&nbsp;&nbsp;(ns&nbsp;clj-activitypub.webfinger 001&nbsp;&nbsp;(ns&nbsp;clj-activitypub.webfinger
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
005&nbsp;&nbsp; 008&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="2 out of 2 forms covered"> <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;) 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">
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))
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
010&nbsp;&nbsp; 010&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="covered" title="6 out of 6 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; 012&nbsp;&nbsp;&nbsp;&nbsp;(str&nbsp;&quot;acct:&quot;&nbsp;username&nbsp;&quot;@&quot;&nbsp;domain))
</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><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
017&nbsp;&nbsp; 013&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="covered" title="2 out of 2 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
019&nbsp;&nbsp;&nbsp;&nbsp;(thread-cache&#x2F;make)) 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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
020&nbsp;&nbsp; 020&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <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><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="covered" title="2 out of 2 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 022&nbsp;&nbsp;&nbsp;&nbsp;(thread-cache&#x2F;make))
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="blank" 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; 023&nbsp;&nbsp;
</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><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <span class="covered" title="1 out of 1 forms covered">
027&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fn&nbsp;[] 024&nbsp;&nbsp;(defn&nbsp;fetch-user-id
</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;%))
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <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/> </span><br/>
</body> </body>
</html> </html>

View file

@ -1,54 +1,73 @@
{"coverage": {"coverage":
{"dog_and_duck/quack/quack.clj": {"dog_and_duck/quack/quack.clj":
[null, 1, 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, 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,
17, null, 1, null, null, null, null, null, true, 5, null, null, 1, null, null, null, null, null, null, null, null, null, null, null,
null, 1, null, null, null, null, 1, null, null, null, null, null, 1, null, null, null, 1, null, null, null, null, null, null, null, null,
null, null, 4, null, 1, null, null, null, null, 1, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, 1, null, null, 4, null, 1, null, null, null, null, 1, null, 40, null, 0, null, 1, null, null, null, null, null, true, 4, null,
null, null, null, null, null, true, 10, 9, true, 2, null, null, null, null, null, 1, null, null, null, null, 1, null, null, null,
null, true, 2, null, 1, null, null, true, 2, 2, 0, 0, 0, null, null, null, null, true, null, null, 5, null, true, null, 1, null, null,
1, null, null, 0, 0, 0, 0, 0, 0, 0, null, null, null, 1, null, null, null, null, 1, null, null, null, null, true, null, null, 5, null,
0, 0, 0, null, null, 1, null, null, null, null, null, 0, 0, 0, null, null, 1, null, null, null, null, null, null, null, null, null, null,
null, 1, null, null, null, null, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, null, null, null, null, true, 2, 2, 0, 0, 0, null, null, 1, null,
null, null, 0, 0, null, 1, null, null, 0, null, 1, null, null, 0, null, null, null, null, null, null, 0, 0, 0, null, null, 1, null,
null, 1, null, null, 0, null, 1, null, null, 0, null, 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": "clj_activitypub/internal/http_util.clj":
[null, 1, null, null, null, null, null, 1, 1, 1, 1, 2, 2, 1, 1, 1, [null, 1, null, null, null, null, null, null, null, null, 1, 1, 1, 1,
null, 1, 0, 0, null, 1, null, null, null, 0], 2, 2, 1, 1, 1, null, 1, 0, 0, null, 1, null, null, null, 0],
"clj_activitypub/internal/thread_cache.clj": "clj_activitypub/internal/thread_cache.clj":
[null, 1, null, 1, null, null, 8, null, 1, 4, 4, 4, null, 1, null, 2, [null, 1, null, null, null, null, 1, null, null, 8, null, 1, 4, 4, 4,
null, 2, 2, 2, 2, 2, 2, 2, 2, null, 4, 4, 4, null, 4, 4, 2, 2, true, null, 1, null, 2, null, 2, 2, 2, 2, 2, 2, 2, 2, null, 4, 4, 4, null,
2, 2, null, 0, 0, 0, 2, 2, 2, 2], 4, 4, 2, 2, true, 2, 2, null, 0, 0, 0, 2, 2, 2, 2],
"dog_and_duck/scratch/parser.clj": "dog_and_duck/scratch/parser.clj":
[null, 1, 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, 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, null, 1, null, null, null, 10, 10, 10, 10, 10, true, 0, null, 1,
0, 0, 0, 0, 0, 0, 1], null, 1, 0, 0, 0, 0, 0, 0, 1, null, 1],
"clj_activitypub/core.clj": "clj_activitypub/core.clj":
[null, 1, null, null, null, null, null, null, 1, null, null, null, [null, 1, null, null, null, null, null, null, null, null, null, 1,
null, null, 0, 0, 0, 0, 0, 0, 0, 0, null, 1, null, null, null, 6, 2, null, null, null, null, null, 0, 0, 0, 0, 0, 0, 0, 0, null, 1, null,
2, null, 1, 1, null, null, null, 1, 1, 1, 1, null, null, 1, null, 1, null, null, 6, 2, 2, null, 1, 1, null, null, null, 1, 1, 1, 1, null,
null, null, null, 0, null, 0, null, 0, 0, 0, 0, 0, 0, null, 1, null, null, 1, null, 1, null, null, null, 0, null, 0, null, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, null, 1, null, null, 0, 0, 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, null, 1, null, null, null, 0, 0, 0, 0, 0, 0, 0, null, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, null, 1, null, null, null, 0, 0, 0, 0,
null, null, null, true, null, 1, null, null, null, null, null, 0, 0, 0, 0, null, 1, null, null, null, true, null, 1, null, null, null,
null, 0, 0, 0, 0, 0, null, 1, null, null, null, true, null, 1, 0, null, null, 0, null, 0, 0, 0, 0, 0, null, 1, null, null, null, true,
null, null, 0, 0, null, 1, 0, null, null, 0, 0, null, 1, null, null, null, 1, 0, null, null, 0, 0, null, 1, 0, null, null, 0, 0, null, 1,
null, 0, 0, 0, 0, 0, 0], null, null, null, 0, 0, 0, 0, 0, 0],
"clj_activitypub/internal/crypto.clj": "clj_activitypub/internal/crypto.clj":
[null, 1, null, null, null, null, 1, 1, null, 1, 0, 0, null, null, 1, [null, 1, null, null, null, null, null, null, null, 1, 1, null, 1, 0,
0, 0, null, 1, 0, 0, null, null, 1, 0, null, 1, 0, 0, null, 1, 0, 0, 0, null, null, 1, 0, 0, null, 1, 0, 0, null, null, 1, 0, null, 1, 0,
0, 0, 0, null], 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], "dog_and_duck/scratch/core.clj":[null, 1, null, 1, null, null, 0],
"clj_activitypub/webfinger.clj": "clj_activitypub/webfinger.clj":
[null, 1, null, null, null, null, 1, null, 1, 1, null, 1, null, null, [null, 1, null, null, null, null, null, null, null, 1, null, 1, 1,
1, 1, 1, null, 1, 1, null, 1, null, null, null, 3, 3, 3, true, 1, null, 1, null, null, 1, 1, 1, null, 1, 1, null, 1, null, null, null,
true, 2, null], 3, 3, 3, true, 1, true, 2, null],
"dog_and_duck/scratch/scratch.clj": "dog_and_duck/scratch/scratch.clj":
[null, 1, 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, 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, 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, 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"> <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;))) 045&nbsp;&nbsp;&nbsp;(file-seq&nbsp;(file&nbsp;&quot;resources&#x2F;activitystreams-test-documents&quot;)))
</span><br/> </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> </body>
</html> </html>

View file

@ -137,7 +137,7 @@
044&nbsp;&nbsp;;;;&nbsp;examine&nbsp;what&nbsp;you&nbsp;got&nbsp;back! 044&nbsp;&nbsp;;;;&nbsp;examine&nbsp;what&nbsp;you&nbsp;got&nbsp;back!
</span><br/> </span><br/>
<span class="covered" title="3 out of 3 forms covered"> <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><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
046&nbsp;&nbsp; 046&nbsp;&nbsp;
@ -184,5 +184,8 @@
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
060&nbsp;&nbsp;&nbsp;&nbsp;) 060&nbsp;&nbsp;&nbsp;&nbsp;)
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered">
061&nbsp;&nbsp;
</span><br/>
</body> </body>
</html> </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%; style="width:69.76744186046511%;
float:left;"> 60 </div></td> float:left;"> 60 </div></td>
<td class="with-number">30.23 %</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>
<tr> <tr>
<td><a href="clj_activitypub/internal/crypto.clj.html">clj-activitypub.internal.crypto</a></td><td class="with-bar"><div class="covered" <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%; style="width:60.869565217391305%;
float:left;"> 14 </div></td> float:left;"> 14 </div></td>
<td class="with-number">39.13 %</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>
<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" <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%; style="width:20.0%;
float:left;"> 3 </div></td> float:left;"> 3 </div></td>
<td class="with-number">80.00 %</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>
<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" <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%; style="width:8.823529411764707%;
float:left;"> 3 </div></td> float:left;"> 3 </div></td>
<td class="with-number">91.18 %</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>
<tr> <tr>
<td><a href="clj_activitypub/webfinger.clj.html">clj-activitypub.webfinger</a></td><td class="with-bar"><div class="covered" <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%; style="width:11.11111111111111%;
float:left;"> 2 </div></td> float:left;"> 2 </div></td>
<td class="with-number">100.00 %</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>
<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" <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%; style="width:48.36734693877551%;
float:left;"> 199 </div><div class="not-covered" float:left;"> 237 </div><div class="not-covered"
style="width:55.580357142857146%; style="width:51.63265306122449%;
float:left;"> 249 </div></td> float:left;"> 253 </div></td>
<td class="with-number">44.42 %</td> <td class="with-number">48.37 %</td>
<td class="with-bar"><div class="covered" <td class="with-bar"><div class="covered"
style="width:45.588235294117645%; style="width:43.28358208955224%;
float:left;"> 31 </div><div class="partial" float:left;"> 29 </div><div class="partial"
style="width:7.352941176470588%; style="width:16.417910447761194%;
float:left;"> 5 </div><div class="not-covered" float:left;"> 11 </div><div class="not-covered"
style="width:47.05882352941177%; style="width:40.298507462686565%;
float:left;"> 32 </div></td> float:left;"> 27 </div></td>
<td class="with-number">52.94 %</td> <td class="with-number">59.70 %</td>
<td class="with-number">187</td><td class="with-number">26</td><td class="with-number">68</td> <td class="with-number">227</td><td class="with-number">26</td><td class="with-number">67</td>
</tr> </tr>
<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" <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>
<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" <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%; style="width:55.84415584415584%;
float:left;"> 34 </div><div class="not-covered" float:left;"> 43 </div><div class="not-covered"
style="width:50.0%; style="width:44.15584415584416%;
float:left;"> 34 </div></td> 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" <td class="with-bar"><div class="covered"
style="width:55.55555555555556%; style="width:57.89473684210526%;
float:left;"> 10 </div><div class="partial" float:left;"> 11 </div><div class="partial"
style="width:5.555555555555555%; style="width:5.2631578947368425%;
float:left;"> 1 </div><div class="not-covered" float:left;"> 1 </div><div class="not-covered"
style="width:38.888888888888886%; style="width:36.8421052631579%;
float:left;"> 7 </div></td> float:left;"> 7 </div></td>
<td class="with-number">61.11 %</td> <td class="with-number">63.16 %</td>
<td class="with-number">45</td><td class="with-number">7</td><td class="with-number">18</td> <td class="with-number">47</td><td class="with-number">8</td><td class="with-number">19</td>
</tr> </tr>
<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" <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%; style="width:100.0%;
float:left;"> 19 </div></td> float:left;"> 19 </div></td>
<td class="with-number">100.00 %</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>
<tr><td>Totals:</td> <tr><td>Totals:</td>
<td class="with-bar"></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-bar"></td>
<td class="with-number">57.75 %</td> <td class="with-number">58.24 %</td>
</tr> </tr>
</table> </table>
</body> </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> <html>
<head>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>The Old Dog and Duck: Documentation</title> <title>The Old Dog and Duck: Documentation</title>
<link rel="stylesheet" type="text/css" href="codox/css/default.css" /> <link rel="stylesheet" type="text/css" href="codox/css/default.css" />
</head> </head>
<body>
<body>
<h1>The Old Dog and Duck: Documentation</h1> <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> <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> <li><a href="cloverage/index.html">Test coverage</a></li>
</ul> </ul>
</body> </body>
</html> </html>

View file

@ -6,8 +6,7 @@
:doc/format :markdown} :doc/format :markdown}
:output-path "docs/codox" :output-path "docs/codox"
:source-uri "https://github.com/simon-brooke/dog-and-duck/blob/master/{filepath}#L{line}"} :source-uri "https://github.com/simon-brooke/dog-and-duck/blob/master/{filepath}#L{line}"}
:description "A playground for hacking ActivityPub stuff."
:description "A Clojure library designed to implement the ActivityPub protocol."
:dependencies [[org.clojure/clojure "1.11.1"] :dependencies [[org.clojure/clojure "1.11.1"]
[org.clojure/data.json "2.4.0"] [org.clojure/data.json "2.4.0"]
[org.clojure/math.numeric-tower "0.0.5"] [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 (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 [clojure.spec.alpha as s])
(:require [dog-and-duck.quack.picky :refer [filter-severity has-context?
object-faults]])
(:import [java.net URI URISyntaxException])) (:import [java.net URI URISyntaxException]))
;;; Copyright (C) Simon Brooke, 2022 ;;; Copyright (C) Simon Brooke, 2022
@ -30,9 +45,18 @@
But we are *just not having that*, because otherwise we're flying blind. 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 We *shall* reject objects lacking at least `:type`. Missing `:id` keys are
tolerable because they represent transient objects, which we expect to tolerable because they represent transient objects, which we expect to
handle." handle.
[x]
**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)) (and (map? x) (:type x) true))
([x severity]
(empty? (filter-severity (object-faults x) severity))))
(defn persistent-object? (defn persistent-object?
"`true` iff `x` is a persistent object. "`true` iff `x` is a persistent object.
@ -44,7 +68,7 @@
(and (object? x) (uri? (URI. (:id x)))) (and (object? x) (uri? (URI. (:id x))))
(catch URISyntaxException _ false))) (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 (def ^:const actor-types
"The set of types we will accept as actors. "The set of types we will accept as actors.
@ -57,10 +81,12 @@
"Person" "Person"
"Service"}) "Service"})
(defn actor-type? (defmacro actor-type?
;; TODO: better as a macro "Return `true` iff the `x` is a recognised actor type, else `false`."
[x] [^String x]
(if (actor-types x) true false)) `(if (actor-types ~x) true false))
;; (actor-type? "Group")
(def ^:const verb-types (def ^:const verb-types
"The set of types we will accept as verbs. "The set of types we will accept as verbs.
@ -72,47 +98,14 @@
"Offer" "Question" "Reject" "Read" "Remove" "TentativeAccept" "Offer" "Question" "Reject" "Read" "Remove" "TentativeAccept"
"TentativeReject" "Travel" "Undo" "Update" "View"}) "TentativeReject" "Travel" "Undo" "Update" "View"})
(defn verb-type? (defmacro verb-type?
;; TODO: better as a macro ;; TODO: better as a macro
[x] [^String x]
(if (verb-types x) true false)) `(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? (defn actor?
"Returns `true` if `x` quacks like an actor, else false." "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.
**NOTE THAT** [Section 4.1 of the spec] **NOTE THAT** [Section 4.1 of the spec]
(https://www.w3.org/TR/activitypub/#actor-objects) says explicitly that (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" However, none of the provided examples in the [activitystreams-test-documents repository]() does in fact have these properties"
[x] [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 (try
(and (object? x) (and (object? x)
(has-context? x) (has-context? x)
(string? (:summary x)) (string? (:summary x))
(actor? (:actor x)) (actor-or-uri? (:actor x))
(verb-type? (:type x)) (verb-type? (:type x))
(or (object? (:object x)) (uri? (URI. (:object x)))) (or (object? (:object x)) (uri? (URI. (:object x))))
true) true)
@ -156,35 +173,46 @@
true)) true))
(defn collection? (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, With one argument, will recognise plain collections and ordered collections,
but (currently) not collection pages." but (currently) not collection pages."
([x type] ([x ^String object-type]
(let [items (or (:items x) (:orderedItems x))] (let [items (or (:items x) (:orderedItems x))]
(and (and
(cond (cond
(:items x) (nil? (:orderedItems x)) (: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) (object? x)
(= (:type x) type) (= (:type x) object-type)
(coll? items) (if items
(every? object? 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)) (integer? (:totalItems x))
true))) true)))
([x]
(or (collection? x "Collection")
(collection? x "OrderedCollection"))))
(defn unordered-collection? (defn unordered-collection?
"`true` iff `x` quacks like an unordered collection, else `false`." "`true` iff `x` quacks like an unordered collection, else `false`."
[x] [x]
(collection? x "Collection")) (and (collection? x "Collection") (integer? (:totalItems x)) true))
(defn ordered-collection? (defn ordered-collection?
"`true` iff `x` quacks like an ordered collection, else `false`." "`true` iff `x` quacks like an ordered collection, else `false`."
[x] [x]
(collection? x "OrderedCollection")) (and (collection? x "OrderedCollection") (integer? (:totalItems x)) true))
(defn collection-page? (defn collection-page?
"`true` iff `x` quacks like a page in a paged collection, else `false`." "`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])))))) (apply webfinger/fetch-user-id (map handle [:domain :username]))))))
;;; examine what you got back! ;;; examine what you got back!
(:outbox account) (:inbox account)
(def rsa (pgp-gen/rsa-keypair-generator 2048)) (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 (ns dog-and-duck.quack.quack-test
(:require [clojure.test :refer [deftest is testing]] (:require [clojure.test :refer [deftest is testing]]
[dog-and-duck.quack.quack :refer [activitystreams-context-uri [dog-and-duck.quack.picky :refer [activitystreams-context-uri
actor? actor-type? context? context?]]
object? persistent-object? [dog-and-duck.quack.quack :refer [actor? actor-type?
object? ordered-collection-page?
persistent-object?
verb-type?]] verb-type?]]
[dog-and-duck.scratch.parser :refer [clean]])) [dog-and-duck.scratch.parser :refer [clean]]))
@ -127,3 +129,13 @@
actual (actor? (-> "resources/activitystreams-test-documents/simple0020.json" slurp clean first :actor))] actual (actor? (-> "resources/activitystreams-test-documents/simple0020.json" slurp clean first :actor))]
(is (= actual expected) "A Person is an 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."))
))