diff --git a/doc/Desiderata.md b/doc/Desiderata.md new file mode 100644 index 0000000..0ade9a5 --- /dev/null +++ b/doc/Desiderata.md @@ -0,0 +1,7 @@ +# Desiderata + +*Social media features which users want which [Mastodon](https://en.wikipedia.org/wiki/Mastodon_(social_network)) does not provide, or provides poorly.* + +1. User-specified inbox-ordering algorithms; +2. Outbox search, by user (i.e. 'find all the times I interacted with x'); +3. Outbox search, full text (i.e. 'find the post where I wrote x'); diff --git a/doc/Per-User Database b/doc/Per-User Database index e69de29..77f28e1 100644 --- a/doc/Per-User Database +++ b/doc/Per-User Database @@ -0,0 +1,5 @@ +# Per-User Database + +*This is a design thought, not a design decision.* + +Obviously, the way to give each user control of their social media is for each user to have effectively their own server, and that thought is behind my ideas about driving more functionality down to the client. Allowing an architecture of intermittent links helps with this - the same client will not always appear on the same ip address and thus cannot use conventional SSL certificates for authentication, so we need a workaround for that. diff --git a/doc/Using_ActivityPub.md b/doc/Using_ActivityPub.md index eb83c18..954b752 100644 --- a/doc/Using_ActivityPub.md +++ b/doc/Using_ActivityPub.md @@ -52,4 +52,3 @@ The Tombstone object is a means of acknowledging that the requested object did o If we're pushing entire objects – which may include media attachments – to the inboxes of many recipients who may never choose to read them, that feels like a lot of wasted bandwidth. However, if we're pushing only ids or links of posts which are not public, that feels like a major security headache in verifying that the requestors are indeed verified recipients. Again, the fact that Mastodon is able to show me '[user] edited a post' items in my notifications seems to imply that updates of the complete edited object are being pushed out to all recipients' inboxes, and again that seems expensive. - diff --git a/docs/codox/Desiderata.html b/docs/codox/Desiderata.html new file mode 100644 index 0000000..90dbbe1 --- /dev/null +++ b/docs/codox/Desiderata.html @@ -0,0 +1,9 @@ + +Desiderata

Desiderata

+

Social media features which users want which [Mastodon](https://en.wikipedia.org/wiki/Mastodon_(social_network)) does not provide, or provides poorly.

+
    +
  1. User-specified inbox-ordering algorithms;
  2. +
  3. Outbox search, by user (i.e. ‘find all the times I interacted with x’);
  4. +
  5. Outbox search, full text (i.e. ‘find the post where I wrote x’);
  6. +
\ No newline at end of file diff --git a/docs/codox/Using_ActivityPub.html b/docs/codox/Using_ActivityPub.html index ea14e0d..5cc36d6 100644 --- a/docs/codox/Using_ActivityPub.html +++ b/docs/codox/Using_ActivityPub.html @@ -1,6 +1,6 @@ -Using ActivityPub

Using ActivityPub

+Using ActivityPub

Using ActivityPub

Introduction

I do not know what I am doing; I am learning, and playing. Nothing in this document should be treated as good advice; it simply relates to the current state of my knowledge.

What happens when you post a new item to an ActivityPub server

diff --git a/docs/codox/Validation_Faults.html b/docs/codox/Validation_Faults.html index 712e88d..6fe1b95 100644 --- a/docs/codox/Validation_Faults.html +++ b/docs/codox/Validation_Faults.html @@ -1,6 +1,6 @@ -Validation Faults in ActivityPub documents

Validation Faults in ActivityPub documents

+Validation Faults in ActivityPub documents

Validation Faults in ActivityPub documents

Motivation

This document is intended to provide an extension vocabulary for ActivityStreams documents, which provides vocabulary for categorising and describing faults in ActivityPub documents.

The motivation is to be able to serialise a validation report on an ActivityPub document as an ActivityStreams document.

diff --git a/docs/codox/dog-and-duck.quack.picky.constants.html b/docs/codox/dog-and-duck.quack.picky.constants.html new file mode 100644 index 0000000..330d1fc --- /dev/null +++ b/docs/codox/dog-and-duck.quack.picky.constants.html @@ -0,0 +1,12 @@ + +dog-and-duck.quack.picky.constants documentation

dog-and-duck.quack.picky.constants

Constants supporting the picky validator.

activitystreams-context-uri

The URI of the context of an ActivityStreams object is expected to be this literal string.

actor-types

The set of types we will accept as actors.

+

There’s an explicit set of allowed actor types.

context-key

The Clojure reader barfs on :@context, although it is in principle a valid keyword. So we’ll make it once, here, to make the code more performant and easier to read.

severity

Severity of faults found, as follows:

+
    +
  1. :info not actually a fault, but an issue noted during validation;
  2. +
  3. :minor things which I consider to be faults, but which don’t actually breach the spec;
  4. +
  5. :should instances where the spec says something SHOULD be done, which isn’t;
  6. +
  7. :must instances where the spec says something MUST be done, which isn’t;
  8. +
  9. :critical instances where I believe the fault means that the object cannot be meaningfully processed.
  10. +

severity-filters

Hack for implementing a severity hierarchy

validation-fault-context-uri

The URI of the context of a validation fault report object shall be this literal string.

verb-types

The set of types we will accept as verbs.

+

There’s an explicit set of allowed verb types.

\ No newline at end of file diff --git a/docs/codox/dog-and-duck.quack.picky.control-variables.html b/docs/codox/dog-and-duck.quack.picky.control-variables.html new file mode 100644 index 0000000..9e4a6d2 --- /dev/null +++ b/docs/codox/dog-and-duck.quack.picky.control-variables.html @@ -0,0 +1,12 @@ + +dog-and-duck.quack.picky.control-variables documentation

dog-and-duck.quack.picky.control-variables

Control variables for the picky validator.

*reify-refs*

dynamic

If true, references to objects in fields will be reified and validated. If false, they won’t, but an :info level fault report will be generated.

+

There are several things in the spec which, in a document, may correctly be either

+
    +
  1. a fully fleshed out object, or
  2. +
  3. a URI pointing to such an object.
  4. +
+

Obviously to fully validate a document we ought to reify all the refs and check that they are themselves valid, but

+

a. in some of the published test documents the URIs do not reference a valid document; b. there will be performance costs to reifying all the refs; c. in perverse cases, reifying refs might result in runaway recursion.

+

TODO: I think that in production this should default to true.

*reject-severity*

dynamic

The severity at which the binary validator will return false.

+

In practice documents seen in the wild do not typically appear to be fully valid, and this does not matter. This allows the sensitivity of the binary validator (dog-and-duck.quack.quack) to be tuned. It’s in this (dog-and-duck.quack.picky) namespace, not that one, because this namespace is where concerns about severity are handled.

\ No newline at end of file diff --git a/docs/codox/dog-and-duck.quack.picky.fault-messages.html b/docs/codox/dog-and-duck.quack.picky.fault-messages.html new file mode 100644 index 0000000..22afc52 --- /dev/null +++ b/docs/codox/dog-and-duck.quack.picky.fault-messages.html @@ -0,0 +1,3 @@ + +dog-and-duck.quack.picky.fault-messages documentation

dog-and-duck.quack.picky.fault-messages

Narrative values for fault reports of specific types, used by the picky validator.

messages

Actual fault messages to which fault codes resolve.

\ No newline at end of file diff --git a/docs/codox/dog-and-duck.quack.picky.html b/docs/codox/dog-and-duck.quack.picky.html index c98eff0..09714fa 100644 --- a/docs/codox/dog-and-duck.quack.picky.html +++ b/docs/codox/dog-and-duck.quack.picky.html @@ -1,6 +1,6 @@ -dog-and-duck.quack.picky documentation

dog-and-duck.quack.picky

Fault-finder for ActivityPub documents.

+dog-and-duck.quack.picky documentation

dog-and-duck.quack.picky

Fault-finder for ActivityPub documents.

Generally, each -faults function will return:

  1. nil if no faults were found;
  2. @@ -15,25 +15,11 @@
  3. :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.

*reify-refs*

dynamic

If true, references to objects in fields will be reified and validated. If false, they won’t, but an :info level fault report will be generated.

-

There are several things in the spec which, in a document, may correctly be either

-
    -
  1. a fully fleshed out object, or
  2. -
  3. a URI pointing to such an object.
  4. -
-

Obviously to fully validate a document we ought to reify all the refs and check that they are themselves valid, but

-

a. in some of the published test documents the URIs do not reference a valid document; b. there will be performance costs to reifying all the refs; c. in perverse cases, reifying refs might result in runaway recursion.

-

TODO: I think that in production this should default to true.

*reject-severity*

dynamic

The severity at which the binary validator will return false.

-

In practice documents seen in the wild do not typically appear to be fully valid, and this does not matter. This allows the sensitivity of the binary validator (dog-and-duck.quack.quack) to be tuned. It’s in this (dog-and-duck.quack.picky) namespace, not that one, because this namespace is where concerns about severity are handled.

accept-required-properties

As base-activity-required-properties, except that the type of the object is restricted.

activity-faults

(activity-faults x)

TODO: write docs

activity-required-properties

Properties activities should have, keyed by activity type. Values are maps of the format of base-activity-required-properties, q.v.

activity-type-faults

(activity-type-faults x)(activity-type-faults x type)

Return a list of faults found in the activity x; if type is also specified, it should be a string naming a specific activity type for which checks should be performed.

-

Some specific activity types have specific requirements which are not requirements.

activitystreams-context-uri

The URI of the context of an ActivityStreams object is expected to be this literal string.

actor-faults

(actor-faults x)

Return a list of faults found in actor x, or nil if none are.

actor-type?

(actor-type? x)

Return true if the x is a recognised actor type, else false.

actor-types

The set of types we will accept as actors.

-

There’s an explicit set of allowed actor types.

base-activity-required-properties

Properties most activities should have. Values are validating functions, each.

-

See https://www.w3.org/TR/activitystreams-vocabulary/#dfn-activity

coll-object-reference-or-fault

(coll-object-reference-or-fault value expected-type severity token)

As object-reference-or-fault, except value argument may also be a list of objects and/or object references.

context-key

The Clojure reader barfs on :@context, although it is in principle a valid keyword. So we’ll make it once, here, to make the code more performant and easier to read.

context?

(context? x)

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.

filter-severity

(filter-severity reports severity)

Return a list of reports taken from these reports where the severity of the report is greater than this or equal to this severity.

has-activity-type?

(has-activity-type? x)

Return true if the object x has a type which is an activity type, else false.

has-actor-type?

(has-actor-type? x)

Return true if the object x has a type which is an actor type, else false.

has-context?

macro

(has-context? x)

True if x is an ActivityStreams object with a valid context, else false.

has-type-or-fault

(has-type-or-fault x acceptable severity token)

If object x has a :type value which is acceptable, return nil; else return a fault object with this severity and token.

-

acceptable may be passed as either nil, a string, or a set of strings. If acceptable is nil, no type specific tests will be performed.

has-type?

(has-type? x type)

Return true if object x has type type, else false.

-

The values of type fields of ActivityStreams objects may be lists; they are considered to have a type if the type token is a member of the list.

intransitive-activity-required-properties

Properties intransitive activities should have.

-

See https://www.w3.org/TR/activitystreams-vocabulary/#dfn-intransitiveactivity

make-fault-object

(make-fault-object severity fault)

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.

nil-if-empty

macro

(nil-if-empty x)

if x is an empty collection, return nil; else return x.

object-faults

(object-faults x)(object-faults x expected-type)

Return a list of faults found in object x, or nil if none are.

-

If expected-type is also passed, verify that x has expected-type. expected-type may be passed as a string or as a set of strings.

object-reference-or-faults

(object-reference-or-faults value expected-type severity token)

If this value is either

+

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.

accept-required-properties

As base-activity-required-properties, except that the type of the object is restricted.

activity-faults

(activity-faults x)

TODO: write docs

activity-required-properties

Properties activities should have, keyed by activity type. Values are maps of the format of base-activity-required-properties, q.v.

activity-type-faults

(activity-type-faults x)(activity-type-faults x type)

Return a list of faults found in the activity x; if type is also specified, it should be a string naming a specific activity type for which checks should be performed.

+

Some specific activity types have specific requirements which are not requirements.

actor-faults

(actor-faults x)

Return a list of faults found in actor x, or nil if none are.

base-activity-required-properties

Properties most activities should have. Values are validating functions, each.

+

See https://www.w3.org/TR/activitystreams-vocabulary/#dfn-activity

coll-object-reference-or-fault

(coll-object-reference-or-fault value expected-type severity token)

As object-reference-or-fault, except value argument may also be a list of objects and/or object references.

intransitive-activity-required-properties

Properties intransitive activities should have.

+

See https://www.w3.org/TR/activitystreams-vocabulary/#dfn-intransitiveactivity

object-faults

(object-faults x)(object-faults x expected-type)

Return a list of faults found in object x, or nil if none are.

+

If expected-type is also passed, verify that x has expected-type. expected-type may be passed as a string or as a set of strings.

object-reference-or-faults

(object-reference-or-faults value expected-type severity token)

If this value is either

  1. an object of expected-type;
  2. a URI referencing an object of expected-type; or
  3. @@ -41,12 +27,4 @@

and no faults are returned from validating the linked object, then return nil; else return a sequence comprising a fault object with this severity and token, prepended to the faults returned.

As with has-type-or-fault (q.v.), expected-type may be passed as a string or as a set of strings.

-

NOTE THAT if *reify-refs* is false, referenced objects will not actually be checked.

persistent-object-faults

(persistent-object-faults x)

Return a list of faults found in persistent object x, or nil if none are.

severity

Severity of faults found, as follows:

-
    -
  1. :info not actually a fault, but an issue noted during validation;
  2. -
  3. :minor things which I consider to be faults, but which don’t actually breach the spec;
  4. -
  5. :should instances where the spec says something SHOULD be done, which isn’t;
  6. -
  7. :must instances where the spec says something MUST be done, which isn’t;
  8. -
  9. :critical instances where I believe the fault means that the object cannot be meaningfully processed.
  10. -

severity-filters

Hack for implementing a severity hierarchy

string-or-fault

(string-or-fault value severity token)(string-or-fault value severity token pattern)

If this value is not a string, return a fault object with this severity and token, else nil. If pattern is also passed, it is expected to be a Regex, and the fault object will be returned unless value matches the pattern.

truthy?

(truthy? x)

Return true if x is truthy, else false.

uri-or-fault

(uri-or-fault u severity if-missing-token)(uri-or-fault u severity if-missing-token if-invalid-token)

If u is not a valid URI, return a fault object with this severity and if-invalid-token. If it’s nil, return a fault object with this severity and if-missing-token. Otherwise return nil.

validation-fault-context-uri

The URI of the context of a validation fault report object shall be this literal string.

verb-type?

(verb-type? x)

true if x, a string, represents a recognised ActivityStreams activity type.

verb-types

The set of types we will accept as verbs.

-

There’s an explicit set of allowed verb types.

\ No newline at end of file +

NOTE THAT if *reify-refs* is false, referenced objects will not actually be checked.

persistent-object-faults

(persistent-object-faults x)(persistent-object-faults x types severity token)

Return a list of faults found in persistent object x, or nil if none are.

string-or-fault

(string-or-fault value severity token)(string-or-fault value severity token pattern)

If this value is not a string, return a fault object with this severity and token, else nil. If pattern is also passed, it is expected to be a Regex, and the fault object will be returned unless value matches the pattern.

uri-or-fault

(uri-or-fault u severity if-missing-token)(uri-or-fault u severity if-missing-token if-invalid-token)

If u is not a valid URI, return a fault object with this severity and if-invalid-token. If it’s nil, return a fault object with this severity and if-missing-token. Otherwise return nil.

\ No newline at end of file diff --git a/docs/codox/dog-and-duck.quack.picky.required-properties.html b/docs/codox/dog-and-duck.quack.picky.required-properties.html new file mode 100644 index 0000000..1e49c08 --- /dev/null +++ b/docs/codox/dog-and-duck.quack.picky.required-properties.html @@ -0,0 +1,3 @@ + +dog-and-duck.quack.picky.required-properties documentation

dog-and-duck.quack.picky.required-properties

TODO: write docs

\ No newline at end of file diff --git a/docs/codox/dog-and-duck.quack.picky.utils.html b/docs/codox/dog-and-duck.quack.picky.utils.html new file mode 100644 index 0000000..850f283 --- /dev/null +++ b/docs/codox/dog-and-duck.quack.picky.utils.html @@ -0,0 +1,7 @@ + +dog-and-duck.quack.picky.utils documentation

dog-and-duck.quack.picky.utils

Utility functions supporting the picky validator

actor-type?

(actor-type? x)

Return true if the x is a recognised actor type, else false.

concat-non-empty

(concat-non-empty & lists)

Quick function to replace the pattern (nil-if-empty (remove nil? (concat …))) which I’m using a lot!

context?

(context? x)

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.

filter-severity

(filter-severity reports severity)

Return a list of reports taken from these reports where the severity of the report is greater than this or equal to this severity.

has-activity-type?

(has-activity-type? x)

Return true if the object x has a type which is an activity type, else false.

has-actor-type?

(has-actor-type? x)

Return true if the object x has a type which is an actor type, else false.

has-context?

macro

(has-context? x)

True if x is an ActivityStreams object with a valid context, else false.

has-type-or-fault

(has-type-or-fault x acceptable severity token)

If object x has a :type value which is acceptable, return nil; else return a fault object with this severity and token.

+

acceptable may be passed as either nil, a string, or a set of strings. If acceptable is nil, no type specific tests will be performed.

has-type?

(has-type? x type)

Return true if object x has type type, else false.

+

The values of type fields of ActivityStreams objects may be lists; they are considered to have a type if the type token is a member of the list.

make-fault-object

(make-fault-object severity fault)

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.

nil-if-empty

macro

(nil-if-empty x)

if x is an empty collection, return nil; else return x.

truthy?

(truthy? x)

Return true if x is truthy, else false.

verb-type?

(verb-type? x)

true if x, a string, represents a recognised ActivityStreams activity type.

\ No newline at end of file diff --git a/docs/codox/dog-and-duck.quack.quack.html b/docs/codox/dog-and-duck.quack.quack.html index 108053c..8a21142 100644 --- a/docs/codox/dog-and-duck.quack.quack.html +++ b/docs/codox/dog-and-duck.quack.quack.html @@ -1,14 +1,14 @@ -dog-and-duck.quack.quack documentation

dog-and-duck.quack.quack

Validator for ActivityPub objects: if it walks like a duck, and it quacks like a duck…

+dog-and-duck.quack.quack documentation

dog-and-duck.quack.quack

Validator for ActivityPub objects: if it walks like a duck, and it quacks like a duck…

**NOTE THAT the ActivityPub spec says

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.

activity?

(activity? x)(activity? x severity)

true iff x quacks like an activity, else false.

actor-or-uri?

(actor-or-uri? x)

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.

actor?

(actor? x)(actor? x severity)

Returns true if x quacks like an actor, else false.

collection-page?

(collection-page? x)

true iff x quacks like a page in a paged collection, else false.

collection?

(collection? x object-type)(collection? x)

true iff x quacks like a collection of type object-type, else false.

-

With one argument, will recognise plain collections and ordered collections, but (currently) not collection pages.

link?

(link? x)(link? x severity)

true iff x quacks like a link, else false.

object?

(object? x)(object? x severity)

Returns true iff x is recognisably an ActivityStreams object.

+

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.

activity?

(activity? x)(activity? x severity)

true iff x quacks like an activity, else false.

actor-or-uri?

(actor-or-uri? x)

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.

actor?

(actor? x)(actor? x severity)

Returns true if x quacks like an actor, else false.

collection-page?

(collection-page? x)

true iff x quacks like a page in a paged collection, else false.

collection?

(collection? x object-type)(collection? x)

true iff x quacks like a collection of type object-type, else false.

+

With one argument, will recognise plain collections and ordered collections, but (currently) not collection pages.

link?

(link? x)(link? x severity)

true iff x quacks like a link, else false.

object?

(object? x)(object? x severity)

Returns true iff x is recognisably an ActivityStreams object.

NOTE THAT The ActivityStreams spec says:

All properties are optional (including the id and type)

@@ -18,5 +18,5 @@

Implementers SHOULD include the ActivityPub context in their object definitions

-

but in samples found in the wild they typically don’t.

ordered-collection-page?

(ordered-collection-page? x)

true iff x quacks like a page in an ordered paged collection, else false.

ordered-collection?

(ordered-collection? x)

true iff x quacks like an ordered collection, else false.

persistent-object?

(persistent-object? x)(persistent-object? x severity)

true iff x is a persistent object.

-

Transient objects in ActivityPub are not required to have an id key, but persistent ones must have a key, and it must be an IRI (but normally a URI).

unordered-collection?

(unordered-collection? x)

true iff x quacks like an unordered collection, else false.

\ No newline at end of file +

but in samples found in the wild they typically don’t.

ordered-collection-page?

(ordered-collection-page? x)

true iff x quacks like a page in an ordered paged collection, else false.

ordered-collection?

(ordered-collection? x)

true iff x quacks like an ordered collection, else false.

persistent-object?

(persistent-object? x)(persistent-object? x severity)

true iff x is a persistent object.

+

Transient objects in ActivityPub are not required to have an id key, but persistent ones must have a key, and it must be an IRI (but normally a URI).

unordered-collection?

(unordered-collection? x)

true iff x quacks like an unordered collection, else false.

\ No newline at end of file diff --git a/docs/codox/dog-and-duck.scratch.core.html b/docs/codox/dog-and-duck.scratch.core.html index 1a895c3..a2efd05 100644 --- a/docs/codox/dog-and-duck.scratch.core.html +++ b/docs/codox/dog-and-duck.scratch.core.html @@ -1,3 +1,3 @@ -dog-and-duck.scratch.core documentation

dog-and-duck.scratch.core

TODO: write docs

foo

(foo x)

I don’t do a whole lot.

\ No newline at end of file +dog-and-duck.scratch.core documentation

dog-and-duck.scratch.core

TODO: write docs

foo

(foo x)

I don’t do a whole lot.

\ No newline at end of file diff --git a/docs/codox/dog-and-duck.scratch.parser.html b/docs/codox/dog-and-duck.scratch.parser.html index f5e260d..45adf0f 100644 --- a/docs/codox/dog-and-duck.scratch.parser.html +++ b/docs/codox/dog-and-duck.scratch.parser.html @@ -1,3 +1,3 @@ -dog-and-duck.scratch.parser documentation

dog-and-duck.scratch.parser

TODO: write docs

clean

(clean json)

Take this json input, and return a sequence of ActivityPub objects represented by it.

\ No newline at end of file +dog-and-duck.scratch.parser documentation

dog-and-duck.scratch.parser

TODO: write docs

clean

(clean json)

Take this json input, and return a sequence of ActivityPub objects represented by it.

\ No newline at end of file diff --git a/docs/codox/dog-and-duck.scratch.scratch.html b/docs/codox/dog-and-duck.scratch.scratch.html index c0eae90..4f6f75d 100644 --- a/docs/codox/dog-and-duck.scratch.scratch.html +++ b/docs/codox/dog-and-duck.scratch.scratch.html @@ -1,3 +1,3 @@ -dog-and-duck.scratch.scratch documentation

dog-and-duck.scratch.scratch

Scratchpad where I try to understand how to do this stuff.

account

Fetch my account to mess with

account-handle

TODO: write docs

handle

TODO: write docs

\ No newline at end of file +dog-and-duck.scratch.scratch documentation

dog-and-duck.scratch.scratch

Scratchpad where I try to understand how to do this stuff.

account-handle

TODO: write docs

\ No newline at end of file diff --git a/docs/codox/dog-and-duck.utils.process.html b/docs/codox/dog-and-duck.utils.process.html index 4390b03..c8b747f 100644 --- a/docs/codox/dog-and-duck.utils.process.html +++ b/docs/codox/dog-and-duck.utils.process.html @@ -1,5 +1,5 @@ -dog-and-duck.utils.process documentation

dog-and-duck.utils.process

TODO: write docs

get-hostname

return the hostname of the current host.

+dog-and-duck.utils.process documentation

dog-and-duck.utils.process

TODO: write docs

get-hostname

return the hostname of the current host.

Java’s methods for getting the hostname are quite startlingly slow, we do not want todo this repeatedly!

get-pid

Get the process id of the current process.

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.

\ No newline at end of file diff --git a/docs/codox/index.html b/docs/codox/index.html index 0aa65a0..4b802af 100644 --- a/docs/codox/index.html +++ b/docs/codox/index.html @@ -1,3 +1,3 @@ -Dog-and-duck 0.1.0-SNAPSHOT

Dog-and-duck 0.1.0-SNAPSHOT

Released under the GPL-2.0-or-later

A playground for hacking ActivityPub stuff.

Installation

To install, add the following dependency to your project or build file:

[dog-and-duck "0.1.0-SNAPSHOT"]

Topics

Namespaces

clj-activitypub.core

copied from Jahfer’s clj-activitypub library. If and when Jahfer issues a release of that library, this directory will be deleted and a dependency on that library will be added to the project.

clj-activitypub.internal.crypto

copied from Jahfer’s clj-activitypub library. If and when Jahfer issues a release of that library, this directory will be deleted and a dependency on that library will be added to the project.

Public variables and functions:

clj-activitypub.internal.http-util

copied from Jahfer’s clj-activitypub library. If and when Jahfer issues a release of that library, this directory will be deleted and a dependency on that library will be added to the project.

Public variables and functions:

clj-activitypub.internal.thread-cache

copied from Jahfer’s clj-activitypub library. If and when Jahfer issues a release of that library, this directory will be deleted and a dependency on that library will be added to the project.

Public variables and functions:

clj-activitypub.webfinger

copied from Jahfer’s clj-activitypub library. If and when Jahfer issues a release of that library, this directory will be deleted and a dependency on that library will be added to the project.

Public variables and functions:

dog-and-duck.quack.fault-messages

TODO: write docs

Public variables and functions:

dog-and-duck.quack.quack

Validator for ActivityPub objects: if it walks like a duck, and it quacks like a duck…

dog-and-duck.scratch.core

TODO: write docs

Public variables and functions:

dog-and-duck.scratch.parser

TODO: write docs

Public variables and functions:

dog-and-duck.scratch.scratch

Scratchpad where I try to understand how to do this stuff.

Public variables and functions:

dog-and-duck.utils.process

TODO: write docs

Public variables and functions:

\ No newline at end of file +Dog-and-duck 0.1.0-SNAPSHOT

Dog-and-duck 0.1.0-SNAPSHOT

Released under the GPL-2.0-or-later

A playground for hacking ActivityPub stuff.

Installation

To install, add the following dependency to your project or build file:

[dog-and-duck "0.1.0-SNAPSHOT"]

Topics

Namespaces

dog-and-duck.quack.picky.control-variables

Control variables for the picky validator.

Public variables and functions:

dog-and-duck.quack.picky.fault-messages

Narrative values for fault reports of specific types, used by the picky validator.

Public variables and functions:

dog-and-duck.quack.picky.required-properties

TODO: write docs

Public variables and functions:

    dog-and-duck.quack.quack

    Validator for ActivityPub objects: if it walks like a duck, and it quacks like a duck…

    dog-and-duck.scratch.core

    TODO: write docs

    Public variables and functions:

    dog-and-duck.scratch.parser

    TODO: write docs

    Public variables and functions:

    dog-and-duck.scratch.scratch

    Scratchpad where I try to understand how to do this stuff.

    Public variables and functions:

    dog-and-duck.utils.process

    TODO: write docs

    Public variables and functions:

    \ No newline at end of file diff --git a/docs/codox/intro.html b/docs/codox/intro.html index 7abe3b9..36e87f4 100644 --- a/docs/codox/intro.html +++ b/docs/codox/intro.html @@ -1,6 +1,6 @@ -Introduction

    Introduction

    +Introduction

    Introduction

    The Old Dog and Duck

    A Clojure library designed to implement the ActivityPub protocol, obviously.

    The Dog and Duck, Derby

    @@ -19,8 +19,24 @@
  • Delivering ActivityStreams objects to peers;
  • Delivering ActivityStreams objects to clients.
  • -

    NOTE THAT what Mastodon delivers to clients is not actually in ActivityStreams format; this seems to be an ad-hoc hack that’s just never been fixed and has therefore become a de-facto standard for communication between ActivityPub hosts and their clients.

    +

    Some motivations

    +

    Empowering users

    +

    The ActivityPub spec starts by saying:

    +
    +

    ActivityPub provides two layers:

    +
      +
    1. A server to server federation protocol (so decentralized websites can share information)
    2. +
    3. A client to server protocol (so users, including real-world users, bots, and other automated processes, can communicate with ActivityPub using their accounts on servers, from a phone or desktop or web application or whatever).
    4. +
    +
    +

    I’m interested in driving much more functionality down to the the client, for example feed ordering and presentation. This would allow users, for example, to choose their own (or roll their own) feed-ordering algorithms.

    My proposal would be to deliver exactly the same ActivityStreams format to my client as to other servers. There may be a valid reason for not doing this, but if there is I will discover it in due course.

    +

    Enhanced resiliency

    +

    The ActivityStreams spec seems predicated on ‘always up’ communication between at least servers, which is perhaps why there is a two tier network of ‘servers’ and ‘clients’. It also depends on HTTPS certificates to identify servers, which implies it’s vulnerable to disruption by a hostile actor with the ability to revoke certificates.

    +

    My own history with social media dates back to Usenet over UUCP, a system designed explicitly for intermittent low bandwidth connections; such a system is immensely resilient in the face of disruption to infrastructure.

    +

    Social media is useful to concerted popular action in periods of disruption, whether in the case of civil ememrgency such as earthquakes, wild fires and floods, in the case of wars, or in the case of intrusive surveillance by authoritarian governments. But to be useful in such situations it needs to be resilient, and one of the things it needs to be resilient to is parts of the network being intermittently available, or requiring rerouting.

    +

    In this I’m influenced by and hope to try to implement ideas from Ian Clarke’s Freenet and Tahrir projects, especially webs of trust.

    +

    To be clear, it is important for The Old Dog and Duck to be able to interact with other existing ‘vanilla’ ActivityStreams implementations, but I hope to experiment with enhanced communication between Dog and Duck servers to provide more FreeNet-like resiliency.

    Proposed dog-and-duck libraries

    NOTE THAT at the present stage all the proposed libraries are in one package, namely this package, but that it is proposed that in future they will form separate libraries in separate packages.

    Bar

    diff --git a/project.clj b/project.clj index b0ba436..523d98e 100644 --- a/project.clj +++ b/project.clj @@ -7,15 +7,14 @@ :output-path "docs/codox" :source-uri "https://github.com/simon-brooke/dog-and-duck/blob/master/{filepath}#L{line}"} :description "A playground for hacking ActivityPub stuff." - :dependencies [[org.clojure/clojure "1.11.1"] + :dependencies [[clj-activitypub/activitypub "0.49"] + [com.taoensso/timbre "6.0.4"] + [mvxcvi/clj-pgp "1.1.0"] + [org.bouncycastle/bcpkix-jdk18on "1.72"] + [org.clojure/clojure "1.11.1"] [org.clojure/data.json "2.4.0"] [org.clojure/math.numeric-tower "0.0.5"] - [org.clojure/spec.alpha "0.3.218"] - [mvxcvi/clj-pgp "1.1.0"] - [org.bouncycastle/bcpkix-jdk18on "1.72"] ;; required by clj-activitypub - [clj-http "3.12.3"] ;; required by clj-activitypub - [cheshire "5.11.0"] ;; if this is not present, clj-http/client errors with 'json-enabled?' - [com.taoensso/timbre "6.0.4"]] + [org.clojure/spec.alpha "0.3.218"]] :license {:name "GPL-2.0-or-later" :url "https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html"} :plugins [[lein-cloverage "1.2.2"] diff --git a/src/dog_and_duck/activitypub.code-workspace b/src/dog_and_duck/activitypub.code-workspace new file mode 100644 index 0000000..b1e3e48 --- /dev/null +++ b/src/dog_and_duck/activitypub.code-workspace @@ -0,0 +1,11 @@ +{ + "folders": [ + { + "path": "../.." + }, + { + "path": "../../../clj-activitypub" + } + ], + "settings": {} +} \ No newline at end of file diff --git a/src/dog_and_duck/quack/picky.clj b/src/dog_and_duck/quack/picky.clj index 54dbed2..113eb57 100644 --- a/src/dog_and_duck/quack/picky.clj +++ b/src/dog_and_duck/quack/picky.clj @@ -302,11 +302,12 @@ (defn activity-faults [x] - (concat-non-empty (persistent-object-faults x) - (activity-type-faults x) - (list - (when-not - (has-activity-type? x) - (make-fault-object :must :not-activity-type)) - (when-not (string? (:summary x)) (make-fault-object :should :no-summary))))) + (concat-non-empty + (persistent-object-faults x) + (activity-type-faults x) + (list + (when-not + (has-activity-type? x) + (make-fault-object :must :not-activity-type)) + (when-not (string? (:summary x)) (make-fault-object :should :no-summary))))) diff --git a/src/dog_and_duck/quack/picky/required_properties.clj b/src/dog_and_duck/quack/picky/required_properties.clj index e69de29..aeedcde 100644 --- a/src/dog_and_duck/quack/picky/required_properties.clj +++ b/src/dog_and_duck/quack/picky/required_properties.clj @@ -0,0 +1,2 @@ +(ns dog-and-duck.quack.picky.required-properties) + diff --git a/src/dog_and_duck/scratch/scratch.clj b/src/dog_and_duck/scratch/scratch.clj index 119533f..f1795ed 100644 --- a/src/dog_and_duck/scratch/scratch.clj +++ b/src/dog_and_duck/scratch/scratch.clj @@ -2,8 +2,11 @@ "Scratchpad where I try to understand how to do this stuff." (:require [clj-activitypub.core :as activitypub] [clj-activitypub.webfinger :as webfinger] + [clj-activitypub.net :as activitypub-net] [clj-pgp.generate :as pgp-gen] - [clojure.walk :refer [keywordize-keys]])) + [clojure.walk :refer [keywordize-keys]] + [clojure.pprint :refer [pprint]] + [clojure.data.json :as json])) ;;; Copyright (C) Simon Brooke, 2022 @@ -24,23 +27,29 @@ ;;; Use any ActivityPub account handle you like - for example, your own (def account-handle "@simon_brooke@mastodon.scot") -(def handle (activitypub/parse-account account-handle)) -(webfinger/fetch-user-id "mastodon.scot" "simon_brooke") -(apply webfinger/fetch-user-id (map handle [:domain :username])) +;;(def handle (activitypub/parse-account account-handle)) +;;(webfinger/fetch-user-id "mastodon.scot" "simon_brooke") +;;(apply webfinger/fetch-user-id (map handle [:domain :username])) ;;; Retrieve the account details from its home server ;;; (`keywordize-keys` is not necessary here but produces a more idiomatic clojure ;;; data structure) (def account - "Fetch my account to mess with" - (let [handle (activitypub/parse-account account-handle)] - (keywordize-keys - (activitypub/fetch-user - (apply webfinger/fetch-user-id (map handle [:domain :username])))))) + (-> account-handle + (webfinger/parse-handle) + (webfinger/fetch-user-id!) + (activitypub-net/fetch-user!) + (select-keys [:name :preferredUsername :inbox :summary]))) -;;; examine what you got back! +;; ;;; examine what you got back! (:inbox account) +(-> account + :inbox + slurp + json/read-str + pprint) ;; => 80 + ;; (def rsa (pgp-gen/rsa-keypair-generator 2048)) ;; (def kp (pgp-gen/generate-keypair rsa :rsa-general))