aboutsummaryrefslogtreecommitdiffstats
path: root/doc/en/developer
diff options
context:
space:
mode:
Diffstat (limited to 'doc/en/developer')
-rw-r--r--doc/en/developer/API.md787
-rw-r--r--doc/en/developer/Plugins.md259
-rw-r--r--doc/en/developer/api_zot.bb766
-rw-r--r--doc/en/developer/attribution.md3
-rw-r--r--doc/en/developer/code_of_conduct.md8
-rw-r--r--doc/en/developer/coding_style.md12
-rw-r--r--doc/en/developer/covenant.bb47
-rw-r--r--doc/en/developer/dev-function-overview.md49
-rw-r--r--doc/en/developer/dev_beginner.md548
-rw-r--r--doc/en/developer/developer_guide.bb176
-rw-r--r--doc/en/developer/developers_guide.md27
-rw-r--r--doc/en/developer/doco.md34
-rw-r--r--doc/en/developer/enforcement.md4
-rw-r--r--doc/en/developer/federate.md69
-rw-r--r--doc/en/developer/file_system_layout.md20
-rw-r--r--doc/en/developer/git_for_non_developers.md100
-rw-r--r--doc/en/developer/git_repository.md6
-rw-r--r--doc/en/developer/hooks.md458
-rw-r--r--doc/en/developer/licensing.md3
-rw-r--r--doc/en/developer/magic_auth.md49
-rw-r--r--doc/en/developer/nomad_protocol.md44
-rw-r--r--doc/en/developer/nomad_structures.md110
-rw-r--r--doc/en/developer/our_pledge.md3
-rw-r--r--doc/en/developer/our_responsibilities.md3
-rw-r--r--doc/en/developer/our_standards.md17
-rw-r--r--doc/en/developer/scope.md3
-rw-r--r--doc/en/developer/technical_introduction.md292
-rw-r--r--doc/en/developer/testing.md32
-rw-r--r--doc/en/developer/tools_workflows.md5
-rw-r--r--doc/en/developer/translations.md51
-rw-r--r--doc/en/developer/unorganized.md12
-rw-r--r--doc/en/developer/versions.md22
-rw-r--r--doc/en/developer/who_is_a_hubzilla_developer.md14
-rw-r--r--doc/en/developer/zot_protocol.bb478
-rw-r--r--doc/en/developer/zot_protocol.md44
-rw-r--r--doc/en/developer/zot_structures.md110
36 files changed, 3172 insertions, 1493 deletions
diff --git a/doc/en/developer/API.md b/doc/en/developer/API.md
new file mode 100644
index 000000000..abb25afb8
--- /dev/null
+++ b/doc/en/developer/API.md
@@ -0,0 +1,787 @@
+### Zot API
+
+Many existing social applications and tools can interface directly using the Twitter/StatusNet API, which is available using the 'twitter_api' addon.
+
+This document describes the native API; which allows direct programmatic access to several internal data structures and libraries extending beyond the basic social interface.
+
+The API endpoints detailed below are relative to `api/z/1.0`, meaning that if an API is listed as `channel/stream` the full API URL is `https://hub.hubzilla.hu/api/z/1.0/channel/stream`.
+
+
+
+### channel/export/basic
+
+Export basic channel data
+
+Options:
+ \- sections
+ comma-separated list of data types to export
+
+ \- posts
+ if true, return default sections plus 3 months of posts
+
+ If no sections are requested, the following sections are returned:
+ channel, connections, config, apps, chatrooms, events, webpages, mail, wikis
+
+ Files and large collections of posts may run into memory limits; these must generally be
+ requested separately.
+
+
+
+### channel/stream
+
+Fetch channel conversation items
+
+
+
+### network/stream
+
+Fetch network conversation items
+
+
+
+
+
+### files
+
+List file storage (attach DB)
+
+GET /api/z/1.0/files
+
+
+Options:
+
+ \- filehash
+ return only entries matching hash (exactly)
+
+ \- filename
+ return only entries matching filename (substring)
+
+ \- filetype
+ return only entries matching filetype/mimetype (substring)
+
+ \- start
+ start at record (default 0)
+
+ \- records
+ number of records to return or 0 for unlimited
+
+
+
+Example:
+
+```
+curl -u mychannel:mypassword https://xyz.macgirvin.com/api/z/1.0/files -d filetype=multipart/mixed
+```
+
+
+Returns:
+
+```
+ {
+
+ "success": true,
+ "results": [
+ {
+ "id": "1",
+ "aid": "1",
+ "uid": "2",
+ "hash": "44ee8b2a1a7f36dea07b93b7747a2383a1bc0fdd08339e8928bfcbe45f65d939",
+ "filename": "Profile Photos",
+ "filetype": "multipart/mixed",
+ "filesize": "0",
+ "revision": "0",
+ "folder": "",
+ "os_storage": "1",
+ "is_dir": "1",
+ "is_photo": "0",
+ "flags": "0",
+ "created": "2016-01-02 21:51:17",
+ "edited": "2016-01-02 21:51:17",
+ "allow_cid": "",
+ "allow_gid": "",
+ "deny_cid": "",
+ "deny_gid": ""
+ },
+ {
+ "id": "12",
+ "aid": "1",
+ "uid": "2",
+ "hash": "71883f1fc64af33889229cbc79c5a056deeec5fc277d765f182f19073e1b2998",
+ "filename": "Cover Photos",
+ "filetype": "multipart/mixed",
+ "filesize": "0",
+ "revision": "0",
+ "folder": "",
+ "os_storage": "1",
+ "is_dir": "1",
+ "is_photo": "0",
+ "flags": "0",
+ "created": "2016-01-15 00:24:33",
+ "edited": "2016-01-15 00:24:33",
+ "allow_cid": "",
+ "allow_gid": "",
+ "deny_cid": "",
+ "deny_gid": ""
+ },
+ {
+ "id": "16",
+ "aid": "1",
+ "uid": "2",
+ "hash": "f48f7ec3278499d1dd86b72c3207beaaf4717b07df5cc9b373f14d7aad2e1bcd",
+ "filename": "2016-01",
+ "filetype": "multipart/mixed",
+ "filesize": "0",
+ "revision": "0",
+ "folder": "",
+ "os_storage": "1",
+ "is_dir": "1",
+ "is_photo": "0",
+ "flags": "0",
+ "created": "2016-01-22 03:24:55",
+ "edited": "2016-01-22 03:26:57",
+ "allow_cid": "",
+ "allow_gid": "",
+ "deny_cid": "",
+ "deny_gid": ""
+ }
+ ]
+ }
+```
+
+### filemeta
+
+Export file metadata for any uploaded file
+
+
+
+### filedata
+
+Provides the ability to download a file from cloud storage in chunks
+
+GET /api/z/1.0/filedata
+
+
+Required:
+
+ \- file_id
+ attach.hash of desired file ('begins with' match)
+
+
+Optional:
+
+ \- start
+ starting byte of returned data in file (counting from 0)
+
+ \- length
+ length (prior to base64 encoding) of chunk to download
+
+
+Returns:
+
+ attach (DB) structure with base64 encoded 'content' comprised of the desired chunk
+
+
+
+Example:
+
+`https://xyz.macgirvin.com/api/z/1.0/filedata?f=&file_id=9f5217770fd&start=0&length=48`
+
+Returns:
+
+```
+ {
+
+ "attach": {
+ "id": "107",
+ "aid": "1",
+ "uid": "2",
+ "hash": "9f5217770fd55d563bd77f84d534d8e119a187514bbd391714626cd9c0e60207",
+ "creator": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
+ "filename": "pcxtopbm.c",
+ "filetype": "application/octet-stream",
+ "filesize": "3934",
+ "revision": "0",
+ "folder": "",
+ "flags": "0",
+ "is_dir": "0",
+ "is_photo": "0",
+ "os_storage": "1",
+ "os_path": "",
+ "display_path": "",
+ "content": "LyogcGN4dG9wYm0uYyAtIGNvbnZlcnQgUEMgcGFpbnRicnVzaCAoLnBjeCkgZmls",
+ "created": "2016-07-24 23:13:01",
+ "edited": "2016-07-24 23:13:01",
+ "allow_cid": "",
+ "allow_gid": "",
+ "deny_cid": "",
+ "deny_gid": "",
+ "start": 0,
+ "length": 48
+ }
+
+ }
+```
+
+### file/export
+
+### file
+
+### albums
+
+Description: list photo albums
+
+GET /api/z/1.0/albums
+
+
+Output:
+
+ text - textual name
+
+ total - number of photos in this album
+
+ url - web URL
+
+ urlencode - textual name, urlencoded
+
+ bin2hex - textual name using bin2hex (which is used in the web URL link)
+
+
+Example:
+
+
+
+```
+ {
+
+ "success": true,
+ "albums": [
+ {
+ "text": "/",
+ "total": "2",
+ "url": "https://xyz.macgirvin.com/photos/hubzilla/album/",
+ "urlencode": "",
+ "bin2hex": ""
+ },
+ {
+ "text": "2016-01",
+ "total": "6",
+ "url": "https://xyz.macgirvin.com/photos/hubzilla/album/323031362d3031",
+ "urlencode": "2016-01",
+ "bin2hex": "323031362d3031"
+ },
+ {
+ "text": "2016-02",
+ "total": "7",
+ "url": "https://xyz.macgirvin.com/photos/hubzilla/album/323031362d3032",
+ "urlencode": "2016-02",
+ "bin2hex": "323031362d3032"
+ },
+ {
+ "text": "Cover Photos",
+ "total": "5",
+ "url": "https://xyz.macgirvin.com/photos/hubzilla/album/436f7665722050686f746f73",
+ "urlencode": "Cover+Photos",
+ "bin2hex": "436f7665722050686f746f73"
+ },
+ {
+ "text": "Profile Photos",
+ "total": "26",
+ "url": "https://xyz.macgirvin.com/photos/hubzilla/album/50726f66696c652050686f746f73",
+ "urlencode": "Profile+Photos",
+ "bin2hex": "50726f66696c652050686f746f73"
+ }
+ ]
+
+ }
+```
+
+### photos
+
+list photo metadata
+
+
+
+### photo
+
+### group
+
+```
+GET /api/z/1.0/group
+```
+
+Description: list privacy groups
+
+Returns: DB tables of all privacy groups.
+
+To use with API group_members, provide either 'group_id' from the id element returned in this call, or 'group_name' from the gname returned in this call.
+
+
+
+```
+ [
+
+ {
+ "id": "1",
+ "hash": "966c946394f3e2627bbb8a55026b5725e582407098415c02f85232de3f3fde76Friends",
+ "uid": "2",
+ "visible": "0",
+ "deleted": "0",
+ "gname": "Friends"
+ },
+ {
+ "id": "2",
+ "hash": "852ebc17f8c3ed4866f2162e384ded0f9b9d1048f93822c0c84196745f6eec66Family",
+ "uid": "2",
+ "visible": "1",
+ "deleted": "0",
+ "gname": "Family"
+ },
+ {
+ "id": "3",
+ "hash": "cc3cb5a7f9818effd7c7c80a58b09a189b62efa698a74319117babe33ee30ab9Co-workers",
+ "uid": "2",
+ "visible": "0",
+ "deleted": "0",
+ "gname": "Co-workers"
+ }
+ ]
+```
+
+### group_members
+
+```
+GET /api/z/1.0/group_members
+```
+
+Required:
+
+group_id or group_name
+
+
+Returns:
+
+group_member+abook+xchan (DB join) for each member of the privacy group
+
+
+
+```
+ [
+
+ {
+ "id": "1",
+ "uid": "2",
+ "gid": "1",
+ "xchan": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
+ "abook_id": "2",
+ "abook_account": "1",
+ "abook_channel": "2",
+ "abook_xchan": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
+ "abook_my_perms": "218555",
+ "abook_their_perms": "0",
+ "abook_closeness": "0",
+ "abook_created": "2016-01-02 21:16:26",
+ "abook_updated": "2016-01-02 21:16:26",
+ "abook_connected": "0000-00-00 00:00:00",
+ "abook_dob": "0000-00-00 00:00:00",
+ "abook_flags": "0",
+ "abook_blocked": "0",
+ "abook_ignored": "0",
+ "abook_hidden": "0",
+ "abook_archived": "0",
+ "abook_pending": "0",
+ "abook_unconnected": "0",
+ "abook_self": "1",
+ "abook_feed": "0",
+ "abook_profile": "",
+ "abook_incl": "",
+ "abook_excl": "",
+ "abook_instance": "",
+ "xchan_hash": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
+ "xchan_guid": "lql-1VnxtiO4-WF0h72wLX1Fu8szzHDOXgQaTbELwXW77k8AKFfh-hYr70vqMrc3SSvWN-Flrc5HFhRTWB7ICw",
+ "xchan_guid_sig": "PafvEL0VpKfxATxlCqDjfOeSIMdmpr3iU7X-Sysa1h5LzDpjSXsjO37tYZL-accb1M5itLlfnW5epkTa5I4flsW21zSY1A2jCuBQUTLLGV7rNyyBy7lgqJUFvAMRx0TfXzP9lcaPqlM9T1tA6jfWOsOmkdzwofGeXBnsjGfjsO2xdGYe6vwjOU0DSavukvzDMnOayB9DekpvDnaNBTxeGLM45Skzr7ZEMcNF7TeXMbnvpfLaALYEKeQs9bGH-UgAG8fBWgzVAzeBfx_XSR1rdixjyiZGP0kq0h35SlmMPcEjliodOBFwMXqpXFB7Ibp4F6o6te2p2ErViJccQVG8VNKB6SbKNXY6bhP5zVcVsJ-vR-p4xXoYJJvzTN7yTDsGAXHOLF4ZrXbo5yi5gFAlIrTLAF2EdWQwxSGyLRWKxG8PrDkzEzX6cJJ0VRcLh5z6OI5QqQNdeghPZbshMFMJSc_ApCPi9_hI4ZfctCIOi3T6bdgTNKryLm5fhy_eqjwLAZTGP-aUBgLZpb1mf2UojBn6Ey9cCyq-0T2RWyk-FcIcbV4qJ-p_8oODqw13Qs5FYkjLr1bGBq82SuolkYrXEwQClxnrfKa4KYc2_eHAXPL01iS9zVnI1ySOCNJshB97Odpooc4wk7Nb2Fo-Q6THU9zuu0uK_-JbK7IIl6go2qA",
+ "xchan_pubkey": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA18JB76lyP4zzL/y7BCej\neJnfZIWZNtM3MZvI1zEVMWmmwOS+u/yH8oPwyaDk4Y/tnj8GzMPj1lCGVRcd8EJa\nNrCMd50HODA5EsJtxpsOzRcILYjOcTtIAG1K4LtKqELi9ICAaFp0fNfa+Jf0eCek\nvPusx2/ORhy+o23hFoSMhL86o2gmaiRnmnA3Vz4ZMG92ieJEDMXt9IA1EkIqS4y5\nBPZfVPLD1pv8iivj+dtN1XjwplgjUbtxmU0/Ej808nHppscRIqx/XJ0XZU90oNGw\n/wYoK2EzJlPbRsAkwNqoFrAYlr5HPpn4BJ2ebFYQgWBUraD7HwS5atsQEaxGfO21\nlUP0+lDg9t3CXvudDj0UG1jiEKbVIGA+4aG0GN2DSC5AyRq/GRxqyay5W2vQbAZH\nyvxPGrZFO24I65g3pjhpjEsLqZ4ilTLQoLMs0drCIcRm5RxMUo4s/LMg16lT4cEk\n1qRtk2X0Sb1AMQQ2uRXiVtWz77QHMONEYkf6OW4SHbwcv5umvlv69NYEGfCcbgq0\nAV7U4/BWztUz/SWj4r194CG43I9I8dmaEx9CFA/XMePIAXQUuABfe1QMOR6IxLpq\nTHG1peZgHQKeGz4aSGrhQkZNNoOVNaZoIfcvopxcHDTZLigseEIaPPha4WFYoKPi\nUPbZ5o8gTLc750uzrnb2jwcCAwEAAQ==\n-----END PUBLIC KEY-----\n",
+ "xchan_photo_mimetype": "image/png",
+ "xchan_photo_l": "https://xyz.macgirvin.com/photo/profile/l/2",
+ "xchan_photo_m": "https://xyz.macgirvin.com/photo/profile/m/2",
+ "xchan_photo_s": "https://xyz.macgirvin.com/photo/profile/s/2",
+ "xchan_addr": "teller@xyz.macgirvin.com",
+ "xchan_url": "https://xyz.macgirvin.com/channel/teller",
+ "xchan_connurl": "https://xyz.macgirvin.com/poco/teller",
+ "xchan_follow": "https://xyz.macgirvin.com/follow?f=&url=%s",
+ "xchan_connpage": "",
+ "xchan_name": "Teller",
+ "xchan_network": "zot",
+ "xchan_instance_url": "",
+ "xchan_flags": "0",
+ "xchan_photo_date": "2016-10-19 01:26:50",
+ "xchan_name_date": "2016-01-02 21:16:26",
+ "xchan_hidden": "0",
+ "xchan_orphan": "0",
+ "xchan_censored": "0",
+ "xchan_selfcensored": "0",
+ "xchan_system": "0",
+ "xchan_pubforum": "0",
+ "xchan_deleted": "0"
+ },
+ {
+ "id": "12",
+ "uid": "2",
+ "gid": "1",
+ "xchan": "xuSMUYxw1djBB97qXsbrBN1nzJH_gFwQL6pS4zIy8fuusOfBxNlMiVb4h_q5tOEvpE7tYf1EsryjNciMuPIj5w",
+ "abook_id": "24",
+ "abook_account": "1",
+ "abook_channel": "2",
+ "abook_xchan": "xuSMUYxw1djBB97qXsbrBN1nzJH_gFwQL6pS4zIy8fuusOfBxNlMiVb4h_q5tOEvpE7tYf1EsryjNciMuPIj5w",
+ "abook_my_perms": "218555",
+ "abook_their_perms": "218555",
+ "abook_closeness": "80",
+ "abook_created": "2016-01-27 00:48:43",
+ "abook_updated": "2016-12-04 17:16:58",
+ "abook_connected": "2016-12-04 17:16:58",
+ "abook_dob": "0001-01-01 00:00:00",
+ "abook_flags": "0",
+ "abook_blocked": "0",
+ "abook_ignored": "0",
+ "abook_hidden": "0",
+ "abook_archived": "0",
+ "abook_pending": "0",
+ "abook_unconnected": "0",
+ "abook_self": "0",
+ "abook_feed": "0",
+ "abook_profile": "debb5236efb1626cfbad33ccb49892801e5f844aa04bf81f580cfa7d13204819",
+ "abook_incl": "",
+ "abook_excl": "",
+ "abook_instance": "",
+ "xchan_hash": "xuSMUYxw1djBB97qXsbrBN1nzJH_gFwQL6pS4zIy8fuusOfBxNlMiVb4h_q5tOEvpE7tYf1EsryjNciMuPIj5w",
+ "xchan_guid": "d5EMLlt1tHHZ0dANoA7B5Wq9UgXoWcFS9-gXOkL_AAejcPApoQRyxfHTuu8DoTbUaO-bYmX5HPuWuK9PHyqNmA",
+ "xchan_guid_sig": "CVWEMRPtzI1YcHfnnWHTuv3H964OAmSElgUfxMoX6RdQdxNpqb_POirpVuyP8s3W17mVCfO5V9IAjkg5iKcqCk6YcvOD_egmMy-AnM9TC1kKndQHw55CunD82Q8K_xBNSXkSROizcNkKh9DVLjJPFjW1AqtI4njkZ3EMgrWqnbFRM1qPToUoCY9zM3tEMHoAD9YX1zP90wl40LzfN-dtcNWpSBbiz9owou62uzLbN7mrCwKOMlXLjwwGswRnxIsEnb3O-FXOs8hs0mArKe9snq1-BKeD16LyzxgwlpVLElzIJZGEZGtMdIJgeRzKuBvPjsOIpQ1yAkuOpFJ3nGCM-IPOIIjAmyVl5zD3xPVcxxpZlJRn5fG1Y-gnqTgsrEQCA7M6XPWQdrdHU4akZfyUyFJDhv3uM-jon9VzrYTBw68R0WA-1Z8WafEHA4qh5OWAj85lUarwhr7iTiEckH51ypPCPs6VbT6Pw7yMaxfjFOcipashQagx0tfOlDhE5dQANOXKASFtH1J9-CZY2MQdLPQ6u54d5whuHKMGaJ0V68pnmZ2rOn7g344Ah2WCJrm17jj60QsRMorqRFj7GMdPIA1XB8Wrk88MuYOe3Dhyuu6ZWKI7YTWJS690ZVkKUqAiNHqj0W86DtaiPUc_mmGR0fHl4Gksnko3WmCFv9q2X2E",
+ "xchan_pubkey": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAoj2xCJktBA8Ww7Hp+ZNL\nrNuQpo8UB/bfvRkIy+yua3xpF1TuXcnAH61kyRz8vXgOu/l2CyxQbIoaGslCV5Sy\n8JKeNXe+IilUdSSEjMIwCPfSPsYnMHsSnHWmPmclvJwEtQUKOZmW5mMuVBvXy7D2\njomFwc69AYphdyys6eQ7Dcn6+FRBiQbyMprZ5lxyVW+O4DuXVNa3ej2ebx0gCJZ4\ntTIlBoKwEey91dY+FyKVFjdwfNczpmL7LgmZXqcVx+MG3mYgibwdVMiXVj5X06cs\nV9hJ5Xi+Aklsv/UWJtjw9FVt7y9TLptnhh4Ra6T/MDmnBBIAkOR7P/X8cRv078MT\nl0IMsP0RJcDEtTLtwHFVtDs6p52KDFqclKWbqmxmxqV3OTPVYtArRGIzgnJi/5ur\nHRr5G6Cif7QY3UowsIOf78Qvy28LwSbdymgBAWwPPKIviXWxGO+9kMWdmPSUQrWy\nK0+7YA9P9fBUFfn9Hc+p8SJQmQ6OAqLwrDGiPSOlGaNrbEqwqLGgIpXwK+lEFcFJ\n3SPOjJRWdR2whlMxvpwX+39+H7dWN3vSa3Al4/Sq7qW8yW2rYwf+eGyp4Z0lRR+8\nJxFMCwZkSw5g14YdlikAPojv5V1c6KuA5ieg8G1hwyONV7A4JHPyEdPt0W0TZi6C\nCOVkPaC3xGrguETZpJfVpwUCAwEAAQ==\n-----END PUBLIC KEY-----\n",
+ "xchan_photo_mimetype": "image/png",
+ "xchan_photo_l": "https://xyz.macgirvin.com/photo/9da63aa910ea14e1501ee1a749d181a6-4",
+ "xchan_photo_m": "https://xyz.macgirvin.com/photo/9da63aa910ea14e1501ee1a749d181a6-5",
+ "xchan_photo_s": "https://xyz.macgirvin.com/photo/9da63aa910ea14e1501ee1a749d181a6-6",
+ "xchan_addr": "cloner@xyz.macgirvin.com",
+ "xchan_url": "http://abc.macgirvin.com/channel/cloner",
+ "xchan_connurl": "http://abc.macgirvin.com/poco/cloner",
+ "xchan_follow": "https://xyz.macgirvin.com/follow?f=&url=%s",
+ "xchan_connpage": "",
+ "xchan_name": "Karen",
+ "xchan_network": "zot",
+ "xchan_instance_url": "",
+ "xchan_flags": "0",
+ "xchan_photo_date": "2016-03-31 19:59:20",
+ "xchan_name_date": "2016-01-26 23:23:42",
+ "xchan_hidden": "0",
+ "xchan_orphan": "0",
+ "xchan_censored": "0",
+ "xchan_selfcensored": "0",
+ "xchan_system": "0",
+ "xchan_pubforum": "0",
+ "xchan_deleted": "0"
+ }
+
+ ]
+```
+
+### xchan
+
+An xchan is a global location independent channel and is the primary record for a network
+identity. It may refer to channels on other websites, networks, or services.
+
+```
+GET /api/z/1.0/xchan
+```
+
+Required: one of [ address, hash, guid ] as GET parameters
+
+Returns a portable xchan structure
+
+Example: `https://xyz.macgirvin.com/api/z/1.0/xchan?f=&address=mike@macgirvin.com`
+
+Returns:
+
+```
+ {
+ "hash": "jr54M_y2l5NgHX5wBvP0KqWcAHuW23p1ld-6Vn63_pGTZklrI36LF8vUHMSKJMD8xzzkz7s2xxCx4-BOLNPaVA",
+ "guid": "sebQ-IC4rmFn9d9iu17m4BXO-kHuNutWo2ySjeV2SIW1LzksUkss12xVo3m3fykYxN5HMcc7gUZVYv26asx-Pg",
+ "guid_sig": "Llenlbl4zHo6-g4sa63MlQmTP5dRCrsPmXHHFmoCHG63BLq5CUZJRLS1vRrrr_MNxr7zob_Ykt_m5xPKe5H0_i4pDj-UdP8dPZqH2fqhhx00kuYL4YUMJ8gRr5eO17vsZQ3XxTcyKewtgeW0j7ytwMp6-hFVUx_Cq08MrXas429ZrjzaEwgTfxGnbgeQYQ0R5EXpHpEmoERnZx77VaEahftmdjAUx9R4YKAp13pGYadJOX5xnLfqofHQD8DyRHWeMJ4G1OfWPSOlXfRayrV_jhnFlZjMU7vOdQwHoCMoR5TFsRsHuzd-qepbvo3pzvQZRWnTNu6oPucgbf94p13QbalYRpBXKOxdTXJrGdESNhGvhtaZnpT9c1QVqC46jdfP0LOX2xrVdbvvG2JMWFv7XJUVjLSk_yjzY6or2VD4V6ztYcjpCi9d_WoNHruoxro_br1YO3KatySxJs-LQ7SOkQI60FpysfbphNyvYMkotwUFI59G08IGKTMu3-GPnV1wp7NOQD1yzJbGGEGSEEysmEP0SO9vnN45kp3MiqbffBGc1r4_YM4e7DPmqOGM94qksOcLOJk1HNESw2dQYWxWQTBXPfOJT6jW9_crGLMEOsZ3Jcss0XS9KzBUA2p_9osvvhUKuKXbNztqH0oZIWlg37FEVsDs_hUwUJpv2Ar09k4",
+ "pubkey": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7QCwvuEIwCHjhjbpz3Oc\ntyei/Pz9nDksNbsc44Cm8jxYGMXsTPFXDZYCcCB5rcAhPPdZSlzaPkv4vPVcMIrw\n5cdX0tvbwa3rNTng6uFE7qkt15D3YCTkwF0Y9FVZiZ2Ko+G23QeBt9wqb9dlDN1d\nuPmu9BLYXIT/JXoBwf0vjIPFM9WBi5W/EHGaiuqw7lt0qI7zDGw77yO5yehKE4cu\n7dt3SakrXphL70LGiZh2XGoLg9Gmpz98t+gvPAUEotAJxIUqnoiTA8jlxoiQjeRK\nHlJkwMOGmRNPS33awPos0kcSxAywuBbh2X3aSqUMjcbE4cGJ++/13zoa6RUZRObC\nZnaLYJxqYBh13/N8SfH7d005hecDxWnoYXeYuuMeT3a2hV0J84ztkJX5OoxIwk7S\nWmvBq4+m66usn6LNL+p5IAcs93KbvOxxrjtQrzohBXc6+elfLVSQ1Rr9g5xbgpub\npSc+hvzbB6p0tleDRzwAy9X16NI4DYiTj4nkmVjigNo9v2VPnAle5zSam86eiYLO\nt2u9YRqysMLPKevNdj3CIvst+BaGGQONlQalRdIcq8Lin+BhuX+1TBgqyav4XD9K\nd+JHMb1aBk/rFLI9/f2S3BJ1XqpbjXz7AbYlaCwKiJ836+HS8PmLKxwVOnpLMbfH\nPYM8k83Lip4bEKIyAuf02qkCAwEAAQ==\n-----END PUBLIC KEY-----\n",
+ "photo_mimetype": "image/jpeg",
+ "photo_l": "https://xyz.macgirvin.com/photo/350b74555c04429148f2e12775f6c403-4",
+ "photo_m": "https://xyz.macgirvin.com/photo/350b74555c04429148f2e12775f6c403-5",
+ "photo_s": "https://xyz.macgirvin.com/photo/350b74555c04429148f2e12775f6c403-6",
+ "address": "mike@macgirvin.com",
+ "url": "https://macgirvin.com/channel/mike",
+ "connurl": "https://macgirvin.com/poco/mike",
+ "follow": "https://macgirvin.com/follow?f=&url=%s",
+ "connpage": "https://macgirvin.com/connect/mike",
+ "name": "Mike Macgirvin",
+ "network": "zot",
+ "instance_url": "",
+ "flags": "0",
+ "photo_date": "2012-12-06 05:06:11",
+ "name_date": "2012-12-06 04:59:13",
+ "hidden": "1",
+ "orphan": "0",
+ "censored": "0",
+ "selfcensored": "0",
+ "system": "0",
+ "pubforum": "0",
+ "deleted": "0"
+ }
+```
+
+### item/update
+
+Create or update an item (post, activity, webpage, etc.)
+
+Usage: `POST /api/z/1.0/item/update`
+
+Description: item/update posts an item (typically a conversation item or post, but can be any item) using form input.
+
+
+Required:
+
+\- body
+
+ text/bbcode contents by default.
+
+
+Optional:
+
+\- $_FILES['media']
+
+ uploaded media file to include with post
+
+\- title
+
+ title of post/item
+
+\- contact_allow
+
+ array of xchan.xchan_hash allowed to view this item
+
+\- group_allow
+
+ array of group.hash allowed to view this item
+
+\- contact_deny
+
+ array of xchan.xchan_hash not allowed to view this item
+
+\- group_deny
+
+ array of group.hash not allowed to view this item
+
+\- coord
+
+ geographic coordinates
+
+\- location
+
+ freefrom location
+
+\- expire
+
+ datetime this post will expire or be removed
+
+\- mimetype
+
+ mimetype if not text/bbcode
+
+\- parent
+
+ item.id of parent to this post (makes it a comment)
+
+\- parent_mid
+
+ alternate form of parent using message_id
+
+\- remote_xchan
+
+ xchan.xchan_hash of this message author if not the channel owner
+
+\- consensus
+
+ boolean set to true if this is a consensus or voting item (default false)
+
+\- nocomment
+
+ boolean set to true if comments are to be disabled (default false)
+
+\- origin
+
+ do not use this without reading the code
+
+\- namespace
+
+ persistent identity for a remote network or service
+
+\- remote_id
+
+ message_id of this resource on a remote network or service
+
+\- message_id
+
+ message_id of this item (leave unset to generate one)
+
+\- created
+
+ datetime of message creation
+
+\- post_id
+
+ existing item.id if this is an edit operation
+
+\- app
+
+ application or network name to display with item
+
+\- category
+
+ comma separated categories for this item
+
+\- webpage
+
+ item.page_type if not 0
+
+\- pagetitle
+
+ for webpage and design elements, the 'page name'
+
+\- layout_mid
+
+ item.mid of layout for this design element
+
+\- plink
+
+ permalink for this item if different than the default
+
+\- verb
+
+ activitystream verb for this item/activity
+
+\- obj_type
+
+ activitystream object type for this item/activity
+
+
+
+Example:
+
+
+
+```
+curl -u mychannel:mypassword https://xyz.macgirvin.com/api/z/1.0/item/update -d body="hello world"
+```
+
+
+Returns:
+
+
+
+```
+ {
+
+ "success": true,
+ "item_id": "2245",
+ "item": {
+ "id": "2245",
+ "mid": "14135cdecf6b8e3891224e4391748722114da6668eebbcb56fe4667b60b88249@xyz.macgirvin.com",
+ "aid": "1",
+ "uid": "2",
+ "parent": "2245",
+ "parent_mid": "14135cdecf6b8e3891224e4391748722114da6668eebbcb56fe4667b60b88249@xyz.macgirvin.com",
+ "thr_parent": "14135cdecf6b8e3891224e4391748722114da6668eebbcb56fe4667b60b88249@xyz.macgirvin.com",
+ "created": "2016-12-03 20:00:12",
+ "edited": "2016-12-03 20:00:12",
+ "expires": "0001-01-01 00:00:00",
+ "commented": "2016-12-03 20:00:12",
+ "received": "2016-12-03 20:00:12",
+ "changed": "2016-12-03 20:00:12",
+ "comments_closed": "0001-01-01 00:00:00",
+ "owner_xchan": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
+ "author_xchan": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
+ "source_xchan": "",
+ "mimetype": "text/bbcode",
+ "title": "",
+ "body": "hello world",
+ "html": "",
+ "app": "",
+ "lang": "",
+ "revision": "0",
+ "verb": "http://activitystrea.ms/schema/1.0/post",
+ "obj_type": "http://activitystrea.ms/schema/1.0/note",
+ "obj": "",
+ "tgt_type": "",
+ "target": "",
+ "layout_mid": "",
+ "postopts": "",
+ "route": "",
+ "llink": "https://xyz.macgirvin.com/display/14135cdecf6b8e3891224e4391748722114da6668eebbcb56fe4667b60b88249@xyz.macgirvin.com",
+ "plink": "https://xyz.macgirvin.com/channel/mychannel/?f=&mid=14135cdecf6b8e3891224e4391748722114da6668eebbcb56fe4667b60b88249@xyz.macgirvin.com",
+ "resource_id": "",
+ "resource_type": "",
+ "attach": "",
+ "sig": "sa4TOQNfHtV13HDZ1tuQGWNBpZp-nWhT2GMrZEmelXxa_IvEepD2SEsCTWOBqM8OKPJLfNy8_i-ORXjrOIIgAa_aT8cw5vka7Q0C8L9eEb_LegwQ_BtH0CXO5uT30e_8uowkwzh6kmlVg1ntD8QqrGgD5jTET_fMQOIw4gQUBh40GDG9RB4QnPp_MKsgemGrADnRk2vHO7-bR32yQ0JI-8G-eyeqGaaJmIwkHoi0vXsfjZtU7ijSLuKEBWboNjKEDU89-vQ1c5Kh1r0pmjiDk-a5JzZTYShpuhVA-vQgEcADA7wkf4lJZCYNwu3FRwHTvhSMdF0nmyv3aPFglQDky38-SAXZyQSvd7qlABHGCVVDmYrYaiq7Dh4rRENbAUf-UJFHPCVB7NRg34R8HIqmOKq1Su99bIWaoI2zuAQEVma9wLqMoFsluFhxX58KeVtlCZlro7tZ6z619-dthS_fwt0cL_2dZ3QwjG1P36Q4Y4KrCTpntn9ot5osh-HjVQ01h1I9yNCj6XPgYJ8Im3KT_G4hmMDFM7H9RUrYLl2o9XYyiS2nRrf4aJHa0UweBlAY4zcQG34bw2AMGCY53mwsSArf4Hs3rKu5GrGphuwYX0lHa7XEKMglwBWPWHI49q7-oNWr7aWwn1FnfaMfl4cQppCMtKESMNRKm_nb9Dsh5e0",
+ "diaspora_meta": "",
+ "location": "",
+ "coord": "",
+ "public_policy": "",
+ "comment_policy": "contacts",
+ "allow_cid": "",
+ "allow_gid": "",
+ "deny_cid": "",
+ "deny_gid": "",
+ "item_restrict": "0",
+ "item_flags": "0",
+ "item_private": "0",
+ "item_origin": "1",
+ "item_unseen": "0",
+ "item_starred": "0",
+ "item_uplink": "0",
+ "item_consensus": "0",
+ "item_wall": "1",
+ "item_thread_top": "1",
+ "item_notshown": "0",
+ "item_nsfw": "0",
+ "item_relay": "0",
+ "item_mentionsme": "0",
+ "item_nocomment": "0",
+ "item_obscured": "0",
+ "item_verified": "1",
+ "item_retained": "0",
+ "item_rss": "0",
+ "item_deleted": "0",
+ "item_type": "0",
+ "item_hidden": "0",
+ "item_unpublished": "0",
+ "item_delayed": "0",
+ "item_pending_remove": "0",
+ "item_blocked": "0"
+ }
+
+ }
+```
+
+### item/full
+
+Get all data associated with an item
+
+
+
+### abook
+
+Connections
+
+
+
+### abconfig
+
+Connection metadata (such as permissions)
+
+
+
+### perm_allowed
+
+Check a permission for a given xchan \ No newline at end of file
diff --git a/doc/en/developer/Plugins.md b/doc/en/developer/Plugins.md
new file mode 100644
index 000000000..78b2dab68
--- /dev/null
+++ b/doc/en/developer/Plugins.md
@@ -0,0 +1,259 @@
+
+### Creating Plugins/Addons for Hubzilla
+
+
+So you want to make hubzilla do something it doesn't already do. There are lots of ways. But let's learn how to write a plugin or addon.
+
+
+In your hubzilla folder/directory, you will probably see a sub-directory called 'addon'. If you don't have one already, go ahead and create it.
+
+
+ mkdir addon
+
+Then figure out a name for your addon. You probably have at least a vague idea of what you want it to do. For our example I'm going to create a plugin called 'randplace' that provides a somewhat random location for each of your posts. The name of your plugin is used to find the functions we need to access and is part of the function names, so to be safe, use only simple text characters.
+
+Once you've chosen a name, create a directory beneath 'addon' to hold your working file or files.
+
+ mkdir addon/randplace
+
+Now create your plugin file. It needs to have the same name, and it's a PHP script, so using your favourite editor, create the file
+
+ addon/randplace/randplace.php
+
+The very first line of this file needs to be
+
+ <?php
+
+Then we're going to create a comment block to describe the plugin. There's a special format for this. We use /* ... */ comment-style and some tagged lines consisting of
+
+ /**
+ *
+ * Name: Random Place (here you can use better descriptions than you could in the filename)
+ * Description: Sample hubzilla plugin, Sets a random place when posting.
+ * Version: 1.0
+ * Author: Mike Macgirvin <mike@zothub.com>
+ *
+ */
+
+These tags will be seen by the site administrator when he/she installs or manages plugins from the admin panel. There can be more than one author. Just add another line starting with 'Author:'.
+
+The typical plugin will have at least the following functions:
+
+* pluginname_load()
+* pluginname_unload()
+
+In our case, we'll call them randplace_load() and randplace_unload(), as that is the name of our plugin. These functions are called whenever we wish to either initialise the plugin or remove it from the current webpage. Also if your plugin requires things like altering the database schema before it can run for the very first time, you would likely place these instructions in the functions named
+
+* pluginname_install()
+* pluginname_uninstall()
+
+
+Next we'll talk about **hooks**. Hooks are places in hubzilla code where we allow plugins to do stuff. There are a [lot of these](help/Hooks), and they each have a name. What we normally do is use the pluginname_load() function to register a "handler function" for any hooks you are interested in. Then when any of these hooks are triggered, your code will be called.
+
+We register hook handlers with the 'register_hook()' function. It takes 3 arguments. The first is the hook we wish to catch, the second is the filename of the file to find our handler function (relative to the base of your hubzilla installation), and the third is the function name of your handler function. So let's create our randplace_load() function right now.
+
+
+ function randplace_load() {
+ register_hook('post_local', 'addon/randplace/randplace.php', 'randplace_post_hook');
+
+ register_hook('feature_settings', 'addon/randplace/randplace.php', 'randplace_settings');
+ register_hook('feature_settings_post', 'addon/randplace/randplace.php', 'randplace_settings_post');
+
+ }
+
+
+So we're going to catch three events, 'post_local' which is triggered when a post is made on the local system, 'feature_settings' to set some preferences for our plugin, and 'feature_settings_post' to store those settings.
+
+Next we'll create an unload function. This is easy, as it just unregisters our hooks. It takes exactly the same arguments.
+
+ function randplace_unload() {
+ unregister_hook('post_local', 'addon/randplace/randplace.php', 'randplace_post_hook');
+
+ unregister_hook('feature_settings', 'addon/randplace/randplace.php', 'randplace_settings');
+ unregister_hook('feature_settings_post', 'addon/randplace/randplace.php', 'randplace_settings_post');
+
+ }
+
+
+Hooks are called with two arguments. The first is always $a, which is our global App structure and contains a huge amount of information about the state of the web request we are processing; as well as who the viewer is, and what our login state is, and the current contents of the web page we're probably constructing.
+
+The second argument is specific to the hook you're calling. It contains information relevant to that particular place in the program, and often allows you to look at, and even change it. In order to change it, you need to add '&' to the variable name so it is passed to your function by reference. Otherwise it will create a copy and any changes you make will be lost when the hook process returns. Usually (but not always) the second argument is a named array of data structures. Please see the "hook reference" (not yet written as of this date) for details on any specific hook. Occasionally you may need to view the program source to see precisely how a given hook is called and how the results are processed.
+
+Let's go ahead and add some code to implement our post_local hook handler.
+
+ function randplace_post_hook($a, &$item) {
+
+ /**
+ *
+ * An item was posted on the local system.
+ * We are going to look for specific items:
+ * - A status post by a profile owner
+ * - The profile owner must have allowed our plugin
+ *
+ */
+
+ logger('randplace invoked');
+
+ if(! local_channel()) /* non-zero if this is a logged in user of this system */
+ return;
+
+ if(local_channel() != $item['uid']) /* Does this person own the post? */
+ return;
+
+ if(($item['parent']) || (! is_item_normal($item))) {
+ /* If the item has a parent, or isn't "normal", this is a comment or something else, not a status post. */
+ return;
+ }
+
+ /* Retrieve our personal config setting */
+
+ $active = get_pconfig(local_channel(), 'randplace', 'enable');
+
+ if(! $active)
+ return;
+ /**
+ *
+ * OK, we're allowed to do our stuff.
+ * Here's what we are going to do:
+ * load the list of timezone names, and use that to generate a list of world cities.
+ * Then we'll pick one of those at random and put it in the "location" field for the post.
+ *
+ */
+
+ $cities = array();
+ $zones = timezone_identifiers_list();
+ foreach($zones as $zone) {
+ if((strpos($zone,'/')) && (! stristr($zone,'US/')) && (! stristr($zone,'Etc/')))
+ $cities[] = str_replace('_', ' ',substr($zone,strpos($zone,'/') + 1));
+ }
+
+ if(! count($cities))
+ return;
+ $city = array_rand($cities,1);
+ $item['location'] = $cities[$city];
+
+ return;
+ }
+
+
+Now let's add our functions to create and store preference settings.
+
+ /**
+ *
+ * Callback from the settings post function.
+ * $post contains the global $_POST array.
+ * We will make sure we've got a valid user account
+ * and that only our own submit button was clicked
+ * and if so set our configuration setting for this person.
+ *
+ */
+
+ function randplace_settings_post($a,$post) {
+ if(! local_channel())
+ return;
+ if($_POST['randplace-submit'])
+ set_pconfig(local_channel(),'randplace','enable',intval($_POST['randplace']));
+ }
+
+
+
+ /**
+ *
+ * Called from the Feature Setting form.
+ * The second argument is a string in this case, the HTML content region of the page.
+ * Add our own settings info to the string.
+ *
+ * For uniformity of settings pages, we use the following convention
+ * <div class="settings-block">
+ * <h3>title</h3>
+ * .... settings html - many elements will be floated...
+ * <div class="clear"></div> <!-- generic class which clears all floats -->
+ * <input type="submit" name="pluginnname-submit" class="settings-submit" ..... />
+ * </div>
+ */
+
+
+
+ function randplace_settings(&$a,&$s) {
+
+ if(! local_channel())
+ return;
+
+ /* Add our stylesheet to the page so we can make our settings look nice */
+
+ head_add_css('/addon/randplace/randplace.css');
+
+ /* Get the current state of our config variable */
+
+ $enabled = get_pconfig(local_channel(),'randplace','enable');
+
+ $checked = (($enabled) ? ' checked="checked" ' : '');
+
+ /* Add some HTML to the existing form */
+
+ $s .= '<div class="settings-block">';
+ $s .= '<h3>' . t('Randplace Settings') . '</h3>';
+ $s .= '<div id="randplace-enable-wrapper">';
+ $s .= '<label id="randplace-enable-label" for="randplace-checkbox">' . t('Enable Randplace Plugin') . '</label>';
+ $s .= '<input id="randplace-checkbox" type="checkbox" name="randplace" value="1" ' . $checked . '/>';
+ $s .= '</div><div class="clear"></div>';
+
+ /* provide a submit button */
+
+ $s .= '<div class="settings-submit-wrapper" ><input type="submit" name="randplace-submit" class="settings-submit" value="' . t('Submit') . '" /></div></div>';
+
+ }
+
+
+
+
+
+#### *Advanced Plugins*
+
+Sometimes your plugins want to provide a range of new functionality which isn't provided at all or is clumsy to provide using hooks. In this case your plugin can also act as a 'module'. A module in our case refers to a structured webpage handler which responds to a given URL. Then anything which accesses that URL will be handled completely by your plugin.
+
+The key to this is to create a simple function named pluginname_module() which does nothing.
+
+ function randplace_module() { return; }
+
+Once this function exists, the URL `https://yoursite/randplace` will access your plugin as a module. Then you can define functions which are called at various points to build a webpage just like the modules in the mod/ directory. The typical functions and the order which they are called is
+
+ modulename_init($a) // (e.g. randplace_init($a);) called first - if you wish to emit json or xml,
+ // you should do it here, followed by killme() which will avoid the default action of building a webpage
+ modulename_aside($a) // Often used to create sidebar content
+ modulename_post($a) // Called whenever the page is accessed via the "post" method
+ modulename_content($a) // called to generate the central page content. This function should return a string
+ // consisting of the central page content.
+
+Your module functions have access to the URL path as if they were standalone programs in the Unix operating system. For instance if you visit the page
+
+ https://yoursite/randplace/something/somewhere/whatever
+
+we will create an argc/argv list for use by your module functions
+
+ $x = argc(); $x will be 4, the number of path arguments after the sitename
+
+ for($x = 0; $x < argc(); $x ++)
+ echo $x . ' ' . argv($x);
+
+
+ 0 randplace
+ 1 something
+ 2 somewhere
+ 3 whatever
+
+#### *Porting Friendica Plugins*
+
+Hubzilla uses a similar plugin architecture to the Friendica project. The authentication, identity, and permissions systems are completely different. Many Friendica plugins can be ported reasonably easily by renaming a few functions - and then ensuring that the permissions model is adhered to. The functions which need to be renamed are:
+
+* Friendica's pluginname_install() is pluginname_load()
+
+* Friendica's pluginname_uninstall() is pluginname_unload()
+
+Hubzilla has _install and _uninstall functions but these are used differently.
+
+* Friendica's "plugin_settings" hook is called "feature_settings"
+
+* Friendica's "plugin_settings_post" hook is called "feature_settings_post"
+
+Changing these will often allow your plugin to function, but please double check all your permission and identity code because the concepts behind it are completely different in hubzilla. Many structured data names (especially DB schema columns) are also quite different.
diff --git a/doc/en/developer/api_zot.bb b/doc/en/developer/api_zot.bb
deleted file mode 100644
index ff937bfa5..000000000
--- a/doc/en/developer/api_zot.bb
+++ /dev/null
@@ -1,766 +0,0 @@
-[h3]Zot API[/h3]
-
-Many existing social applications and tools can interface directly using the Twitter/StatusNet API, which is available using the 'twitter_api' addon.
-
-This document describes the native API; which allows direct programmatic access to several internal data structures and libraries extending beyond the basic social interface.
-
-The API endpoints detailed below are relative to [code]api/z/1.0[/code], meaning that if an API is listed as [code]channel/stream[/code] the full API URL is [code][baseurl]/api/z/1.0/channel/stream[/code].
-
-[h3]channel/export/basic[/h3]
-
-Export basic channel data
-
-Options:
- - sections
- comma-separated list of data types to export
-
- - posts
- if true, return default sections plus 3 months of posts
-
- If no sections are requested, the following sections are returned:
- channel, connections, config, apps, chatrooms, events, webpages, mail, wikis
-
- Files and large collections of posts may run into memory limits; these must generally be
- requested separately.
-
-
-[h3]channel/stream[/h3]
-
-Fetch channel conversation items
-
-[h3]network/stream[/h3]
-
-
-Fetch network conversation items
-
-
-
-[h3]files[/h3]
-
-
-List file storage (attach DB)
-
-GET /api/z/1.0/files
-
-
-Options:
-
- - filehash
- return only entries matching hash (exactly)
-
- - filename
- return only entries matching filename (substring)
-
- - filetype
- return only entries matching filetype/mimetype (substring)
-
- - start
- start at record (default 0)
-
- - records
- number of records to return or 0 for unlimited
-
-
-
-Example:
-
-curl -u mychannel:mypassword https://xyz.macgirvin.com/api/z/1.0/files -d filetype=multipart/mixed
-
-
-Returns:
-[code nowrap]
- {
-
- "success": true,
- "results": [
- {
- "id": "1",
- "aid": "1",
- "uid": "2",
- "hash": "44ee8b2a1a7f36dea07b93b7747a2383a1bc0fdd08339e8928bfcbe45f65d939",
- "filename": "Profile Photos",
- "filetype": "multipart/mixed",
- "filesize": "0",
- "revision": "0",
- "folder": "",
- "os_storage": "1",
- "is_dir": "1",
- "is_photo": "0",
- "flags": "0",
- "created": "2016-01-02 21:51:17",
- "edited": "2016-01-02 21:51:17",
- "allow_cid": "",
- "allow_gid": "",
- "deny_cid": "",
- "deny_gid": ""
- },
- {
- "id": "12",
- "aid": "1",
- "uid": "2",
- "hash": "71883f1fc64af33889229cbc79c5a056deeec5fc277d765f182f19073e1b2998",
- "filename": "Cover Photos",
- "filetype": "multipart/mixed",
- "filesize": "0",
- "revision": "0",
- "folder": "",
- "os_storage": "1",
- "is_dir": "1",
- "is_photo": "0",
- "flags": "0",
- "created": "2016-01-15 00:24:33",
- "edited": "2016-01-15 00:24:33",
- "allow_cid": "",
- "allow_gid": "",
- "deny_cid": "",
- "deny_gid": ""
- },
- {
- "id": "16",
- "aid": "1",
- "uid": "2",
- "hash": "f48f7ec3278499d1dd86b72c3207beaaf4717b07df5cc9b373f14d7aad2e1bcd",
- "filename": "2016-01",
- "filetype": "multipart/mixed",
- "filesize": "0",
- "revision": "0",
- "folder": "",
- "os_storage": "1",
- "is_dir": "1",
- "is_photo": "0",
- "flags": "0",
- "created": "2016-01-22 03:24:55",
- "edited": "2016-01-22 03:26:57",
- "allow_cid": "",
- "allow_gid": "",
- "deny_cid": "",
- "deny_gid": ""
- }
- ]
- }
-[/code]
-
-
-
-[h3]filemeta[/h3]
-
-Export file metadata for any uploaded file
-
-
-[h3]filedata[/h3]
-
-
-Provides the ability to download a file from cloud storage in chunks
-
-GET /api/z/1.0/filedata
-
-
-Required:
-
- - file_id
- attach.hash of desired file ('begins with' match)
-
-
-Optional:
-
- - start
- starting byte of returned data in file (counting from 0)
-
- - length
- length (prior to base64 encoding) of chunk to download
-
-
-Returns:
-
- attach (DB) structure with base64 encoded 'content' comprised of the desired chunk
-
-
-
-Example:
-
- https://xyz.macgirvin.com/api/z/1.0/filedata?f=&file_id=9f5217770fd&start=0&length=48
-
-Returns:
-[code nowrap]
- {
-
- "attach": {
- "id": "107",
- "aid": "1",
- "uid": "2",
- "hash": "9f5217770fd55d563bd77f84d534d8e119a187514bbd391714626cd9c0e60207",
- "creator": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
- "filename": "pcxtopbm.c",
- "filetype": "application/octet-stream",
- "filesize": "3934",
- "revision": "0",
- "folder": "",
- "flags": "0",
- "is_dir": "0",
- "is_photo": "0",
- "os_storage": "1",
- "os_path": "",
- "display_path": "",
- "content": "LyogcGN4dG9wYm0uYyAtIGNvbnZlcnQgUEMgcGFpbnRicnVzaCAoLnBjeCkgZmls",
- "created": "2016-07-24 23:13:01",
- "edited": "2016-07-24 23:13:01",
- "allow_cid": "",
- "allow_gid": "",
- "deny_cid": "",
- "deny_gid": "",
- "start": 0,
- "length": 48
- }
-
- }
-[/code]
-
-[h3]file/export[/h3]
-
-
-[h3]file[/h3]
-
-
-[h3]albums[/h3]
-
-
-Description: list photo albums
-
-GET /api/z/1.0/albums
-
-
-Output:
-
- text - textual name
-
- total - number of photos in this album
-
- url - web URL
-
- urlencode - textual name, urlencoded
-
- bin2hex - textual name using bin2hex (which is used in the web URL link)
-
-
-Example:
-
-[code nowrap]
- {
-
- "success": true,
- "albums": [
- {
- "text": "/",
- "total": "2",
- "url": "https://xyz.macgirvin.com/photos/hubzilla/album/",
- "urlencode": "",
- "bin2hex": ""
- },
- {
- "text": "2016-01",
- "total": "6",
- "url": "https://xyz.macgirvin.com/photos/hubzilla/album/323031362d3031",
- "urlencode": "2016-01",
- "bin2hex": "323031362d3031"
- },
- {
- "text": "2016-02",
- "total": "7",
- "url": "https://xyz.macgirvin.com/photos/hubzilla/album/323031362d3032",
- "urlencode": "2016-02",
- "bin2hex": "323031362d3032"
- },
- {
- "text": "Cover Photos",
- "total": "5",
- "url": "https://xyz.macgirvin.com/photos/hubzilla/album/436f7665722050686f746f73",
- "urlencode": "Cover+Photos",
- "bin2hex": "436f7665722050686f746f73"
- },
- {
- "text": "Profile Photos",
- "total": "26",
- "url": "https://xyz.macgirvin.com/photos/hubzilla/album/50726f66696c652050686f746f73",
- "urlencode": "Profile+Photos",
- "bin2hex": "50726f66696c652050686f746f73"
- }
- ]
-
- }
-[/code]
-
-
-[h3]photos[/h3]
-
-
-list photo metadata
-
-
-[h3]photo[/h3]
-
-
-
-[h3]group[/h3]
-
-
-[code]GET /api/z/1.0/group[/code]
-
-Description: list privacy groups
-
-Returns: DB tables of all privacy groups.
-
-To use with API group_members, provide either 'group_id' from the id element returned in this call, or 'group_name' from the gname returned in this call.
-
-[code nowrap]
- [
-
- {
- "id": "1",
- "hash": "966c946394f3e2627bbb8a55026b5725e582407098415c02f85232de3f3fde76Friends",
- "uid": "2",
- "visible": "0",
- "deleted": "0",
- "gname": "Friends"
- },
- {
- "id": "2",
- "hash": "852ebc17f8c3ed4866f2162e384ded0f9b9d1048f93822c0c84196745f6eec66Family",
- "uid": "2",
- "visible": "1",
- "deleted": "0",
- "gname": "Family"
- },
- {
- "id": "3",
- "hash": "cc3cb5a7f9818effd7c7c80a58b09a189b62efa698a74319117babe33ee30ab9Co-workers",
- "uid": "2",
- "visible": "0",
- "deleted": "0",
- "gname": "Co-workers"
- }
- ]
-[/code]
-[h3]group_members[/h3]
-
-
-[code]GET /api/z/1.0/group_members[/code]
-
-Required:
-
-group_id or group_name
-
-
-Returns:
-
-group_member+abook+xchan (DB join) for each member of the privacy group
-
-[code nowrap]
- [
-
- {
- "id": "1",
- "uid": "2",
- "gid": "1",
- "xchan": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
- "abook_id": "2",
- "abook_account": "1",
- "abook_channel": "2",
- "abook_xchan": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
- "abook_my_perms": "218555",
- "abook_their_perms": "0",
- "abook_closeness": "0",
- "abook_created": "2016-01-02 21:16:26",
- "abook_updated": "2016-01-02 21:16:26",
- "abook_connected": "0000-00-00 00:00:00",
- "abook_dob": "0000-00-00 00:00:00",
- "abook_flags": "0",
- "abook_blocked": "0",
- "abook_ignored": "0",
- "abook_hidden": "0",
- "abook_archived": "0",
- "abook_pending": "0",
- "abook_unconnected": "0",
- "abook_self": "1",
- "abook_feed": "0",
- "abook_profile": "",
- "abook_incl": "",
- "abook_excl": "",
- "abook_instance": "",
- "xchan_hash": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
- "xchan_guid": "lql-1VnxtiO4-WF0h72wLX1Fu8szzHDOXgQaTbELwXW77k8AKFfh-hYr70vqMrc3SSvWN-Flrc5HFhRTWB7ICw",
- "xchan_guid_sig": "PafvEL0VpKfxATxlCqDjfOeSIMdmpr3iU7X-Sysa1h5LzDpjSXsjO37tYZL-accb1M5itLlfnW5epkTa5I4flsW21zSY1A2jCuBQUTLLGV7rNyyBy7lgqJUFvAMRx0TfXzP9lcaPqlM9T1tA6jfWOsOmkdzwofGeXBnsjGfjsO2xdGYe6vwjOU0DSavukvzDMnOayB9DekpvDnaNBTxeGLM45Skzr7ZEMcNF7TeXMbnvpfLaALYEKeQs9bGH-UgAG8fBWgzVAzeBfx_XSR1rdixjyiZGP0kq0h35SlmMPcEjliodOBFwMXqpXFB7Ibp4F6o6te2p2ErViJccQVG8VNKB6SbKNXY6bhP5zVcVsJ-vR-p4xXoYJJvzTN7yTDsGAXHOLF4ZrXbo5yi5gFAlIrTLAF2EdWQwxSGyLRWKxG8PrDkzEzX6cJJ0VRcLh5z6OI5QqQNdeghPZbshMFMJSc_ApCPi9_hI4ZfctCIOi3T6bdgTNKryLm5fhy_eqjwLAZTGP-aUBgLZpb1mf2UojBn6Ey9cCyq-0T2RWyk-FcIcbV4qJ-p_8oODqw13Qs5FYkjLr1bGBq82SuolkYrXEwQClxnrfKa4KYc2_eHAXPL01iS9zVnI1ySOCNJshB97Odpooc4wk7Nb2Fo-Q6THU9zuu0uK_-JbK7IIl6go2qA",
- "xchan_pubkey": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA18JB76lyP4zzL/y7BCej\neJnfZIWZNtM3MZvI1zEVMWmmwOS+u/yH8oPwyaDk4Y/tnj8GzMPj1lCGVRcd8EJa\nNrCMd50HODA5EsJtxpsOzRcILYjOcTtIAG1K4LtKqELi9ICAaFp0fNfa+Jf0eCek\nvPusx2/ORhy+o23hFoSMhL86o2gmaiRnmnA3Vz4ZMG92ieJEDMXt9IA1EkIqS4y5\nBPZfVPLD1pv8iivj+dtN1XjwplgjUbtxmU0/Ej808nHppscRIqx/XJ0XZU90oNGw\n/wYoK2EzJlPbRsAkwNqoFrAYlr5HPpn4BJ2ebFYQgWBUraD7HwS5atsQEaxGfO21\nlUP0+lDg9t3CXvudDj0UG1jiEKbVIGA+4aG0GN2DSC5AyRq/GRxqyay5W2vQbAZH\nyvxPGrZFO24I65g3pjhpjEsLqZ4ilTLQoLMs0drCIcRm5RxMUo4s/LMg16lT4cEk\n1qRtk2X0Sb1AMQQ2uRXiVtWz77QHMONEYkf6OW4SHbwcv5umvlv69NYEGfCcbgq0\nAV7U4/BWztUz/SWj4r194CG43I9I8dmaEx9CFA/XMePIAXQUuABfe1QMOR6IxLpq\nTHG1peZgHQKeGz4aSGrhQkZNNoOVNaZoIfcvopxcHDTZLigseEIaPPha4WFYoKPi\nUPbZ5o8gTLc750uzrnb2jwcCAwEAAQ==\n-----END PUBLIC KEY-----\n",
- "xchan_photo_mimetype": "image/png",
- "xchan_photo_l": "https://xyz.macgirvin.com/photo/profile/l/2",
- "xchan_photo_m": "https://xyz.macgirvin.com/photo/profile/m/2",
- "xchan_photo_s": "https://xyz.macgirvin.com/photo/profile/s/2",
- "xchan_addr": "teller@xyz.macgirvin.com",
- "xchan_url": "https://xyz.macgirvin.com/channel/teller",
- "xchan_connurl": "https://xyz.macgirvin.com/poco/teller",
- "xchan_follow": "https://xyz.macgirvin.com/follow?f=&url=%s",
- "xchan_connpage": "",
- "xchan_name": "Teller",
- "xchan_network": "zot",
- "xchan_instance_url": "",
- "xchan_flags": "0",
- "xchan_photo_date": "2016-10-19 01:26:50",
- "xchan_name_date": "2016-01-02 21:16:26",
- "xchan_hidden": "0",
- "xchan_orphan": "0",
- "xchan_censored": "0",
- "xchan_selfcensored": "0",
- "xchan_system": "0",
- "xchan_pubforum": "0",
- "xchan_deleted": "0"
- },
- {
- "id": "12",
- "uid": "2",
- "gid": "1",
- "xchan": "xuSMUYxw1djBB97qXsbrBN1nzJH_gFwQL6pS4zIy8fuusOfBxNlMiVb4h_q5tOEvpE7tYf1EsryjNciMuPIj5w",
- "abook_id": "24",
- "abook_account": "1",
- "abook_channel": "2",
- "abook_xchan": "xuSMUYxw1djBB97qXsbrBN1nzJH_gFwQL6pS4zIy8fuusOfBxNlMiVb4h_q5tOEvpE7tYf1EsryjNciMuPIj5w",
- "abook_my_perms": "218555",
- "abook_their_perms": "218555",
- "abook_closeness": "80",
- "abook_created": "2016-01-27 00:48:43",
- "abook_updated": "2016-12-04 17:16:58",
- "abook_connected": "2016-12-04 17:16:58",
- "abook_dob": "0001-01-01 00:00:00",
- "abook_flags": "0",
- "abook_blocked": "0",
- "abook_ignored": "0",
- "abook_hidden": "0",
- "abook_archived": "0",
- "abook_pending": "0",
- "abook_unconnected": "0",
- "abook_self": "0",
- "abook_feed": "0",
- "abook_profile": "debb5236efb1626cfbad33ccb49892801e5f844aa04bf81f580cfa7d13204819",
- "abook_incl": "",
- "abook_excl": "",
- "abook_instance": "",
- "xchan_hash": "xuSMUYxw1djBB97qXsbrBN1nzJH_gFwQL6pS4zIy8fuusOfBxNlMiVb4h_q5tOEvpE7tYf1EsryjNciMuPIj5w",
- "xchan_guid": "d5EMLlt1tHHZ0dANoA7B5Wq9UgXoWcFS9-gXOkL_AAejcPApoQRyxfHTuu8DoTbUaO-bYmX5HPuWuK9PHyqNmA",
- "xchan_guid_sig": "CVWEMRPtzI1YcHfnnWHTuv3H964OAmSElgUfxMoX6RdQdxNpqb_POirpVuyP8s3W17mVCfO5V9IAjkg5iKcqCk6YcvOD_egmMy-AnM9TC1kKndQHw55CunD82Q8K_xBNSXkSROizcNkKh9DVLjJPFjW1AqtI4njkZ3EMgrWqnbFRM1qPToUoCY9zM3tEMHoAD9YX1zP90wl40LzfN-dtcNWpSBbiz9owou62uzLbN7mrCwKOMlXLjwwGswRnxIsEnb3O-FXOs8hs0mArKe9snq1-BKeD16LyzxgwlpVLElzIJZGEZGtMdIJgeRzKuBvPjsOIpQ1yAkuOpFJ3nGCM-IPOIIjAmyVl5zD3xPVcxxpZlJRn5fG1Y-gnqTgsrEQCA7M6XPWQdrdHU4akZfyUyFJDhv3uM-jon9VzrYTBw68R0WA-1Z8WafEHA4qh5OWAj85lUarwhr7iTiEckH51ypPCPs6VbT6Pw7yMaxfjFOcipashQagx0tfOlDhE5dQANOXKASFtH1J9-CZY2MQdLPQ6u54d5whuHKMGaJ0V68pnmZ2rOn7g344Ah2WCJrm17jj60QsRMorqRFj7GMdPIA1XB8Wrk88MuYOe3Dhyuu6ZWKI7YTWJS690ZVkKUqAiNHqj0W86DtaiPUc_mmGR0fHl4Gksnko3WmCFv9q2X2E",
- "xchan_pubkey": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAoj2xCJktBA8Ww7Hp+ZNL\nrNuQpo8UB/bfvRkIy+yua3xpF1TuXcnAH61kyRz8vXgOu/l2CyxQbIoaGslCV5Sy\n8JKeNXe+IilUdSSEjMIwCPfSPsYnMHsSnHWmPmclvJwEtQUKOZmW5mMuVBvXy7D2\njomFwc69AYphdyys6eQ7Dcn6+FRBiQbyMprZ5lxyVW+O4DuXVNa3ej2ebx0gCJZ4\ntTIlBoKwEey91dY+FyKVFjdwfNczpmL7LgmZXqcVx+MG3mYgibwdVMiXVj5X06cs\nV9hJ5Xi+Aklsv/UWJtjw9FVt7y9TLptnhh4Ra6T/MDmnBBIAkOR7P/X8cRv078MT\nl0IMsP0RJcDEtTLtwHFVtDs6p52KDFqclKWbqmxmxqV3OTPVYtArRGIzgnJi/5ur\nHRr5G6Cif7QY3UowsIOf78Qvy28LwSbdymgBAWwPPKIviXWxGO+9kMWdmPSUQrWy\nK0+7YA9P9fBUFfn9Hc+p8SJQmQ6OAqLwrDGiPSOlGaNrbEqwqLGgIpXwK+lEFcFJ\n3SPOjJRWdR2whlMxvpwX+39+H7dWN3vSa3Al4/Sq7qW8yW2rYwf+eGyp4Z0lRR+8\nJxFMCwZkSw5g14YdlikAPojv5V1c6KuA5ieg8G1hwyONV7A4JHPyEdPt0W0TZi6C\nCOVkPaC3xGrguETZpJfVpwUCAwEAAQ==\n-----END PUBLIC KEY-----\n",
- "xchan_photo_mimetype": "image/png",
- "xchan_photo_l": "https://xyz.macgirvin.com/photo/9da63aa910ea14e1501ee1a749d181a6-4",
- "xchan_photo_m": "https://xyz.macgirvin.com/photo/9da63aa910ea14e1501ee1a749d181a6-5",
- "xchan_photo_s": "https://xyz.macgirvin.com/photo/9da63aa910ea14e1501ee1a749d181a6-6",
- "xchan_addr": "cloner@xyz.macgirvin.com",
- "xchan_url": "http://abc.macgirvin.com/channel/cloner",
- "xchan_connurl": "http://abc.macgirvin.com/poco/cloner",
- "xchan_follow": "https://xyz.macgirvin.com/follow?f=&url=%s",
- "xchan_connpage": "",
- "xchan_name": "Karen",
- "xchan_network": "zot",
- "xchan_instance_url": "",
- "xchan_flags": "0",
- "xchan_photo_date": "2016-03-31 19:59:20",
- "xchan_name_date": "2016-01-26 23:23:42",
- "xchan_hidden": "0",
- "xchan_orphan": "0",
- "xchan_censored": "0",
- "xchan_selfcensored": "0",
- "xchan_system": "0",
- "xchan_pubforum": "0",
- "xchan_deleted": "0"
- }
-
- ]
-[/code]
-
-[h3]xchan[/h3]
-
-
-An xchan is a global location independent channel and is the primary record for a network
-identity. It may refer to channels on other websites, networks, or services.
-
-[code]GET /api/z/1.0/xchan[/code]
-
-Required: one of [ address, hash, guid ] as GET parameters
-
-Returns a portable xchan structure
-
-Example: https://xyz.macgirvin.com/api/z/1.0/xchan?f=&address=mike@macgirvin.com
-
-Returns:
-[code nowrap]
- {
- "hash": "jr54M_y2l5NgHX5wBvP0KqWcAHuW23p1ld-6Vn63_pGTZklrI36LF8vUHMSKJMD8xzzkz7s2xxCx4-BOLNPaVA",
- "guid": "sebQ-IC4rmFn9d9iu17m4BXO-kHuNutWo2ySjeV2SIW1LzksUkss12xVo3m3fykYxN5HMcc7gUZVYv26asx-Pg",
- "guid_sig": "Llenlbl4zHo6-g4sa63MlQmTP5dRCrsPmXHHFmoCHG63BLq5CUZJRLS1vRrrr_MNxr7zob_Ykt_m5xPKe5H0_i4pDj-UdP8dPZqH2fqhhx00kuYL4YUMJ8gRr5eO17vsZQ3XxTcyKewtgeW0j7ytwMp6-hFVUx_Cq08MrXas429ZrjzaEwgTfxGnbgeQYQ0R5EXpHpEmoERnZx77VaEahftmdjAUx9R4YKAp13pGYadJOX5xnLfqofHQD8DyRHWeMJ4G1OfWPSOlXfRayrV_jhnFlZjMU7vOdQwHoCMoR5TFsRsHuzd-qepbvo3pzvQZRWnTNu6oPucgbf94p13QbalYRpBXKOxdTXJrGdESNhGvhtaZnpT9c1QVqC46jdfP0LOX2xrVdbvvG2JMWFv7XJUVjLSk_yjzY6or2VD4V6ztYcjpCi9d_WoNHruoxro_br1YO3KatySxJs-LQ7SOkQI60FpysfbphNyvYMkotwUFI59G08IGKTMu3-GPnV1wp7NOQD1yzJbGGEGSEEysmEP0SO9vnN45kp3MiqbffBGc1r4_YM4e7DPmqOGM94qksOcLOJk1HNESw2dQYWxWQTBXPfOJT6jW9_crGLMEOsZ3Jcss0XS9KzBUA2p_9osvvhUKuKXbNztqH0oZIWlg37FEVsDs_hUwUJpv2Ar09k4",
- "pubkey": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7QCwvuEIwCHjhjbpz3Oc\ntyei/Pz9nDksNbsc44Cm8jxYGMXsTPFXDZYCcCB5rcAhPPdZSlzaPkv4vPVcMIrw\n5cdX0tvbwa3rNTng6uFE7qkt15D3YCTkwF0Y9FVZiZ2Ko+G23QeBt9wqb9dlDN1d\nuPmu9BLYXIT/JXoBwf0vjIPFM9WBi5W/EHGaiuqw7lt0qI7zDGw77yO5yehKE4cu\n7dt3SakrXphL70LGiZh2XGoLg9Gmpz98t+gvPAUEotAJxIUqnoiTA8jlxoiQjeRK\nHlJkwMOGmRNPS33awPos0kcSxAywuBbh2X3aSqUMjcbE4cGJ++/13zoa6RUZRObC\nZnaLYJxqYBh13/N8SfH7d005hecDxWnoYXeYuuMeT3a2hV0J84ztkJX5OoxIwk7S\nWmvBq4+m66usn6LNL+p5IAcs93KbvOxxrjtQrzohBXc6+elfLVSQ1Rr9g5xbgpub\npSc+hvzbB6p0tleDRzwAy9X16NI4DYiTj4nkmVjigNo9v2VPnAle5zSam86eiYLO\nt2u9YRqysMLPKevNdj3CIvst+BaGGQONlQalRdIcq8Lin+BhuX+1TBgqyav4XD9K\nd+JHMb1aBk/rFLI9/f2S3BJ1XqpbjXz7AbYlaCwKiJ836+HS8PmLKxwVOnpLMbfH\nPYM8k83Lip4bEKIyAuf02qkCAwEAAQ==\n-----END PUBLIC KEY-----\n",
- "photo_mimetype": "image/jpeg",
- "photo_l": "https://xyz.macgirvin.com/photo/350b74555c04429148f2e12775f6c403-4",
- "photo_m": "https://xyz.macgirvin.com/photo/350b74555c04429148f2e12775f6c403-5",
- "photo_s": "https://xyz.macgirvin.com/photo/350b74555c04429148f2e12775f6c403-6",
- "address": "mike@macgirvin.com",
- "url": "https://macgirvin.com/channel/mike",
- "connurl": "https://macgirvin.com/poco/mike",
- "follow": "https://macgirvin.com/follow?f=&url=%s",
- "connpage": "https://macgirvin.com/connect/mike",
- "name": "Mike Macgirvin",
- "network": "zot",
- "instance_url": "",
- "flags": "0",
- "photo_date": "2012-12-06 05:06:11",
- "name_date": "2012-12-06 04:59:13",
- "hidden": "1",
- "orphan": "0",
- "censored": "0",
- "selfcensored": "0",
- "system": "0",
- "pubforum": "0",
- "deleted": "0"
- }
-[/code]
-[h3]item/update[/h3]
-
-
-Create or update an item (post, activity, webpage, etc.)
-
-Usage: [code]POST /api/z/1.0/item/update[/code]
-
-Description: item/update posts an item (typically a conversation item or post, but can be any item) using form input.
-
-
-Required:
-
-- body
-
- text/bbcode contents by default.
-
-
-Optional:
-
-- $_FILES['media']
-
- uploaded media file to include with post
-
-- title
-
- title of post/item
-
-- contact_allow
-
- array of xchan.xchan_hash allowed to view this item
-
-- group_allow
-
- array of group.hash allowed to view this item
-
-- contact_deny
-
- array of xchan.xchan_hash not allowed to view this item
-
-- group_deny
-
- array of group.hash not allowed to view this item
-
-- coord
-
- geographic coordinates
-
-- location
-
- freefrom location
-
-- expire
-
- datetime this post will expire or be removed
-
-- mimetype
-
- mimetype if not text/bbcode
-
-- parent
-
- item.id of parent to this post (makes it a comment)
-
-- parent_mid
-
- alternate form of parent using message_id
-
-- remote_xchan
-
- xchan.xchan_hash of this message author if not the channel owner
-
-- consensus
-
- boolean set to true if this is a consensus or voting item (default false)
-
-- nocomment
-
- boolean set to true if comments are to be disabled (default false)
-
-- origin
-
- do not use this without reading the code
-
-- namespace
-
- persistent identity for a remote network or service
-
-- remote_id
-
- message_id of this resource on a remote network or service
-
-- message_id
-
- message_id of this item (leave unset to generate one)
-
-- created
-
- datetime of message creation
-
-- post_id
-
- existing item.id if this is an edit operation
-
-- app
-
- application or network name to display with item
-
-- category
-
- comma separated categories for this item
-
-- webpage
-
- item.page_type if not 0
-
-- pagetitle
-
- for webpage and design elements, the 'page name'
-
-- layout_mid
-
- item.mid of layout for this design element
-
-- plink
-
- permalink for this item if different than the default
-
-- verb
-
- activitystream verb for this item/activity
-
-- obj_type
-
- activitystream object type for this item/activity
-
-
-
-Example:
-
- curl -u mychannel:mypassword https://xyz.macgirvin.com/api/z/1.0/item/update -d body="hello world"
-
-
-Returns:
-
-[code nowrap]
- {
-
- "success": true,
- "item_id": "2245",
- "item": {
- "id": "2245",
- "mid": "14135cdecf6b8e3891224e4391748722114da6668eebbcb56fe4667b60b88249@xyz.macgirvin.com",
- "aid": "1",
- "uid": "2",
- "parent": "2245",
- "parent_mid": "14135cdecf6b8e3891224e4391748722114da6668eebbcb56fe4667b60b88249@xyz.macgirvin.com",
- "thr_parent": "14135cdecf6b8e3891224e4391748722114da6668eebbcb56fe4667b60b88249@xyz.macgirvin.com",
- "created": "2016-12-03 20:00:12",
- "edited": "2016-12-03 20:00:12",
- "expires": "0001-01-01 00:00:00",
- "commented": "2016-12-03 20:00:12",
- "received": "2016-12-03 20:00:12",
- "changed": "2016-12-03 20:00:12",
- "comments_closed": "0001-01-01 00:00:00",
- "owner_xchan": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
- "author_xchan": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
- "source_xchan": "",
- "mimetype": "text/bbcode",
- "title": "",
- "body": "hello world",
- "html": "",
- "app": "",
- "lang": "",
- "revision": "0",
- "verb": "http://activitystrea.ms/schema/1.0/post",
- "obj_type": "http://activitystrea.ms/schema/1.0/note",
- "obj": "",
- "tgt_type": "",
- "target": "",
- "layout_mid": "",
- "postopts": "",
- "route": "",
- "llink": "https://xyz.macgirvin.com/display/14135cdecf6b8e3891224e4391748722114da6668eebbcb56fe4667b60b88249@xyz.macgirvin.com",
- "plink": "https://xyz.macgirvin.com/channel/mychannel/?f=&mid=14135cdecf6b8e3891224e4391748722114da6668eebbcb56fe4667b60b88249@xyz.macgirvin.com",
- "resource_id": "",
- "resource_type": "",
- "attach": "",
- "sig": "sa4TOQNfHtV13HDZ1tuQGWNBpZp-nWhT2GMrZEmelXxa_IvEepD2SEsCTWOBqM8OKPJLfNy8_i-ORXjrOIIgAa_aT8cw5vka7Q0C8L9eEb_LegwQ_BtH0CXO5uT30e_8uowkwzh6kmlVg1ntD8QqrGgD5jTET_fMQOIw4gQUBh40GDG9RB4QnPp_MKsgemGrADnRk2vHO7-bR32yQ0JI-8G-eyeqGaaJmIwkHoi0vXsfjZtU7ijSLuKEBWboNjKEDU89-vQ1c5Kh1r0pmjiDk-a5JzZTYShpuhVA-vQgEcADA7wkf4lJZCYNwu3FRwHTvhSMdF0nmyv3aPFglQDky38-SAXZyQSvd7qlABHGCVVDmYrYaiq7Dh4rRENbAUf-UJFHPCVB7NRg34R8HIqmOKq1Su99bIWaoI2zuAQEVma9wLqMoFsluFhxX58KeVtlCZlro7tZ6z619-dthS_fwt0cL_2dZ3QwjG1P36Q4Y4KrCTpntn9ot5osh-HjVQ01h1I9yNCj6XPgYJ8Im3KT_G4hmMDFM7H9RUrYLl2o9XYyiS2nRrf4aJHa0UweBlAY4zcQG34bw2AMGCY53mwsSArf4Hs3rKu5GrGphuwYX0lHa7XEKMglwBWPWHI49q7-oNWr7aWwn1FnfaMfl4cQppCMtKESMNRKm_nb9Dsh5e0",
- "diaspora_meta": "",
- "location": "",
- "coord": "",
- "public_policy": "",
- "comment_policy": "contacts",
- "allow_cid": "",
- "allow_gid": "",
- "deny_cid": "",
- "deny_gid": "",
- "item_restrict": "0",
- "item_flags": "0",
- "item_private": "0",
- "item_origin": "1",
- "item_unseen": "0",
- "item_starred": "0",
- "item_uplink": "0",
- "item_consensus": "0",
- "item_wall": "1",
- "item_thread_top": "1",
- "item_notshown": "0",
- "item_nsfw": "0",
- "item_relay": "0",
- "item_mentionsme": "0",
- "item_nocomment": "0",
- "item_obscured": "0",
- "item_verified": "1",
- "item_retained": "0",
- "item_rss": "0",
- "item_deleted": "0",
- "item_type": "0",
- "item_hidden": "0",
- "item_unpublished": "0",
- "item_delayed": "0",
- "item_pending_remove": "0",
- "item_blocked": "0"
- }
-
- }
-[/code]
-[h3]item/full[/h3]
-
-
-Get all data associated with an item
-
-[h3]abook[/h3]
-
-
-Connections
-
-[h3]abconfig[/h3]
-
-
-Connection metadata (such as permissions)
-
-[h3]perm_allowed[/h3]
-
-
-Check a permission for a given xchan
diff --git a/doc/en/developer/attribution.md b/doc/en/developer/attribution.md
new file mode 100644
index 000000000..1c06e0b0d
--- /dev/null
+++ b/doc/en/developer/attribution.md
@@ -0,0 +1,3 @@
+#### Attribution
+
+This Code of Conduct is an adaptation of the [Contributor Covenant](http://contributor-covenant.org/?f=&zid=pepecyb@hub.hubzilla.hu), version 1.4, available at [http://contributor-covenant.org/version/1/4.](http://contributor-covenant.org/version/1/4/?f=&zid=pepecyb@hub.hubzilla.hu) \ No newline at end of file
diff --git a/doc/en/developer/code_of_conduct.md b/doc/en/developer/code_of_conduct.md
new file mode 100644
index 000000000..ecdb9194b
--- /dev/null
+++ b/doc/en/developer/code_of_conduct.md
@@ -0,0 +1,8 @@
+### Code of conduct for contributors
+
+#include doc/en/developer/our_pledge.md;
+#include doc/en/developer/our_standards.md;
+#include doc/en/developer/our_responsibilities.md;
+#include doc/en/developer/scope.md;
+#include doc/en/developer/enforcement.md;
+#include doc/en/developer/attribution.md;
diff --git a/doc/en/developer/coding_style.md b/doc/en/developer/coding_style.md
new file mode 100644
index 000000000..23af95274
--- /dev/null
+++ b/doc/en/developer/coding_style.md
@@ -0,0 +1,12 @@
+### Coding style
+
+In the interest of consistency, we use the following code style. We also accept patches that use other styles, but please try to use a consistent coding style if possible. We will not argue or discuss the merits of this style, and it is irrelevant what project ‘xyz’ uses. This is not project ‘xyz’. This is a baseline to try to keep the code readable now and in the future.
+
+- All comments should be in English.
+- We use Doxygen to create documentation. This has not been used consistently, but it is highly recommended to learn and use it.
+- Indentation is mainly done by tabs with a tab width of 4.
+- String concatenations and operators should be separated by spaces. e.g. `$foo = $bar . ‘abc’;` instead of `$foo=$bar.”abc’;`
+- In general, we use single quotes for string variables and double quotes for SQL statements. ‘Here documents’ should be avoided. Sometimes using strings in double quotes with variable substitution is the most efficient way to create the string. In most cases, you should use single quotes.
+- Use spaces liberally to improve readability. When creating arrays with many elements, a key/value pair is often set per line, which is indented accordingly from the parent line. Lining up the assignment operators requires a little more work, but also increases readability.
+- In general, opening curly brackets are placed on the same line as what the bracket opens. They are the last character in the line. Closing brackets are placed on a separate line.
+- Some functions take arguments in argc/argv style, such as main() in C or function args in Bash or Perl. Urls are split within a module. e.g. for `http://example.com/module/arg1/arg2` $this->argc is 3 (integer) and $this->argv contains: [0] => ‘module’, [1] => ‘arg1’, [2] => ‘arg2’. Only one argument is ever specified. If a naked domain URL is specified, $this->argv[0] is set to ‘home’. \ No newline at end of file
diff --git a/doc/en/developer/covenant.bb b/doc/en/developer/covenant.bb
deleted file mode 100644
index 431cc74e9..000000000
--- a/doc/en/developer/covenant.bb
+++ /dev/null
@@ -1,47 +0,0 @@
-[size=large]Contributor Covenant Code of Conduct[/size]
-
-[h3]Our Pledge[/h3]
-
-In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
-
-[h3]Our Standards[/h3]
-
-Examples of behavior that contributes to creating a positive environment
-include:
-
-[list]
- [*]Using welcoming and inclusive language
- [*]Being respectful of differing viewpoints and experiences
- [*]Gracefully accepting constructive criticism
- [*]Focusing on what is best for the community
- [*]Showing empathy towards other community members
-[/list]
-
-Examples of unacceptable behavior by participants include:
-
-[list]
- [*]The use of sexualized language or imagery and unwelcome sexual attention or advances
- [*]Trolling, insulting/derogatory comments, and personal or political attacks
- [*]Public or private harassment
- [*]Publishing others' private information, such as a physical or electronic address, without explicit permission
- [*]Other conduct which could reasonably be considered inappropriate in a professional setting
-[/list]
-
-[h3]Our Responsibilities[/h3]
-
-Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
-
-[h3]Scope[/h3]
-
-This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
-
-[h3]Enforcement[/h3]
-
-Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at project&#x40;hubzilla.org. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
-
-Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
-
-[h3]Attribution[/h3]
-
-This Code of Conduct is adapted from the [url=http://contributor-covenant.org]Contributor Covenant[/url], version 1.4, available at [url=http://contributor-covenant.org/version/1/4/]http://contributor-covenant.org/version/1/4[/url].
-
diff --git a/doc/en/developer/dev-function-overview.md b/doc/en/developer/dev-function-overview.md
new file mode 100644
index 000000000..1db5ee6c6
--- /dev/null
+++ b/doc/en/developer/dev-function-overview.md
@@ -0,0 +1,49 @@
+### Hubzilla development - some useful basic functions
+
+
+
+* `get_account_id()`
+
+Returns numeric account_id if authenticated or 0. It is possible to be authenticated and not connected to a channel.
+
+* `local_channel()`
+
+Returns authenticated numeric channel_id if authenticated and connected to a channel or 0. Sometimes referred to as $uid in the code.
+
+* `remote_channel()`
+
+Returns authenticated string hash of Red global identifier, if authenticated via remote auth, or an empty string.
+
+* `App::get_observer()`
+
+returns an xchan structure representing the current viewer if authenticated (locally or remotely).
+
+* `get_config($family,$key), get_pconfig($uid,$family,$key)`
+
+Returns the config setting for $family and $key or false if unset.
+
+Deprecated: Use `Zotlabs\Lib\Config::Get` instead.
+
+* `set_config($family,$key,$value), set_pconfig($uid,$family,$key,$value)`
+
+Sets the value of config setting for $family and $key to $value. Returns $value. The config versions operate on system-wide settings. The pconfig versions get/set the values for a specific integer uid (channel_id).
+
+Deprecated: Use `Zotlabs\Lib\Config::Set` instead.
+
+* `dbesc()`
+
+Always escape strings being used in DB queries. This function returns the escaped string. Integer DB parameters should all be proven integers by wrapping with intval()
+
+* `q($sql,$var1...)`
+
+Perform a DB query with the SQL statement $sql. printf style arguments %s and %d are replaced with variable arguments, which should each be appropriately dbesc() or intval(). SELECT queries return an array of results or false if SQL or DB error. Other queries return true if the command was successful or false if it wasn't.
+
+* `t($string)`
+
+Returns the translated variant of $string for the current language or $string (default 'en' language) if the language is unrecognised or a translated version of the string does not exist.
+
+* `x($var), $x($array,$key)`
+
+Shorthand test to see if variable $var is set and is not empty. Tests vary by type. Returns false if $var or $key is not set.
+If variable is set, returns 1 if has 'non-zero' value, otherwise returns 0. -- e.g. x('') or x(0) returns 0;
+
diff --git a/doc/en/developer/dev_beginner.md b/doc/en/developer/dev_beginner.md
new file mode 100644
index 000000000..63b12d97c
--- /dev/null
+++ b/doc/en/developer/dev_beginner.md
@@ -0,0 +1,548 @@
+### You want to contribute code?
+
+**...and don't know how to start to...**
+
+- debug hubzilla (php on the webserver),
+- contribute code to the project,
+- optionally - do it all from inside a virtual machine
+
+This manual was tested for Debian (Wheezy) as virtual machine on Lubuntu (Ubuntu 14.0) as host.
+
+
+
+#### Install a Virtual Machine (KVM)
+
+[Here](https://wiki.debian.org/KVM) the installation guide for Linux Debian.
+The summary:
+
+1. install KVM
+
+```
+# apt-get install qemu-kvm libvirt-bin
+```
+
+2. add yourself to the group libvirt
+```
+# adduser <youruser> libvirt
+```
+
+3. install gui to manage virtual machines
+```
+# apt-get install virt-manager
+```
+
+4. download an operating system to run inside the vm ([mini.iso](http://ftp.nl.debian.org/debian/dists/wheezy/main/installer-amd64/current/images/netboot/mini.iso))
+5. start the virt manager
+- create new virtual machine (click on icon)
+- choose your iso image (just downloaded) as installation source
+- optional: configure the new vm: ram, cpu's,...
+- start virtual machine > result: linux debian starts in a new window.
+6. (optional) avoid network errors after restart of host os
+
+```
+# virsh net-start default
+# virsh net-autostart default
+```
+
+
+
+#### Install Apache Webserver
+
+Open a terminal and make yourself root
+
+```
+su -l
+```
+
+
+Create the standard group for the Apache webserver
+
+```
+groupadd www-data
+```
+
+might exist already
+
+
+```
+usermod -a -G www-data www-data
+```
+
+
+Check if the system is really up to date
+
+```
+apt-get update
+apt-get upgrade
+```
+
+
+Optional restart services after installation
+
+```
+reboot
+```
+
+
+If you restarted, make yourself root
+
+```
+su -l
+```
+
+
+Install Apache:
+```
+apt-get install apache2 apache2-doc apache2-utils
+```
+
+
+Open webbrowser on PC and check [localhost](localhost)
+Should show you a page like "It works"
+
+(Source [http://www.manfred-steger.de/tuts/20-der-eigene-webserver-mit-dem-raspberry-pi#](http://www.manfred-steger.de/tuts/20-der-eigene-webserver-mit-dem-raspberry-pi#))
+
+#### Install PHP, MySQL, phpMyAdmin
+
+##### PHP, MySQL
+
+
+```
+su -l
+apt-get install libapache2-mod-php8.2 php8.2 php-pear php8.2-xcache php8.2-curl php8.2-mcrypt php8.2-xdebug
+apt-get install php8.2-mysql
+apt-get install mysql-server mysql-client
+```
+
+enter and note the mysql passwort
+
+Optional since its already enabled during phpmyadmin setup
+
+```
+phpenmod mcrypt
+```
+
+##### phpMyAdmin
+
+Install php myadmin
+
+```
+apt-get install phpmyadmin
+```
+
+
+Configuring phpmyadmin
+- Select apache2 (hint: use the tab key to select)
+- Configure database for phpmyadmin with dbconfig-common?: Choose Yes
+
+(Source [http://www.manfred-steger.de/tuts/20-der-eigene-webserver-mit-dem-raspberry-pi#](http://www.manfred-steger.de/tuts/20-der-eigene-webserver-mit-dem-raspberry-pi#))
+
+##### Enable rewrite
+
+The default installation of Apache2 comes with mod_rewrite installed. To check whether this is the case, verify the existence of `/etc/apache2/mods-available/rewrite.load`
+
+
+```
+nano /etc/apache2/mods-available/rewrite.load
+```
+
+ (You should find the content: `LoadModule rewrite_module` `/usr/lib/apache2/modules/mod_rewrite.so`)
+To enable and load mod_rewrite, do the rest of steps.
+Create a symbolic link in `/etc/apache2/mods-enabled`
+
+
+```
+cd /var/www
+root@debian /var/www $ a2enmod rewrite
+```
+
+
+Then open up the following file, and replace every occurrence of "`AllowOverride None`" with "`AllowOverride all`".
+
+
+```
+nano /etc/apache2/apache2.conf
+```
+
+or
+
+```
+gedit /etc/apache2/sites-enabled/000-default
+```
+
+
+Finally, restart Apache2.
+
+
+```
+service apache2 restart
+```
+
+##### Test installation
+
+
+```
+cd /var/www
+```
+
+
+create a php file to test the php installation
+```
+nano phpinfo.php
+```
+
+
+Insert into the file:
+
+```
+<?php
+ phpinfo();
+?>
+```
+
+(save CTRL+0, ENTER, CTRL+X)
+
+open webbrowser on PC and try `http://localhost/phpinfo.php` (page shows infos on php)
+
+connect phpMyAdmin with MySQL database
+```
+nano /etc/apache2/apache2.conf
+```
+
+- CTRL+V... to the end of the file
+- Insert at the end of the file: (save CTRL+0, ENTER, CTRL+X)
+```
+Include /etc/phpmyadmin/apache.conf
+```
+
+
+restart apache
+
+```
+/etc/init.d/apache2 restart
+apt-get update
+apt-get upgrade
+reboot
+```
+
+**phpMyAdmin**
+
+open webbrowser on PC and try `http://localhost/phpmyadmin`
+
+(Source [http://www.manfred-steger.de/tuts/20-der-eigene-webserver-mit-dem-raspberry-pi#](http://www.manfred-steger.de/tuts/20-der-eigene-webserver-mit-dem-raspberry-pi#))
+
+##### Create an empty database... that is later used by hubzilla
+
+
+open webbrowser on PC and try `http://localhost/phpmyadmin`
+
+Create an empty database, for example named "red".
+Create a database user, for example "red".
+Grant all rights for the user "red" to the database "red".
+
+Note the access details (hostname, username, password, database name).
+
+##### Fork the project on github
+
+Please follow the instruction in the offiical [ documentation](http://git-scm.com/book/en/v2/GitHub-Contributing-to-a-Project) of git.
+It is a good idea to read the whole manual! Git is different to other version control systems in many ways.
+
+Now you should
+
+- create an account at github.com
+- fork `https://framagit.org/hubzilla/core`
+- fork `https://framagit.org/hubzilla/addons`
+
+
+
+If you not want to use GIT from the command line - there is a usefull Eclipse plugin named ""Eclipse Mylyn to GitHub connector".
+
+#### Install Hubzilla and its Addons
+
+##### Git at your computer / vm
+
+You should have created an account on github and forked the projects befor you procceed.
+
+Delete the directory www
+
+```
+rm -R www/
+```
+
+
+Install git (and optionally git-gui a client gui)
+
+```
+apt-get install git git-gui
+```
+
+##### Download hubzilla and addons
+
+Download the main project hubzilla and hubzilla-addons
+
+```
+git clone https://github.com/yourname/hubzilla www
+cd www/
+git clone https://github.com/yourname/hubzilla-addons addon
+```
+
+
+Make this extra folder
+
+```
+mkdir -p "store/[data]/smarty3"
+```
+
+
+Create .htconfig.php and make it writable by the webserver
+
+```
+touch .htconfig.php
+chmod ou+w .htconfig.php
+```
+
+
+Make user www-data (webserver) is the owner all the project files
+
+```
+cd ..
+chown -R www-data:www-data www/
+```
+
+Add yourself ("surfer" in this example) to the group www-data. Why? Later you want to modify files in eclipse or in another editor.
+
+Then make all files writable by the group www-date you are now a member of.
+
+```
+cd www/
+usermod -G www-data surfer
+chmod -R g+w www/
+```
+
+Restart the computer (or vm)
+
+If you are still not able to modify the project files you can check the members of the group www-data with
+
+```
+cat /etc/group
+```
+
+##### Register yourself as admin
+
+Open `http://localhost` and init the matrix
+
+Befor you register a first user switch off the registration mails.
+Open `/var/www/.htconfig.php`
+and make sure "0" is set in this line
+
+```
+App::$config['system']['verify_email'] = 0;
+```
+
+You should be able to change the file as "yourself" (instead of using root or www-data).
+
+##### Cron and the poller
+
+Important!
+Run the poller to pick up the recent "public" postings of your friends
+Set up a cron job or scheduled task to run the poller once every 5-10
+minutes to pick up the recent "public" postings of your friends
+
+
+```
+crontab -e
+```
+
+
+Add
+
+```
+*/10 * * * * cd /var/www/; /usr/bin/php include/poller.php
+```
+
+
+If you don't know the path to PHP type
+
+```
+which php
+```
+
+
+
+#### Debug the server via eclipse
+
+##### Check the configuration of xdebug
+
+You shoud already have installed xdebug in the steps befor
+
+```
+apt-get install php5-xdebug
+```
+
+
+Configuring Xdebug
+
+Open your terminal and type as root (su -l)
+
+```
+gedit /etc/php5/mods-available/xdebug.ini
+```
+
+
+if the file is empty try this location
+
+```
+gedit /etc/php5/conf.d/xdebug.ini
+```
+
+
+That command should open the text editor gedit with the Xdebug configuration file
+At the end of the file content append the following text
+
+```
+xdebug.remote_enable=on
+xdebug.remote_handler=dbgp
+xdebug.remote_host=localhost
+xdebug.remote_port=9000
+```
+
+Save changes and close the editor.
+In you terminal type to restart the web server.
+
+```
+service apache2 restart
+```
+
+
+
+##### Install Eclipse and start debugging
+
+Install eclipse.
+Start eclipse with default worspace (or as you like)
+
+Install the PHP plugin
+Menu > Help > Install new software...
+Install "PHP Developnent Tools ..."
+
+Optionally - Install the GitHub connector plugin
+Menu > Help > Install new software...
+Install "Eclipse Mylyn to GitHub connector"
+
+Configure the PHP plugin
+Menu > Window > Preferences...
+> General > Webbrowser > Change to "Use external web browser"
+> PHP > Debug > Debug Settings > PHP Debugger > Change to "XDebug"
+
+Create a new PHP project
+Menu > File > New Project > Choose PHP > "PHP Project"
+> Choose Create project at existing location" and "/var/www"
+
+Start debugging
+Open index.php and "Debug as..."
+Choose as Launch URL: "`http://localhost/`"
+
+Expected:
+
+- The web browser starts
+- The debugger will stop at the first php line
+
+
+
+#### Contribute your changes via github
+
+##### Preparations
+
+There is a related page in this docs: [zrl=[baseurl]/help/git_for_non_developers]Git for Non-Developers[/zrl].
+As stated befor it is recommended to read the official documentation [GitHub-Contributing-to-a-Project](http://git-scm.com/book/en/v2/GitHub-Contributing-to-a-Project) of git.
+
+Eclipse has a usefull plugin for GIT: "Eclipse Mylyn to GitHub connector".
+
+Make sure you have set your data
+
+```
+git config --global user.name "Your Name"
+git config --global user.email "your@mail.com"
+```
+
+##### Your first contribution
+
+Create a descriptive topic branch
+
+```
+git checkout -b dev_beginning
+```
+
+
+Make sure your local repository is up-to-date with the main project.
+Add the original repository as a remote named “upstream” if not done yet
+
+```
+git remote add upstream https://framagit.org/hubzilla/core/
+```
+
+
+Fetch the newest work from that remote
+
+```
+git fetch upstream
+git merge upstream/master
+```
+
+
+Hint: You can list the branches
+
+```
+git branch -v
+```
+
+
+Make your changes. In this example it is a new doc file.
+
+Check your modifications
+
+```
+git status
+```
+
+
+Add (stage) the new file
+
+```
+git add doc/dev_beginner.bb
+```
+
+
+Commit the changes to your local branch. This will open an editor to provide a message.
+
+```
+git commit -a
+```
+
+
+Push back up to the same topic branch online
+
+```
+git push
+```
+
+
+Now you can go to your (online) account at github and create the pull request.
+
+##### Following contributions
+
+In case the main devolpers want you to change something.
+Fetch the newest work from the remote upstream/master to be sure you have the latest changes.
+
+```
+git fetch upstream
+git merge upstream/master
+```
+
+Make your changes, test them, commit (to local repository), push (to online repository)
+
+```
+git status
+git commit -a -m "added modification of branch"
+git push
+```
+
diff --git a/doc/en/developer/developer_guide.bb b/doc/en/developer/developer_guide.bb
deleted file mode 100644
index d04cec121..000000000
--- a/doc/en/developer/developer_guide.bb
+++ /dev/null
@@ -1,176 +0,0 @@
-[h3]Who is a $Projectname developer? Should I read this?[/h3]
-
-Anyone who contributes to making $Projectname better is a developer. There are many different and important ways you can contribute to this amazing technology, [i]even if you do not know how to write code[/i]. The software itself is only a part of the $Projectname project. You can contribute by
-[list]
-[*] translating text to your language so that people around the world have the opportunity to use $Projectname
-[*] promoting $Projectname and spreading awareness of the platform through blog posts, articles, and word-of-mouth
-[*] creating artwork and graphics for project assets such as icons and marketing material
-[*] supporting project infrastructure like the project website and demo servers
-[/list]
-[i]Software[/i] developers are of course welcomed; there are so many great ideas to implement and not enough people to make them all a reality! The $Projectname code base is an advanced and mature system, but the platform is still very flexible and responsive to new ideas.
-
-We're pretty relaxed when it comes to developers. We don't have a lot of rules. Some of us are over-worked and if you want to help we're happy to let you help. That said, attention to a few guidelines will make the process smoother and make it easier to work together. All developers are expected to abide by our [zrl=[baseurl]/help/developer/covenant]code of conduct[/zrl]. We have developers from across the globe with different abilities and different cultural backgrounds and different levels of patience. Our primary rule is to respect others. Sometimes this is hard and sometimes we have very different opinions of how things should work, but if everybody makes an effort, we'll get along just fine.
-
-This document will help you get started learning and contributing to $Projectname.
-
-[h3]Versions and Releases[/h3]
-
-$Projectname currently uses a standard version numbering sequence of $x.$y(.$z), for instance '1.12' or '1.12.1'. The first digit is the major version number. Major versions are released "roughly" once per year; often in December.
-
-The second digit is the minor release number. If this number is odd, it is a development version. If the number is even, it is a released version. Minor versions are released (moved from dev to master) typically once per month when development is 'stable', but this is likely to increase. Going forward minor releases will be made somewhere between one and three months; corresponding to a stable code point and when there is general community consensus that the current code base is stable enough to consider a release.
-
-The final digit is an interface or patch designator.
-
-The release process involves changing the version number (by definition the minor version number will be odd, and the minor number will be incremented). Once a year for a major release the major version will be incremented, and the minor number reset to 0.
-
-The release candidate is moved to a new branch; and testing will commence/continue for a period of 1-2 weeks afterward or until any significant issues have been resolved. This branch is usually labelled with RC (release candidate); for instance 1.8RC represents the pending release of version 1.8. At this time, the minor version number on the dev branch is incremented to the next odd number. (For instance 1.9). New development can then take place in the dev branch.
-
-Bug fixes should always be applied to 'dev' and from there merged forward (typically with git cherry-pick) to the RC branch and if necessary applied to the master or official release branch.
-
-At the time a release candidate is produced, the language strings file is frozen until a release is made. Translation work may continue, but all translations should be submitted to 'dev' and merged forward to RC.
-
-Once RC testing is completed, RC is merged to 'master' and the RC version designator removed; resulting in one final checkin to change the version number. The CHANGELOG file should also be updated at or just prior to this time. If there are merge conflicts during this final merge, the merge will be abandoned; and 'git merge -s ours' applied. This results in a replacement of master with the contents of the RC branch. Conflicts often arise with string updates which were made to master after the last release and cannot easily be resolved without hand editing. Since this is a release of tested code, hand editing is discouraged, and the replacement merge strategy should be used instead. It is assumed that RC now contains the most recent well-tested code.
-
-Once the release is live and merged to master, the RC branch may be removed.
-
-Fixes may be made to master after release. Where possible these should be made to dev and 'git cherry-pick' used to merge forward; which preserves the commit info and prevents merge conflicts in the next cycle. Only rarely does a patch only apply to the master branch. If necessary this can be made. If the change is severe, the interface version number should be incremented. This is at the discretion of the community. In any event, a 'git pull' of the master branch should always result in the latest release with any post-release patches applied.
-
-The interface number (the $z in $x.$y.$z) should be incremented in dev whenever a change is made which changes the interfaces or API in incompatible ways so that any external packages (especially addons and API clients) relying on a the current behaviour can discover and change their own interfaces accordingly at the point that it changed.
-
-[h3]Git repository branches[/h3]
-
-There are two official branches of the $Projectname git repo.
-[list]
-[*] The stable version is maintained on the [b]master[/b] branch. The latest commit in this branch is considered to be suitable for production hubs.
-[*] Experimental development occurs on the [b]dev[/b] branch, which is merged into [b]master[/b] when it is deemed tested and stable enough.
-[/list]
-
-[h3]Developer tools and workflows[/h3]
-
-[h4]Hub Snapshots[/h4]
-
-The [url=[baseurl]/help/admin/hub_snapshots]hub snapshots[/url] page provides instructions and scripts for taking complete snapshots of a hub to support switching between consistent and completely known states. This is useful to prevent situations where the content or database schema might be incompatible with the code.
-
-[h3]Translations[/h3]
-
-Our translations are managed through Transifex. If you wish to help out translating $Projectname to another language, sign up on transifex.com, visit [url=https://www.transifex.com/Friendica/hubzilla/]Transifex[/url] and request to join one of the existing language teams or create a new one. Notify one of the core developers when you have a translation update which requires merging, or ask about merging it yourself if you're comfortable with git and PHP. We have a string file called 'messages.po' which is gettext compliant and a handful of email templates, and from there we automatically generate the application's language files.
-
-[h4]Translation Process[/h4]
-
-The strings used in the UI of $Projectname is translated at [url=https://www.transifex.com/Friendica/hubzilla/]Transifex[/url] and then
-included in the git repository at github. If you want to help with translation
-for any language, be it correcting terms or translating $Projectname to a
-currently not supported language, please register an account at transifex.com
-and contact the translation team there.
-
-Translating $Projectname is simple. Just use the online tool at transifex. If you
-don't want to deal with git & co. that is fine, we check the status of the translations
-regularly and import them into the source tree at github so that others can use them.
-
-We do not include every translation from transifex in the source tree to avoid
-a scattered and disturbed overall experience. As an uneducated guess we have a
-lower limit of 50% translated strings before we include the language. This
-limit is judging only by the amount of translated strings under the assumption
-that the most prominent strings for the UI will be translated first by a translation
-team. If you feel your translation useable before this limit,
-please contact us and we will probably include your teams work in the source tree.
-
-If you want to get your work into the source tree yourself, feel free to do so
-and contact us with and question that arises. The process is simple and
-$Projectname ships with all the tools necessary.
-
-The location of the translated files in the source tree is
- /view/LNG-CODE/
-where LNG-CODE is the language code used, e.g. de for German or fr for French.
-For the email templates (the *.tpl files) just place them into the directory
-and you are done. The translated strings come as a "hmessages.po" file from
-Transifex which needs to be translated into the PHP file $Projectname uses. To do
-so, place the file in the directory mentioned above and use the "po2php"
-utility from the util directory of your $Projectname installation.
-
-Assuming you want to convert the German localization which is placed in
-view/de/hmessages.po you would do the following.
-
-1. Navigate at the command prompt to the base directory of your
- $Projectname installation
-
-2. Execute the po2php script, which will place the translation
- in the hstrings.php file that is used by $Projectname.
-
- $> php util/po2php.php view/de/hmessages.po
-
- The output of the script will be placed at view/de/hstrings.php where
- froemdoca os expecting it, so you can test your translation mmediately.
-
-3. Visit your $Projectname page to check if it still works in the language you
- just translated. If not try to find the error, most likely PHP will give
- you a hint in the log/warnings.about the error.
-
- For debugging you can also try to "run" the file with PHP. This should
- not give any output if the file is ok but might give a hint for
- searching the bug in the file.
-
- $> php view/de/hstrings.php
-
-4. commit the two files with a meaningful commit message to your git
- repository, push it to your fork of the $Projectname repository at github and
- issue a pull request for that commit.
-
-[h4]Utilities[/h4]
-
-Additional to the po2php script there are some more utilities for translation
-in the "util" directory of the $Projectname source tree. If you only want to
-translate $Projectname into another language you wont need any of these tools most
-likely but it gives you an idea how the translation process of $Projectname
-works.
-
-For further information see the utils/README file.
-
-[h4]Known Problems[/h4]
-
-* $Projectname uses the language setting of the visitors browser to determain the
- language for the UI. Most of the time this works, but there are some known
- quirks.
-* the early translations are based on the friendica translations, if you
- some rough translations please let us know or fix them at Transifex.
-
-[h3]Licensing[/h3]
-
-All code contributed to the project falls under the MIT license, unless otherwise specified. We will accept third-party code which falls under MIT, BSD and LGPL, but copyleft licensing (GPL, and AGPL) is only permitted in addons. It must be possible to completely remove the GPL (copyleft) code from the main project without breaking anything.
-
-[h3]Coding Style[/h3]
-
-In the interests of consistency we adopt the following code styling. We may accept patches using other styles, but where possible please try to provide a consistent code style. We aren't going to argue or debate the merits of this style, and it is irrelevant what project 'xyz' uses. This is not project 'xyz'. This is a baseline to try and keep the code readable now and in the future.
-[list]
-[*]All comments should be in English.
-[*]We use doxygen to generate documentation. This hasn't been consistently applied, but learning it and using it are highly encouraged.
-[*]Indentation is accomplished primarily with tabs using a tab-width of 4.
-[*]String concatenation and operators should be separated by whitespace. e.g. "$foo = $bar . 'abc';" instead of "$foo=$bar.'abc';"
-[*]Generally speaking, we use single quotes for string variables and double quotes for SQL statements. "Here documents" should be avoided. Sometimes using double quoted strings with variable replacement is the most efficient means of creating the string. In most cases, you should be using single quotes.
-[*]Use whitespace liberally to enhance readability. When creating arrays with many elements, we will often set one key/value pair per line, indented from the parent line appropriately. Lining up the assignment operators takes a bit more work, but also increases readability.
-[*]Generally speaking, opening braces go on the same line as the thing which opens the brace. They are the last character on the line. Closing braces are on a line by themselves.
-[*]Some functions take arguments in argc/argv style like main() in C or function args in bash or Perl. Urls are broken up within a module. e.g, given "http://example.com/module/arg1/arg2", then $this->argc will be 3 (integer) and $this->argv will contain: [0] => 'module', [1] => 'arg1', [2] => 'arg2'. There will always be one argument. If provided a naked domain URL, $this->argv[0] is set to "home".
-[/list]
-
-[h3]File system layout[/h3]
-[table border=0]
-[th]Directory[/th][th]Description[/th][/tr]
-[tr][td]addon[/td][td]optional addons/plugins[/td][/tr]
-[tr][td]boot.php[/td][td]Every process uses this to bootstrap the application structure[/td][/tr]
-[tr][td]doc[/td][td]Help Files[/td][/tr]
-[tr][td]images[/td][td]core required images[/td][/tr]
-[tr][td]include[/td][td]The "model" in MVC - (back-end functions), also contains PHP "executables" for background processing[/td][/tr]
-[tr][td]index.php[/td][td]The front-end controller for web access[/td][/tr]
-[tr][td]install[/td][td]Installation and upgrade files and DB schema[/td][/tr]
-[tr][td]library[/td][td]Third party modules (must be license compatible)[/td][/tr]
-[tr][td]mod[/td][td]Controller modules based on URL pathname (e.g. [url=http://sitename/foo]http://sitename/foo[/url] loads mod/foo.php)[/td][/tr]
-[tr][td]mod/site/[/td][td]site-specific mod overrides, excluded from git[/td][/tr]
-[tr][td]util[/td][td]translation tools, main English string database and other miscellaneous utilities[/td][/tr]
-[tr][td]version.inc[/td][td]contains current version (auto-updated via cron for the master repository and distributed via git)[/td][/tr]
-[tr][td]view[/td][td]theming and language files[/td][/tr]
-[tr][td]view/(css,js,img,php,tpl)[/td][td]default theme files[/td][/tr]
-[tr][td]view/(en,it,es ...)[/td][td]language strings and resources[/td][/tr]
-[tr][td]view/theme/[/td][td]individual named themes containing (css,js,img,php,tpl) over-rides[/td][/tr]
-[/table]
-
-[b][url=[baseurl]/help/developer/unorganized]More information needing re-organization and updating...[/url][/b]
diff --git a/doc/en/developer/developers_guide.md b/doc/en/developer/developers_guide.md
new file mode 100644
index 000000000..0f6ee6e7c
--- /dev/null
+++ b/doc/en/developer/developers_guide.md
@@ -0,0 +1,27 @@
+## Developers Guide
+
+Information for Hubzilla developers
+
+#include doc/en/developer/who_is_a_hubzilla_developer.md;
+#include doc/en/developer/dev_beginner.md;
+#include doc/en/developer/versions.md;
+#include doc/en/developer/git_repository.md;
+#include doc/en/developer/git_for_non_developers.md;
+#include doc/en/developer/tools_workflows.md;
+#include doc/en/developer/doco.md;
+#include doc/en/developer/translations.md;
+#include doc/en/developer/licensing.md;
+#include doc/en/developer/coding_style.md;
+#include doc/en/developer/file_system_layour.md;
+#include doc/en/developer/dev-functions-overview.md;
+#include doc/en/developer/Plugins.md;
+#include doc/en/developer/testing.md;
+#include doc/en/developer/federate.md;
+#include doc/en/developer/code_of_conduct.md;
+#include doc/en/developer/nomad_protocol.md;
+#include doc/en/developer/technical_introductions.md;
+#include doc/en/developer/magic_auth.md;
+#include doc/en/developer/nomad_structures.md;
+#include doc/en/developer/API.md;
+#include doc/en/developer/hooks.md;
+#include doc/en/developer/unorganized.md;
diff --git a/doc/en/developer/doco.md b/doc/en/developer/doco.md
new file mode 100644
index 000000000..f6bab3911
--- /dev/null
+++ b/doc/en/developer/doco.md
@@ -0,0 +1,34 @@
+### Creating Documentation
+
+To contribute documentation, simply put some words in a cunning order, and make their existence known to a developer. You can do this literally anywhere as long as a developer can see it. Once made aware, somebody will check it in for you. You should try to avoid proprietary formats, or locations that require authentication with methods other than Nomad in order to make it easy for a developer to access, but even this is not a strict requirement.
+
+If you wish to contribute directly, that's fine too. To contribute directly, documentation should be in one of the following formats:
+
+- Markdown
+- BBCode
+- HTML
+- Plain Text
+- Other formats are also allowed, but support for the format must be added to mod/help.php first.
+
+
+If editing a plain text file, please keep column width to 80. This is because plain text is used in instances where we may not have a working installation - the installation documentation, for example - and it should be easy to read these from a CLI text editor.
+
+The advantage of Markdown is that it is human readable.
+
+The advantage of BBCode is that it is identity aware.
+
+Therefore, if using BBCode, try to make the most of it:
+
+- Use ZRL links where appropriate to ensure a link to another site retains authentication and keeps identity based documentation working
+- Use baseurl or observer.baseurl tags where appropriate instead of example.com for authenticated viewers.
+- Support non-authenticated users with observer=0 tags. We presently do not do this due to historical oversights. This needs adding everywhere
+
+**Translations**
+
+To translate documentation, or provided documentation in languages other than English:
+
+- Create a directory in doc/ with your two letter country code if it doesn't already exist (eg, doc/de/ for German or doc/fr/ for French)
+- Create a document with the same filename as the English version, but with content in your own language. This allows us to fallback to the English if the translation for a particular page is not provided
+
+To create documentation that has no equivalent file in English, you can create a new file with a name of your choosing - but you'll also need to provide a localised version of the index page (main.bb in English) to make it accessible from the menu.
+
diff --git a/doc/en/developer/enforcement.md b/doc/en/developer/enforcement.md
new file mode 100644
index 000000000..753b786f2
--- /dev/null
+++ b/doc/en/developer/enforcement.md
@@ -0,0 +1,4 @@
+#### Enforcement
+
+Instances of offensive, harassing or otherwise unacceptable behaviour can be reported to the project team at [project@hubzilla.org](mailto:project@hubzilla.org). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is committed to confidentiality towards the person reporting an incident. Further details of specific enforcement policies may be published separately.
+Project supervisors who fail to follow or enforce the Code of Conduct in good faith may face temporary or permanent consequences as determined by other members of the project management team. \ No newline at end of file
diff --git a/doc/en/developer/federate.md b/doc/en/developer/federate.md
new file mode 100644
index 000000000..0bb370c8a
--- /dev/null
+++ b/doc/en/developer/federate.md
@@ -0,0 +1,69 @@
+### Creating protocol federation services
+
+There are three main components to writing federation plugins. These are:
+
+1. Channel discovery and making connections
+2. Sending posts/messages
+3. Receiving posts/messages
+
+In addition, federation drivers must handle
+
+4. differences in privacy policies (and content formats)
+
+#### Making connections
+
+The core application provides channel discovery in the following sequence:
+
+1. Nomad channel discovery
+2. Webfinger (channel@hub) lookup
+ 2.1 RFC7033 webfinger
+ 2.2 XRD based webfinger (old style)
+3. URL discovery (currently only used to discover RSS feeds)
+4. If all of these fail, the network is "unknown" and we are unable to communicate with or connect with the channel. An 'xchan' record *may* still be created **if** there is enough information known to identify a unique channel.
+
+Any of the lookup services may be bound to a plugin and extended. When a channel is discovered, we create an 'xchan' record which is a platform neutral representation of the channel identity. If we need to send information to the channel, a 'hubloc' (hub location) record is also generally required. A 'follow' plugin hook is provided to bypass webfinger and this discovery sequence completely.
+
+The final step in gluing this together is to create an 'abook' record, which attaches an xchan in a relationship to a local channel with a given set of permissions.
+
+For networks which do not support nomadic identity, your plugin must also set "abook_instance" which is a comma-separated list of local URLs that the remote channel is connected with. For instance if your member was connected to my channel clone at https://example.com, the abook_instance for that connection would read 'https://example.com'. If you also connected to my clone at https://abc.example.com, the string would be changed to 'https://example.com,https://abc.example.com'. This allows local channels to differentiate which instance a given remote channel is connected with and avoid delivery failures to those channels from other clone instances.
+
+A federation plugin for a webfinger based system needs only to examine the webfinger or XRD results and identify a protocol stack which can be used to connect or communicate. Then create an xchan record with the given 'xchan_network' type and a hubloc record with the same 'hubloc_network' with the information given. Currently the plugin will need to create the entire record, but in the future this will be extended so that the plugin only need identify a network name and the record will be populated with all other known values.
+
+An xchan record is always required in order to connect. To connect, create an abook record with the desired permissions.
+
+Additional information that your plugin requires for communication can be stored in the xconfig table and/or abconfig table if there is no convenient or appropriate table column in the xchan or hubloc tables.
+
+When a connection is made, we generally call the notifier (include/notifier.php) to send a message to the remote channel. This is bound to the hook 'permissions_create'. Your plugin will need to handle this in order to send a "follow" or "make friends" message to the other network.
+
+Notes: The first stage Nomad lookup will be replaced with a webfinger lookup. This work is in progress. A separate lookup was required initially as webfinger does not allow non-SSL connections. We will provide non-SSL Nomad lookups (usually test and development sites) via the "old" XRD based webfinger to avoid this limitation.
+
+The core application will attempt to create xchan records for projects identified as members of the "open web"; currently Hubzilla, Friendica, Diaspora, GNU-Social and Pump.io. This is so that comments can be passed amongst project sites and the network correctly identified. A federation plugin is required to fully federate with other networks, but comments may be passed to sites without such a plugin installed so that there are no unexplained holes in conversations.
+
+The core application must also provide signing ability for Diaspora comments since they require a special signing format and must be signed by the comment author regardless of whether that channel federates with Diaspora. The owner of the conversation may federate with Diaspora so the comments must be signed. This is unfortunate but necessary.
+
+#### Sending Messages
+
+Whenever any message is sent (with the sole exception of directory communications), we invoke the notifier (include/notifier.php), and pass it the type of message and generally an identifier to lookup the information being sent from the database (items or conversational things, private mail, permissions updates, etc.).
+
+The notifier has several hooks which may be used by plugins in different ways, depending on how their delivery loop works. For different message types and complex delivery situations you may need to tie into multiple hooks. The 'permissions_create' hook was mentioned in the first section. There is also a 'permissions_update' message if permissions have changed and the other end of the link needs to be advised. Few services will provide or handle this (as their permissions are static), but it is also used for instance to send profile and profile photo update messages and you may wish to handle this.
+
+The next plugin hook is 'notifier_process'. It is passed an array providing the complete state of the notifier and is called once per notifier invocation. It contains the complete list of recipients (with xchan_network set for each).
+
+There is also 'notifier_hub' which like 'notifier_process' is passed the complete state of the notifier, but the difference is that it is called for each individual hub or distinct URL delivery and may be matched on the hubloc_network type. Hub delivery is much more efficient than recipient delivery but may not be suitable for all protocol stacks.
+
+
+Your plugin will be required to understand the message state and recipients and translate the sent item to the desired format. You will also be required to check privacy and block communication to anybody but the intended recipients - *if* it is a private communication. The plugin will often at this point stick the message into the queue and return the queue id to the notifier.
+
+
+Queue handlers exist already for simple posted data. If you create a queue entry with 'post' type we'll open an HTTP POST request and post the data provided and acknowledge success or failure. You can create other forms of communication by providing a different outq_driver type and handling the processing of queue requests yourself. Delivery reporting is available if you wish to acknowledge different error conditions, or anything beyond success/failure. Advanced delivery reporting will also require a custom queue type. The basic 'post' type only deals with success (communication successful with the remote site) and failure.
+
+​
+
+#### Receiving Messages
+
+
+Receiving messages from the remote network will probably require a 'receive' endpoint or module dedicated to your network communication protocol. This is a URL route that your plugin may need to register with the'module_loaded' hook. You module will then take responsibility for importing any data which arrives at that endpoint and translating it to the format required for this project and storing the resulting data. The basic structure we use is an extensible activitystream item but with slightly different field names and several optional fields. It can be easily mapped to an activitystream. Additional data can be stored in the "iconfig" table. item_store() and item_store_update() are generally used to store the data and send appropriate notifications. Similiar facilities are available for private mail and profile information.
+
+
+
+
diff --git a/doc/en/developer/file_system_layout.md b/doc/en/developer/file_system_layout.md
new file mode 100644
index 000000000..63f42f0fc
--- /dev/null
+++ b/doc/en/developer/file_system_layout.md
@@ -0,0 +1,20 @@
+### File system layout
+
+| Directory | Description |
+| ------------------------- | ------------------------------------------------------------ |
+| addon | Optional addons/plugins |
+| boot.php | Each process uses this to boot the application structure |
+| doc | Help files |
+| images | required images |
+| include | The ‘model’ in MVC - (back-end functions), also contains PHP ‘executables’ for background processing |
+| index.php | The front-end controller for web access |
+| install | Installation and upgrade files and DB schema |
+| library | Third-party modules (must be licence-compatible) |
+| mod | Control modules based on URL path names (e.g. http://sitename/foo loads mod/foo.php) |
+| mod/site/ | Site-specific mod overrides that are excluded from Git |
+| util | Translation tools, main database for English strings and other various utilities |
+| version.inc | contains the current version (which is automatically updated via cron for the main repository and distributed via git) |
+| view | Theme and language files |
+| view/(css,js,img,php,tpl) | Standard theme files |
+| view/(en,it,es ...) | Language strings and resources |
+| view/theme/ | Single named themes that contain (css,js,img,php,tpl) overrides | \ No newline at end of file
diff --git a/doc/en/developer/git_for_non_developers.md b/doc/en/developer/git_for_non_developers.md
new file mode 100644
index 000000000..c944ec383
--- /dev/null
+++ b/doc/en/developer/git_for_non_developers.md
@@ -0,0 +1,100 @@
+### Git For Non-Developers
+
+So you're handling a translation, or you're contributing to a theme, and every time you make a pull request you have to talk to one of the developers before your changes can be merged in?
+
+Chances are, you just haven't found a quick how-to explaining how to keep things in sync on your end. It's really very easy.
+
+After you've created a fork of the repo (just click "fork" at github), you need to clone your own copy.
+
+For the sake of examples, we'll assume you're working on a theme called redexample (which does not exist).
+
+
+```
+git clone https://github.com/username/red.git
+```
+
+
+Once you've done that, cd into the directory, and add an upstream.
+
+
+```
+cd red
+git remote add upstream https://framagit.org/hubzilla/core/
+```
+
+
+From now on, you can pull upstream changes with the command
+
+```
+git fetch upstream
+```
+
+
+Before your changes can be merged automatically, you will often need to merge upstream changes.
+
+
+```
+git merge upstream/master
+```
+
+
+You should always merge upstream before pushing any changes, and *must* merge upstream with any pull requests to make them automatically mergeable.
+
+99% of the time, this will all go well. The only time it won't is if somebody else has been editing the same files as you - and often, only if they have been editing the same lines of the same files. If that happens, that would be a good time to request help until you get the hang of handling your own merge conflicts.
+
+Then you just need to add your changes
+```
+git add view/theme/redexample/
+```
+
+
+This will add all the files in view/theme/redexample and any subdirectories. If your particular files are mixed throughout the code, you should add one at a time. Try not to do git add -a, as this will add everything, including temporary files (we mostly, but not always catch those with a .gitignore) and any local changes you have, but did not intend to commit.
+
+Once you have added all the files you have changed, you need to commit them.
+```
+git commit
+```
+
+
+This will open up an editor where you can describe the changes you have made. Save this file, and exit the editor.
+
+Finally, push the changes to your own git
+
+```
+git push
+```
+
+
+And that's it, your repo is up to date!
+
+All you need to do now is actually create the pull request. There are two ways to do this.
+
+The easy way, if you're using Github is to simply click the green button at the top of your own copy of the repository, enter a description of the changes, and click 'create pull request'. The
+main repository, themes, and addons all have their main branch at Github, so this method can be used most of the time.
+
+Most people can stop here.
+
+Some projects in the extended RedMatrix ecosphere have no Github presence, to pull request these is a bit different - you'll have to create your pull request manually. Fortunately, this isn't
+much harder.
+
+
+```
+git request-pull -p <start> <url>
+```
+
+
+Start is the name of a commit to start at. This must exist upstream. Normally, you just want master.
+
+URL is the URL of *your* repo.
+
+One can also specify `<end>`. This defaults to HEAD.
+
+Example:
+
+```
+git request-pull master https://example.com/project
+```
+
+
+And simply send the output to the project maintainer.
+
diff --git a/doc/en/developer/git_repository.md b/doc/en/developer/git_repository.md
new file mode 100644
index 000000000..b2650b5b2
--- /dev/null
+++ b/doc/en/developer/git_repository.md
@@ -0,0 +1,6 @@
+### Git repository branches
+
+There are two official branches of the Hubzilla Git repository.
+
+- The stable version is maintained in the **master branch**. The latest commit in this branch is considered suitable for production hubs.
+- Experimental development takes place in the **dev branch**, which is transferred to the **master branch** as soon as it is deemed tested and stable enough. \ No newline at end of file
diff --git a/doc/en/developer/hooks.md b/doc/en/developer/hooks.md
new file mode 100644
index 000000000..9a1c0605b
--- /dev/null
+++ b/doc/en/developer/hooks.md
@@ -0,0 +1,458 @@
+### Hooks
+
+Hooks allow plugins/addons to ‘hook’ into the code in many places and change the behaviour or otherwise perform independent actions when an activity takes place or certain data structures are accessed. There are many hooks that allow you to hook into the software at almost any point and do something other than what is intended by default. Two variables are passed to these hooks. The first is the app structure, which contains details about the overall state of the page request as we build the resulting page. The second is unique to the specific hook being called and provides specific details about what is happening in the software at the time the hook is called.
+
+[Created index of all hooks and the files they call](https://hub.hubzilla.hu/help/hooks)
+
+[module_mod_aftercontent](https://hub.hubzilla.hu/help/hook/module_mod_aftercontent) General hook for each module, executed after mod_content(). Replace ‘module’ with the name of the module, e.g. ‘photos_mod_aftercontent’.
+
+[module_mod_content](https://hub.hubzilla.hu/help/hook/module_mod_content) General hook for any module, executed before mod_content(). Replace ‘module’ with the module name, e.g. ‘photos_mod_content’.
+
+[module_mod_init](https://hub.hubzilla.hu/help/hook/module_mod_init) General hook for any module, executed before mod_init(). Replace ‘module’ with the module name, e.g. ‘photos_mod_init’.
+
+[module_mod_post](https://hub.hubzilla.hu/help/hook/module_mod_post) General hook for any module, executed before mod_post(). Replace ‘module’ with the name of the module, e.g. ‘photos_mod_post’.
+
+[about_hook](https://hub.hubzilla.hu/help/hook/about_hook) Called from the siteinfo page
+
+[accept_follow](https://hub.hubzilla.hu/help/hook/accept_follow) Called when a connection is accepted (friend request)
+
+[account_downgrade](https://hub.hubzilla.hu/help/hook/account_downgrade) Called when an account has expired, indicating a possible downgrade to the ‘basic’ class of service
+
+[account_settings](https://hub.hubzilla.hu/help/hook/account_settings) Called when the account settings form is created
+
+[account_settings_post](https://hub.hubzilla.hu/help/hook/account_settings_post) Called when posting from the account settings form
+
+[activity_filter](https://hub.hubzilla.hu/help/hook/activity_filter) Called when creating the list of filters for the network page
+
+[activity_mapper](https://hub.hubzilla.hu/help/hook/activity_filter) Called when determining the activity type for the transfer.
+
+[activity_decode_mapper](https://hub.hubzilla.hu/help/hook/activity_filter) Called when the activity type for the transfer is determined.
+
+[activity_obj_mapper](https://hub.hubzilla.hu/help/hook/activity_filter) Called when the object type for the transfer is determined.
+
+[activity_obj_decode_mapper](https://hub.hubzilla.hu/help/hook/activity_filter) Is called when the object type for the transfer is determined.
+
+[activity_order](https://hub.hubzilla.hu/help/hook/activity_order) Called when generating the list of order options for the network page
+
+[addon_app_installed_filter](https://hub.hubzilla.hu/help/hook/addon_app_installed_filter) Called when determining whether an addon_app is[installed](https://hub.hubzilla.hu/help/hook/addon_app_installed_filter)
+
+[activity_received](https://hub.hubzilla.hu/help/hook/activity_received) Called when an activity (post, comment, like, etc.) has been received from a Nomad source
+
+[admin_aside](https://hub.hubzilla.hu/help/hook/admin_aside) Is called when the sidebar widget of the administration page is created
+
+[affinity_labels](https://hub.hubzilla.hu/help/hook/affinity_labels) Is used to generate alternative labels for the affinity slider.
+
+[api_perm_is_allowed](https://hub.hubzilla.hu/help/hook/api_perm_is_allowed) Called when perm_is_allowed() is executed by an API call.
+
+[app_destroy](https://hub.hubzilla.hu/help/hook/app_destroy) Called when an app is deleted.
+
+[app_installed_filter](https://hub.hubzilla.hu/help/hook/app_installed_filter) Called when it is determined whether an app is[installed](https://hub.hubzilla.hu/help/hook/app_installed_filter)
+
+[app_menu](https://hub.hubzilla.hu/help/hook/app_menu) Called when the app_menu dropdown is created (may be deprecated)
+
+[attach_delete](https://hub.hubzilla.hu/help/hook/attach_delete) Called when attachments are deleted from the attach table
+
+[atom_author](https://hub.hubzilla.hu/help/hook/atom_author) Called when an author or owner element is created for an Atom ActivityStream feed
+
+[atom_entry](https://hub.hubzilla.hu/help/hook/atom_entry) Called when generating each entry of an Atom ActivityStream feed
+
+[atom_feed](https://hub.hubzilla.hu/help/hook/atom_feed) Called when an Atom ActivityStreams feed is generated
+
+[atom_feed_end](https://hub.hubzilla.hu/help/hook/atom_feed_end) Called when the generation of an Atom ActivityStreams feed is complete
+
+[attach_upload_file](https://hub.hubzilla.hu/help/hook/attach_upload_file) Called when a file is uploaded
+
+[authenticate](https://hub.hubzilla.hu/help/hook/authenticate) Can provide alternative authentication mechanisms
+
+[author_is_pmable](https://hub.hubzilla.hu/help/hook/author_is_pmable) Called from the thread's action menu to determine if we can send a private email to the author of the post
+
+[bb2diaspora](https://hub.hubzilla.hu/help/hook/bb2diaspora) Called when converting bbcode to Markdown
+
+[bbcode](https://hub.hubzilla.hu/help/hook/bbcode) Called at the end of the conversion from bbcode to HTML
+
+[bbcode_filter](https://hub.hubzilla.hu/help/hook/bbcode_filter) Called at the beginning of the conversion from bbcode to HTML
+
+[bb_translate_video](https://hub.hubzilla.hu/help/hook/bb_translate_video) Called when extracting embedded services from bbcode video elements (rarely used)
+
+[build_pagehead](https://hub.hubzilla.hu/help/hook/build_pagehead) Called when the HTML page header is created
+
+[can_comment_on_post](https://hub.hubzilla.hu/help/hook/can_comment_on_post) Called when deciding whether or not to display a comment field for a post
+
+[change_channel](https://hub.hubzilla.hu/help/hook/change_channel) Called when you log in to a channel (either during login or afterwards via the channel manager)
+
+[channel_remove](https://hub.hubzilla.hu/help/hook/channel_remove) Called when a channel is removed
+
+[channel_links](https://hub.hubzilla.hu/help/hook/channel_links) Is called when the link is generated: HTTP header for a channel
+
+[channel_settings](https://hub.hubzilla.hu/help/hook/channel_settings) Called when the channel settings page is displayed
+
+[chat_message](https://hub.hubzilla.hu/help/hook/chat_message) Called to create a chat message.
+
+[chat_post](https://hub.hubzilla.hu/help/hook/chat_post) Called when a chat message has been posted.
+
+[check_account_email](https://hub.hubzilla.hu/help/hook/check_account_email) Checks the email specified during account registration
+
+[check_account_invite](https://hub.hubzilla.hu/help/hook/check_account_invite) Validation of an invitation code when using website invitations
+[check_account_password](https://hub.hubzilla.hu/help/hook/check_account_password) Used to check account passwords (minimum length, inclusion of character sets, etc.)
+[check_channelallowed](https://hub.hubzilla.hu/help/hook/check_channelallowed) Used to override or bypass black and white channel block lists.
+
+[check_siteallowed](https://hub.hubzilla.hu/help/hook/check_siteallowed) Is used to override or bypass the black/white block lists for websites.
+
+[collect_public_recipients](https://hub.hubzilla.hu/help/hook/collect_public_recipients) Used to create a list of recipients to send a public message to.
+
+[comment_buttons](https://hub.hubzilla.hu/help/hook/comment_buttons) Called when the comment edit buttons are displayed.
+
+[comments_are_now_closed](https://hub.hubzilla.hu/help/hook/comments_are_now_closed) Called when deciding whether or not to display a comment box for a post
+
+[connect_premium](https://hub.hubzilla.hu/help/hook/connect_premium) Called when a connection to a premium channel is established
+
+[connection_remove](https://hub.hubzilla.hu/help/hook/connection_remove) Called when a connection is deleted/removed
+
+[connector_settings](https://hub.hubzilla.hu/help/hook/connector_settings) Called when the page with the features/addon settings is called up
+
+[construct_page](https://hub.hubzilla.hu/help/hook/construct_page) General hook for providing content for specific page areas. Is called when the Comanche page is created.
+
+[contact_block_end](https://hub.hubzilla.hu/help/hook/contact_block_end) Called when the ‘Connections’ widget is created in the sidebar
+
+[contact_edit](https://hub.hubzilla.hu/help/hook/contact_edit) Called when editing a connection via connedit
+
+[contact_edit_post](https://hub.hubzilla.hu/help/hook/contact_edit_post) Is called when a post is sent to connedit
+[contact_selection_options](https://hub.hubzilla.hu/help/hook/contact_select_options) Deprecated/unused
+
+[content_security_policy](https://hub.hubzilla.hu/help/hook/content_security_policy) Called before the Content-Security-Policy header is output
+
+[conversation_start](https://hub.hubzilla.hu/help/hook/conversation_start) Called at the beginning of the rendering of a conversation (message or message collection or stream)
+
+[cover_photo_content_end](https://hub.hubzilla.hu/help/hook/cover_photo_content_end) Called after a cover photo has been uploaded
+
+[create_identity](https://hub.hubzilla.hu/help/hook/create_identity) Called when a channel is created
+
+[cron](https://hub.hubzilla.hu/help/hook/cron) Called when a scheduled task (poller) is executed
+
+[cron_daily](https://hub.hubzilla.hu/help/hook/cron_daily) Called when daily scheduled tasks are executed
+
+[cron_weekly](https://hub.hubzilla.hu/help/hook/cron_weekly) Called when weekly scheduled tasks are executed
+
+[crypto_methods](https://hub.hubzilla.hu/help/hook/crypto_methods) Called when a list of crypto algorithms is created in the locally preferred order
+
+[daemon_addon](https://hub.hubzilla.hu/help/hook/daemon_addon) Called when the extensible background daemon is called
+
+[daemon_master_release](https://hub.hubzilla.hu/help/hook/daemon_master_release) Called at the beginning of the processing of \Zotlabs\Daemon\Master::Release()
+
+[directory_item](https://hub.hubzilla.hu/help/hook/directory_item) Called when creating a directory listing for display
+
+[discover_channel_webfinger](https://hub.hubzilla.hu/help/hook/discover_channel_webfinger) Called when a webfinger lookup is performed
+
+[display_item](https://hub.hubzilla.hu/help/hook/display_item) Called for each element that is displayed in a conversation thread
+
+[display_settings](https://hub.hubzilla.hu/help/hook/display_settings) Called by the settings module when the ‘display settings’ section is displayed
+
+[display_settings_post](https://hub.hubzilla.hu/help/hook/display_settings_post) Called when a post from the ‘display settings’ form of the settings module is displayed
+
+[donate_contributors](https://hub.hubzilla.hu/help/hook/donate_contributors) Called by the ‘donate’ addon when a list of donation recipients is created
+
+[donate_plugin](https://hub.hubzilla.hu/help/hook/donate_plugin) is called by the ‘donate’ addon
+
+[donate_sponsors](https://hub.hubzilla.hu/help/hook/donate_sponsors) Called by the ‘donate’ addon
+
+[dreport_is_storable](https://hub.hubzilla.hu/help/hook/dreport_is_storable) is called before saving a Dreport record to determine if it should be saved
+
+[dreport_process](https://hub.hubzilla.hu/help/hook/dreport_process) is called for each valid delivery report
+
+[dropdown_extras](https://hub.hubzilla.hu/help/hook/dropdown_extras) Add additional items to the dropdown menu when item/threads are displayed.
+
+[drop_item](https://hub.hubzilla.hu/help/hook/drop_item) is called when an ‘item’ is removed
+
+[encode_object](https://hub.hubzilla.hu/help/hook/encode_object) is called when an object is encoded for transmission.
+
+[enotify](https://hub.hubzilla.hu/help/hook/enotify) is called before each notification
+
+[enotify_mail](https://hub.hubzilla.hu/help/hook/enotify_mail) is called when a notification email is sent
+
+[enotify_store](https://hub.hubzilla.hu/help/hook/enotify_store) is called when a notification data record is saved
+
+[enotify_store_end](https://hub.hubzilla.hu/help/hook/enotify_store_end) is called after a notification record has been saved
+
+[event_created](https://hub.hubzilla.hu/help/hook/event_created) is called when an event record is created
+
+[event_store_event](https://hub.hubzilla.hu/help/hook/event_store_event) is called when an event record is created or updated
+
+[event_updated](https://hub.hubzilla.hu/help/hook/event_updated) is called when an event record is changed
+
+[externals_url_select](https://hub.hubzilla.hu/help/hook/externals_url_select) is called when a list of random websites from which to retrieve public posts is created
+
+[feature_enabled](https://hub.hubzilla.hu/help/hook/feature_enabled) is called when ‘feature_enabled()’ is used
+
+[feature_settings](https://hub.hubzilla.hu/help/hook/feature_settings) is called from the settings page when visiting ‘addon/feature settings’
+
+[feature_settings_post](https://hub.hubzilla.hu/help/hook/feature_settings_post) is called from the settings page when posting from ‘addon/feature settings’
+
+[fetch_and_store](https://hub.hubzilla.hu/help/hook/fetch_and_store) is called to enable filtering of ‘decrypted’ elements before saving.
+
+[file_thumbnail](https://hub.hubzilla.hu/help/hook/file_thumbnail) is called when creating thumbnails for the cloud page in ‘show tiles’ mode
+
+[follow](https://hub.hubzilla.hu/help/hook/follow) is called when a follow operation takes place
+
+[follow_from_feed](https://hub.hubzilla.hu/help/hook/follow_from_feed) is called when a follow operation takes place in an RSS feed
+
+[follow_allow](https://hub.hubzilla.hu/help/hook/follow_allow) is called before the results of a follow operation are saved
+
+[gender_selector](https://hub.hubzilla.hu/help/hook/gender_selector) is called when the ‘Gender’ drop-down list is created (extended profile)
+
+[gender_selector_min](https://hub.hubzilla.hu/help/hook/gender_selector_min) is called when the ‘Gender’ drop-down list is created (normal profile)
+
+[generate_map](https://hub.hubzilla.hu/help/hook/generate_map) is called to generate the HTML code for displaying a location on the map by coordinates
+
+[generate_named_map](https://hub.hubzilla.hu/help/hook/generate_named_map) is called to generate the HTML file for displaying a map location by text
+
+[get_all_api_perms](https://hub.hubzilla.hu/help/hook/get_all_api_perms) Called when the permissions for API uses are retrieved
+
+[get_all_perms](https://hub.hubzilla.hu/help/hook/get_all_perms) is called when get_all_perms() is used
+[get_best_language](https://hub.hubzilla.hu/help/hook/get_best_language) is called when the preferred language for the page is selected
+[get_default_export_sections](https://hub.hubzilla.hu/help/hook/get_default_export_sections) Called to get the default list of function data groups to be exported in identity_basic_export()
+
+[get_features](https://hub.hubzilla.hu/help/hook/get_features) Called when get_features() is called
+
+[get_photo](https://hub.hubzilla.hu/help/hook/get_photo) Called when photo content (except profile photos) is retrieved in mod_photo
+
+[get_profile_photo](https://hub.hubzilla.hu/help/hook/get_profile_photo) Called when the content of the local profile photo is retrieved in mod_photo
+
+[get_role_perms](https://hub.hubzilla.hu/help/hook/get_role_perms) Called when get_role_perms() is called to get permissions for named permission roles
+
+[global_permissions](https://hub.hubzilla.hu/help/hook/global_permissions) Called when the global permissions list is created
+
+[home_content](https://hub.hubzilla.hu/help/hook/home_content) Called by mod_home to replace the content of the home page
+
+[home_init](https://hub.hubzilla.hu/help/hook/home_init) Called by the home_init() function of the home page
+
+[hostxrd](https://hub.hubzilla.hu/help/hook/hostxrd) Called when generating .well-known/hosts-meta for ‘old webfinger’ (used by the Diaspora protocol)
+
+[html2bb_video](https://hub.hubzilla.hu/help/hook/html2bb_video) Called when html2bbcode translation is used to handle embedded media
+
+[html2bbcode](https://hub.hubzilla.hu/help/hook/html2bbcode) Called when using the html2bbcode translation
+
+[identity_basic_export](https://hub.hubzilla.hu/help/hook/identity_basic_export) Called when the basic information of a channel is exported for backup or transfer.
+
+[import_author_xchan](https://hub.hubzilla.hu/help/hook/import_author_xchan) Called when searching for an author of a post with xchan_hash to make sure they have an xchan entry on our website
+
+[import_channel](https://hub.hubzilla.hu/help/hook/import_channel) Called when a channel is imported from a file or API source
+
+[import_directory_profile](https://hub.hubzilla.hu/help/hook/import_directory_profile) Called when processing the delivery of a profile structure from an external source (usually for storage in directories)
+
+[import_xchan](https://hub.hubzilla.hu/help/hook/import_xchan) Called when processing the result of zot_finger() to save the result
+
+[item_photo_menu](https://hub.hubzilla.hu/help/hook/item_photo_menu) Called when the list of actions associated with a displayed conversation item is generated
+
+[item_store](https://hub.hubzilla.hu/help/hook/item_store) Called when item_store() stores a record of type item
+
+[item_stored](https://hub.hubzilla.hu/help/hook/item_stored) Called after item_store() has stored a record of type item in the database.
+
+[item_custom](https://hub.hubzilla.hu/help/hook/item_custom) Is called before item_store() saves a data record of the type item (so that addons can process ITEM_TYPE_CUSTOM elements).
+
+[item_store_update](https://hub.hubzilla.hu/help/hook/item_store_update) Called when item_store_update() is called to update a stored item.
+
+[item_stored_update](https://hub.hubzilla.hu/help/hook/item_stored_update) Called after item_store_update() has updated a[stored](https://hub.hubzilla.hu/help/hook/item_stored_update) item.
+
+[item_translate](https://hub.hubzilla.hu/help/hook/item_translate) Called by item_store and item_store_update after the language of the item has been automatically recognised.
+
+[jot_networks](https://hub.hubzilla.hu/help/hook/jot_networks) Called to generate the list of additional post plugins to be activated from the ACL form
+
+[jot_tool](https://hub.hubzilla.hu/help/hook/jot_tool) Obsolete and possibly superfluous. Enables action buttons to be added to the post editor.
+
+[jot_tpl_filter](https://hub.hubzilla.hu/help/hook/jot_tpl_filter) Called to filter template variables before replacing them in jot.tpl.
+
+[jot_header_tpl_filter](https://hub.hubzilla.hu/help/hook/jot_header_tpl_filter) Called to filter template variables before replacing them in jot_header.tpl.
+
+[legal_webbie](https://hub.hubzilla.hu/help/hook/legal_webbie) Called to validate a channel address
+
+[legal_webbie_text](https://hub.hubzilla.hu/help/hook/legal_webbie_text) Provides an explanation of the text/character restrictions for legal_webbie()
+
+[load_pdl](https://hub.hubzilla.hu/help/hook/load_pdl) Called when we load a PDL file or description
+
+[local_dir_update](https://hub.hubzilla.hu/help/hook/local_dir_update) Called when a directory update is processed by a channel on the directory server
+
+[location_move](https://hub.hubzilla.hu/help/hook/location_move) Called when a UNO channel has been notified of a new location (indicating a move and not a clone)
+
+[logged](https://hub.hubzilla.hu/help/hook/logged_in) Called when authentication was successful in any way
+
+[Logger](https://hub.hubzilla.hu/help/hook/logger) Called when an entry is made in the application's log file
+
+[logging_out](https://hub.hubzilla.hu/help/hook/logging_out) Called when logging[out](https://hub.hubzilla.hu/help/hook/logging_out)
+
+[login_hook](https://hub.hubzilla.hu/help/hook/login_hook) Called when the login form is generated
+
+[magic_auth](https://hub.hubzilla.hu/help/hook/magic_auth) Called when processing a magic-auth sequence
+
+[markdown_to_bb](https://hub.hubzilla.hu/help/hook/markdown_to_bb) Called when processing the Markdown conversion
+
+[match_webfinger_location](https://hub.hubzilla.hu/help/hook/match_webfinger_location) Called when processing webfinger requests
+
+[magic_auth_openid_success](https://hub.hubzilla.hu/help/hook/magic_auth_openid_success) Called when a magic-auth was successful due to openid credentials
+
+[magic_auth_success](https://hub.hubzilla.hu/help/hook/magic_auth_success) Called when a magic-auth was successful
+
+[main_slider](https://hub.hubzilla.hu/help/hook/main_slider) Called when the affinity tool is generated
+
+[marital_selector](https://hub.hubzilla.hu/help/hook/marital_selector) Called when the selection list for the drop-down menu of the ‘Marital status’ profile is created (extended profile)
+
+[marital_selector_min](https://hub.hubzilla.hu/help/hook/marital_selector_min) Called when the selection list for the ‘Marital status’ drop-down profile is created (normal profile)
+
+[module_loaded](https://hub.hubzilla.hu/help/hook/module_loaded) Is called when a module has been successfully localised for a URL request on the server.
+
+[mood_verbs](https://hub.hubzilla.hu/help/hook/mood_verbs) Called when the list of moods is created
+[nav](https://hub.hubzilla.hu/help/hook/nav) Called when the navigation bar is created
+
+[network_content_init](https://hub.hubzilla.hu/help/hook/network_content_init) Called when loading the content for the network page
+
+[network_ping](https://hub.hubzilla.hu/help/hook/network_ping) Called when a ping request is made
+[network_to_name](https://hub.hubzilla.hu/help/hook/network_to_name) Deprecated
+
+[notifier_end](https://hub.hubzilla.hu/help/hook/notifier_end) Called when a delivery loop is completed
+
+[notifier_hub](https://hub.hubzilla.hu/help/hook/notifier_hub) Called when a hub has been delivered
+
+[notifier_normal](https://hub.hubzilla.hu/help/hook/notifier_normal) Called when the notifier is called for a ‘normal’ delivery
+
+[notifier_process](https://hub.hubzilla.hu/help/hook/notifier_process) Called when the notifier processes a message/event
+
+[obj_verbs](https://hub.hubzilla.hu/help/hook/obj_verbs) Called when the list of verbs available for the ‘things’ profile is created.
+
+[oembed_action](https://hub.hubzilla.hu/help/hook/oembed_action) Called when deciding whether to filter, block or approve an oembed url
+
+[oembed_probe](https://hub.hubzilla.hu/help/hook/oembed_probe) Called when a search for Oembed content is performed.
+
+[other_encapsulate](https://hub.hubzilla.hu/help/hook/other_encapsulate) Called when encrypting content for which the algorithm is unknown (see also crypto_methods)
+
+[other_unencapsulate](https://hub.hubzilla.hu/help/hook/other_unencapsulate) Called when decrypting content for which the algorithm is unknown (see also crypto_methods)
+
+[page_content_top](https://hub.hubzilla.hu/help/hook/page_content_top) Called when we generate a web page (before calling the module content function)
+
+[page_end](https://hub.hubzilla.hu/help/hook/page_end) Called after we have generated the page content
+
+[page_header](https://hub.hubzilla.hu/help/hook/page_header) Called when the navigation bar is generated
+
+[page_meta](https://hub.hubzilla.hu/help/hook/page_header) Called when generating the metadata in the page header.
+
+[parse_atom](https://hub.hubzilla.hu/help/hook/parse_atom) Called when an Atom/RSS feed element is parsed.
+
+[parse_link](https://hub.hubzilla.hu/help/hook/parse_link) Is called when a URL is queried to generate a post from it
+
+[pdl_selector](https://hub.hubzilla.hu/help/hook/pdl_selector) Called when creating a layout selection in a form
+
+[perm_is_allowed](https://hub.hubzilla.hu/help/hook/perm_is_allowed) Called during perm_is_allowed() to determine whether authorisation is permitted for this channel and observer
+
+[permissions_create](https://hub.hubzilla.hu/help/hook/permissions_create) Called when a book entry (connection) is created
+
+[permissions_update](https://hub.hubzilla.hu/help/hook/permissions_update) Is called when an authorisation update is transferred
+
+[permit_hook](https://hub.hubzilla.hu/help/hook/permit_hook) Called before a registered hook is actually executed to determine whether it should be allowed or blocked
+
+[personal_xrd](https://hub.hubzilla.hu/help/hook/personal_xrd) Called when generating the personal XRD for ‘old webfinger’ (Diaspora)
+
+[photo_post_end](https://hub.hubzilla.hu/help/hook/photo_post_end) Called after a photo has been uploaded
+
+[photo_upload_begin](https://hub.hubzilla.hu/help/hook/photo_upload_begin) Called when an attempt is made to upload a photo
+
+[photo_upload_end](https://hub.hubzilla.hu/help/hook/photo_upload_end) Called when a photo upload has been processed
+
+[photo_upload_file](https://hub.hubzilla.hu/help/hook/photo_upload_file) Called to generate alternative file names for an upload
+
+[photo_upload_form](https://hub.hubzilla.hu/help/hook/photo_upload_form) Called when a photo upload form is generated
+
+[photo_view_filter](https://hub.hubzilla.hu/help/hook/photo_view_filter) Called before the data is passed to the photo_view template
+
+[poke_verbs](https://hub.hubzilla.hu/help/hook/poke_verbs) Called when creating the list of actions for the ‘poke’ module
+
+[post_local](https://hub.hubzilla.hu/help/hook/post_local) Called when an article has been set on this computer via mod/item.php (also via API)
+
+[post_local_end](https://hub.hubzilla.hu/help/hook/post_local_end) Is called when a local post process has been completed
+
+[post_local_start](https://hub.hubzilla.hu/help/hook/post_local_start) Is called when a local post process begins
+[post_mail](https://hub.hubzilla.hu/help/hook/post_mail) Called when a mail message has been created
+
+[post_mail_end](https://hub.hubzilla.hu/help/hook/post_mail_end) Called when a mail message has been delivered
+
+[post_remote](https://hub.hubzilla.hu/help/hook/post_remote) Called when an activity arrives from another location
+
+[post_remote_end](https://hub.hubzilla.hu/help/hook/post_remote_end) Called after a remote post has been processed
+
+[post_remote_update](https://hub.hubzilla.hu/help/hook/post_remote_update) Called when processing a remote post that includes an edit or update
+
+[post_remote_update_end](https://hub.hubzilla.hu/help/hook/post_remote_update_end) Called after processing a remote post that included an edit or update
+
+[prepare_body](https://hub.hubzilla.hu/help/hook/prepare_body) Is called when the HTML code for a displayed conversation object is generated.
+
+[prepare_body_final](https://hub.hubzilla.hu/help/hook/prepare_body_final) Called after the HTML for a displayed conversation item has been generated
+
+[prepare_body_init](https://hub.hubzilla.hu/help/hook/prepare_body_init) Called before the HTML for a displayed conversation element is generated
+
+[privacygroup_extras](https://hub.hubzilla.hu/help/hook/privacygroup_extras) Called before generating the HTML for the privacy group editing options
+
+[privacygroup_extras_delete](https://hub.hubzilla.hu/help/hook/privacygroup_extras_delete) Called after the privacy group has been deleted.
+
+[privacygroup_extras_post](https://hub.hubzilla.hu/help/hook/privacygroup_extras_post) Is called when the form for editing the privacy group is sent.
+
+[proc_run](https://hub.hubzilla.hu/help/hook/proc_run) Called when PHP sub-processes are called
+[process_channel_sync_delivery](https://hub.hubzilla.hu/help/hook/process_channel_sync_delivery) Called when a ‘sync package’ with structure and table updates is received from a channel clone.
+
+[profile_advanced](https://hub.hubzilla.hu/help/hook/profile_advanced) Called when an advanced profile page is generated
+
+[profile_edit](https://hub.hubzilla.hu/help/hook/profile_edit) Called when editing a profile
+
+[profile_photo_content_end](https://hub.hubzilla.hu/help/hook/profile_photo_content_end) Called when a profile photo is changed
+
+[profile_post](https://hub.hubzilla.hu/help/hook/profile_post) Called when an edited profile is posted
+
+[profile_sidebar](https://hub.hubzilla.hu/help/hook/profile_sidebar) Is called up when the ‘channel sidebar’ or the mini profile is created
+
+[profile_sidebar_enter](https://hub.hubzilla.hu/help/hook/profile_sidebar_enter) Called before the ‘channel sidebar’ or mini-profile is created
+
+[queue_deliver](https://hub.hubzilla.hu/help/hook/queue_deliver) Called when a message is delivered in the queue
+
+[register_account](https://hub.hubzilla.hu/help/hook/register_account) Called when an account has been created
+
+[render_location](https://hub.hubzilla.hu/help/hook/render_location) Called to create an inactive inline map
+
+[replace_macros](https://hub.hubzilla.hu/help/hook/replace_macros) Called before the template processor is called
+
+[reverse_magic_auth](https://hub.hubzilla.hu/help/hook/reverse_magic_auth) Called before calling reverse magic auth to send you to your own website so you can authenticate on that website
+
+[settings_account](https://hub.hubzilla.hu/help/hook/settings_account) Called when the account settings form is created
+
+[settings_form](https://hub.hubzilla.hu/help/hook/settings_form) Called when creating the channel settings form
+
+[settings_post](https://hub.hubzilla.hu/help/hook/settings_post) Called when posting from the channel settings form
+
+[sexpref_selector](https://hub.hubzilla.hu/help/hook/sexpref_selector) Called when creating a drop-down menu for sexual preferences (advanced profile)
+
+[sexpref_selector_min](https://hub.hubzilla.hu/help/hook/sexpref_selector_min) Called when a drop-down list of sexual preferences is created (normal profile)
+
+[smilie](https://hub.hubzilla.hu/help/hook/smilie) Called when translating emoticons
+
+[status_editor](https://hub.hubzilla.hu/help/hook/status_editor) Called when the status_editor is created.
+
+[stream_item](https://hub.hubzilla.hu/help/hook/stream_item) Called for each item that is rendered for display via conversation()
+
+[system_app_installed_filter](https://hub.hubzilla.hu/help/hook/system_app_installed_filter) Called when it is determined whether a system app is[installed](https://hub.hubzilla.hu/help/hook/system_app_installed_filter).
+
+[tagged](https://hub.hubzilla.hu/help/hook/tagged) Called when a delivery is processed that results in you being tagged
+
+[thumbnail](https://hub.hubzilla.hu/help/hook/thumbnail) Called when creating thumbnails for the cloud storage tile view
+
+[update_unseen](https://hub.hubzilla.hu/help/hook/update_unseen) Called before automatically tagging programmes loaded in the browser that have been viewed
+
+[validate_channelname](https://hub.hubzilla.hu/help/hook/validate_channelname) Used to validate the names used by a channel
+
+[webfinger](https://hub.hubzilla.hu/help/hook/webfinger) Called when visiting the webfinger service (RFC7033)
+
+[well_known](https://hub.hubzilla.hu/help/hook/well_known) Called when accessing the special ‘.well-known’ site addresses
+
+[wiki_preprocess](https://hub.hubzilla.hu/help/hook/wiki_preprocess) Called before markdown/bcode processors are executed for wiki pages
+
+[zot_best_algorithm](https://hub.hubzilla.hu/help/hook/zot_best_algorithm) Called when negotiating encryption algorithms with remote sites
+
+[zid](https://hub.hubzilla.hu/help/hook/zid) Called when the observer's zid is added to a URL
+
+[zid_init](https://hub.hubzilla.hu/help/hook/zid_init) Called when authenticating a visitor who has used zid
+
+[zot_finger](https://hub.hubzilla.hu/help/hook/zot_finger) Called when a Nomad info packet has been requested (this is our web finger detection mechanism) \ No newline at end of file
diff --git a/doc/en/developer/licensing.md b/doc/en/developer/licensing.md
new file mode 100644
index 000000000..96bf15e85
--- /dev/null
+++ b/doc/en/developer/licensing.md
@@ -0,0 +1,3 @@
+### Licensing
+
+All code contributed to the project is subject to the MIT licence unless otherwise stated. We accept third party code that falls under MIT, BSD and LGPL, but copyleft licences (GPL and AGPL) are only allowed in addons. It must be possible to completely remove the GPL (copyleft) code from the main project without destroying anything. \ No newline at end of file
diff --git a/doc/en/developer/magic_auth.md b/doc/en/developer/magic_auth.md
new file mode 100644
index 000000000..fc9650823
--- /dev/null
+++ b/doc/en/developer/magic_auth.md
@@ -0,0 +1,49 @@
+### Magic Auth
+
+The so-called ‘magic auth’ takes place via a special exchange. On the remote computer, a redirection is made to the Nomad endpoint with special GET parameters.
+
+Endpoint: [https://example.com/post/name](https://example.com/post/name?f=&zid=pepecyb@hub.hubzilla.hu)
+
+where ‘name’ is the left-hand side of the channel webbie, for example ‘mike’ if the webbie is [‘mike@zothub.com’](mailto:mike@zothub.com).
+
+In addition, four parameters are passed:
+
+- auth => the webbie of the person requesting access
+- dest => the desired destination URL (urlencoded)
+- sec => a random string, which is also stored locally for use during the verification phase.
+- version => the Zot revision
+
+When this packet is received, a Nomad message is sent to the auth identity:
+
+```
+ {
+ ‘type’: ‘auth_check’,
+ ‘sender’:{
+ ‘guid’: ‘kgVFf_1_SSbyqH-BNWjWuhAvJ2EhQBTUdw-Q1LwwssAntr8KTBgBSzNVzUm9_RwuDpxI6X8me_QQhZMf7RfjdA’,
+ ‘guid_sig’: "PT9-TApzpm7QtMxC63MjtdK2nUyxNI0tUoWlOYTFGke3kNdtxSzSvDV4uzq_7SSBtlrNnVMAFx2_1FDgyKawmqVtRPmT7QSXrKOL2oPzL8Hu_nnVVTs_0YOLQJJ0GYACOOK- R5874WuXLEept5-KYg0uShifsvhHnxnPIlDM9lWuZ1hSJTrk3NN9Ds6AKpyNRqf3DUdz81- Xvs8I2kj6y5vfFtm-FPKAqu77XP05r74vGaWbqb1r8zpWC7zxXakVVOHHC4plG6rLINjQzvdSFKCQb5R_xtGsPPfvuE24bv4fvN4ZG2ILvb6X4Dly37WW_HXBqBnUs24mngoTxFaPgNmz1nDQNYQu91- ekX4-BNaovjDx4tP379qIG3-NygHTjFoOMDVUvs-pOPi1kfaoMjmYF2mdZAmVYS2nNLWxbeUymkHXF8lT_iVsJSzyaRFJS1Iqn7zbvwH1iUBjD_pB9EmtNmnUraKrCU9eHES27xTwD- yaaH_GHNc1XwXNbhWJaPFAm35U8ki1Le4WbUVRluFx0qwVqlEF3ieGO84PMidrp51FPm83B_oGt80xpvf6P8Ht5WvVpytjMU8UG7-js8hAzWQeYiK05YTXk-78xg0AO6NoNe_RSRk05zYpF6KlA2yQ_My79rZBv9GFt4kUfIxNjd9OiV1wXdidO7Iaq_Q’,
+ ‘url’: ‘http:\/\/podunk.edu’,
+ ‘url_sig’: "T8Bp7j5DHHhQDCFcAHXfuhUfGk2P3inPbImwaXXF1xJd3TGgluoXyyKDx6WDm07x0hqbupoAoZB1qBP3_WfvWiJVAK4N1FD77EOYttUEHZ7L43xy5PCpojJQmkppGbPJc2jnTIc_F1vvGvw5fv8gBWZvPqTdb6LWF6FLrzwesZpi7j2rsioZ3wyUkqb5TDZaNNeWQrIEYXrEnWkRI_qTSOzx0dRTsGO6SpU1fPWuOOYMZG8Nh18nay0kLpxReuHCiCdxjXRVvk5k9rkcMbDBJcBovhiSioPKv_yJxcZVBATw3z3TTE95kGi4wxCEenxwhSpvouwa5b0hT7NS4Ay70QaxoKiLb3ZjhZaUUn4igCyZM0h6fllR5I6J_sAQxiMYD0v5ouIlb0u8YVMni93j3zlqMWdDUZ4WgTI7NNbo8ug9NQDHd92TPmSE1TytPTgya3tsFMzwyq0LZ0b- g- zSXWIES__jKQ7vAtIs9EwlPxqJXEDDniZ2AJ6biXRYgE2Kd6W_nmI7w31igwQTms3ecXe5ENI3ckEPUAq__llNnND7mxp5ZrdXzd5HHU9slXwDShYcW3yDeQLEwAVomTGSFpBrCX8W77n9hF3JClkWaeS4QcZ3xUtsSS81yLrp__ifFfQqx9_Be89WVyIOoF4oydr08EkZ8zwlAsbZLG7eLXY"
+ },
+ ‘recipients’:{
+ {
+ ‘guid’: ‘ZHSqb3yGar3TYV_o9S-JkD-6o_V4DhUcxtv0VeyX8Kj_ENHPI_M3SyAUucU835-mIayGMmTpqJz3ujPkcavVhA’,
+ ‘guid_sig’: "JsAAXigNghTkkbq8beGMJjj9LBKZn28hZ-pHSsoQuwYWvBJ2lSnfc4r9l--WgO6sucH-SR6RiBo78eWn1cZrh_cRMu3x3LLx4y-tjixg- oOOgtZakkBg4vmOhkKPkci0mFtzvUrpY4YHySqsWTuPwRx_vOlIYIGEY5bRXpnkNCoC8J4EJnRucDrgSARJvA8QQeQQL0H4mWEdGL7wlsZp_2VTC6nEMQ48Piu6Czu5ThvLggGPDbr7PEMUD2cZ0jE4SeaC040REYASq8IdXIEDMm6btSlGPuskNh3cD0AGzH2dMciFtWSjmMVuxBU59U1I6gHwcxYEV6BubWt_jQSfmA3EBiPhKLyu02cBMMiOvYIdJ3xmpGoMY1Cn__vhHnx_vEofFOIErb6nRzbD- pY49C28AOdBA5ffzLW3ss99d0A-6GxZmjsyYhgJu4tFUAa7JUl84tMbq28Tib0HW6qYo6QWw8K1HffxcTpHtwSL5Ifx0PAoGMJsGDZDD1y_r9a4vH5pjqmGrjL3RXJJUy- m4eLV5r7xMWXsxjqu3D8r04_dcw4hwwexpMT1Nwf8CTB0TKb8ElgeOpDFjYVgrqMYWP0XdhatcFtAJI7gsS-JtzsIwON9Kij66-VAkqy_z1IXI0ziyqV1yapSVYoUV1vMScRZ_nMqwiB5rEDx-XLfzko"
+ }
+ }
+ ‘callback’:‘\/post’,
+ ‘version’:1,
+ ‘secret’:‘1eaa6613699be6ebb2adcefa5379c61a3678aa0df89025470fac871431b70467’,
+ ‘secret_sig’: "eKV968b1sDkOVdSMi0tLRtOhQw4otA8yFKaVg6cA4I46_zlAQGbFptS-ODiZlSAqR7RiiZQv4E2uXCKar52dHo0vvNKbpOp_ezWYcwKRu1shvAlYyytsflH5acnDWL-FKOOgz5zqLLZ6cKXFMoR1VJGG_Od- DKjSwajyV9uVzTry58Hz_w0W2pjxwQ-Xv11rab5R2O4kKSW77YzPG2R5E6Q7HN38FrLtyWD_ai3K9wlsFOpwdYC064dk66X7BZtcIbKtM6zKwMywcfJzvS5_0U5yc5GGbIY_lY6SViSfx9shOKyxkEKHfS29Ynk9ATYYGnwO-jnlMqkJC7t149H- sI9hYWMkLuCzaeLP56k2B2B2TmtnYvE_vHNQjzVhTwuHCIRVr-p6nplQn_P3SkOpYqPi3k_tnnOLa2d3Wtga8ClEY90oLWFJC3j2UkBf_VEOBNcg-t5XO3T-j9O4Sbk96k1Qoalc-QlznbGx4bOVsGkRBBMiH4YUqiiWB_OkFHtdqv7dqGeC- u-B4u9IxzYst46vvmyA3O-Q4APSZ1RY8ITUH0jLTbh6EAV7Oki8pIbOg0t56p-8RlanOZqmFvR-grVSc7Ak1ZcD8NACmvidUpa1B7WEvRcOeffx9lype0bt5XenDnMyx6szevwxZIiM8qGM2lsSk4fu8HI9cW0mLywzZT0"
+ }
+```
+
+auth_check messages MUST be encrypted. This message is sent to the originating site, which checks whether the ‘secret’ matches the ‘sec’ it originally transmitted. It also checks secret_sig, which is signed with the private key of the destination channel and encoded with base64url. If everything is OK, a json packet is returned:
+
+```
+ {
+ ‘success’:1,
+ ‘confirm’: "q0Ysovd1uQRsur2xG9Tg6bC23ynzw0191SkVd7CJcYoaePy6e_v0vnmPg2xBUtIaHpx_aSuhgAkd3aVjPeaVBmts6aakT6a_yAEy7l2rBydntu2tvrHhoVqRNOmw0Q1tI6hwobk1BgK9Pm0lwOeAo8Q98BqIJxf47yO9pATa0wktOg6a7LMogC2zkkhwOV5oEqjJfeHeo27TiHr1e2WaphfCusjmk27V_FAYTzw05HvW4SPCx55EeeTJYIwDfQwjLfP4aKV- I8HQCINt-2yxJvzH7Izy9AW- 7rYU0Il_gW5hrhIS5MTM12GBXLVs2Ij1CCLXIs4cO0x6e8KEIKwIjf7iAu60JPmnb_fx4QgBlF2HLw9vXMwZokor8yktESoGl1nvf5VV5GHWSIKAur3KPS2Tb0ekNh-tIk9u-xob4d9eIf6tge_d3aq1LcAtrDBDLk8AD0bho5zrVuTmZ9k- lBVPr_DRHSV_dlpu088j3ThaBsuV1olHK3vLFRhYCDIO0CqqK5IuhqtRNnRaqhlNN6fQUHpXk2SwHiJ2W36RCYMTnno6ezFk_tN-RA2ly- FomNZoC5FPA9gFwoJR7ZmVFDmUeK3bW-zYTA5vu15lpBPnt7Up_5rZKkr0WQVbhWJmylqOuwuNWbn3SrMQ8rYFZ23Tv300cOfKVgRBaePWQb4"
+ }
+```
+
+‘confirm’ in this case is the base64url-encoded RSA signature of the concatenation of “secret” with the base64url-encoded whirlpool hash of the source guid and guid_sig; signed with the private key of the source channel. This prevents a manin-the-middle from inserting a fraudulent success packet. Upon receipt and successful verification of this packet, the destination page is redirected to the original destination URL and displays a successful remote login. \ No newline at end of file
diff --git a/doc/en/developer/nomad_protocol.md b/doc/en/developer/nomad_protocol.md
new file mode 100644
index 000000000..c734ab9eb
--- /dev/null
+++ b/doc/en/developer/nomad_protocol.md
@@ -0,0 +1,44 @@
+### The Nomad protocol
+
+#### What is Nomad?
+
+Nomad is the revolutionary protocol that powers Hubzilla, enabling **communication**, **identity management** and **access control** across a fully **decentralised** network of independent websites, often referred to as ‘the grid’. The resulting platform is a robust system that supports privacy and security while enabling the kind of rich web services typically found only in centralised, proprietary solutions.
+
+Consider this typical scenario:
+
+Jaquelina wants to share photos from her blog at **jaquelina.org** with Roberto, but with no one else. Roberto maintains his own family hub at **roberto.net** on a completely independent server. Nomad allows Jaquelina to publish her photos with an *access control list (ACL)* that only includes Roberto. This means that while Roberto can see the photos when he visits her blog, his brother Marco cannot, nor can any other family member who has an account on **roberto.net**.
+
+The twist in this scenario is the fact that Roberto never logged in to Jaquelina's website. Instead, he only had to log in once with his password on his *own* **roberto.net** website. When Roberto visits **jaquelina.org**, he is seamlessly authenticated by their hub by querying his server in the background.
+
+It's not uncommon for servers to have technical issues or become inaccessible for various reasons. Nomad provides robustness to Roberto's online activities by allowing him to have *clones* of his online identity or *channel* on multiple independent hubs. Imagine that Roberto's server goes down for some reason and he can no longer log in there. He simply logs into one of his clones on **gadfly.com**, a website run by his friend Peter. Once he has authenticated himself at **gadfly.com**, Roberto can view Jaquelina's blog as before, without Jaquelina having to grant additional access!
+
+#### Communication
+
+Communication and social networks are an essential part of the grid. Any channel (and any service provided by that channel) can take full advantage of feature-rich social communication on a global scale. These communications can be public or private - and private communications include not only fully encrypted transport, but also encrypted storage to protect against accidental snooping and disclosure by rogue system administrators and ISPs.
+
+Nomad supports a wide range of background services in the grid, from friend suggestions to directory services. New content and data updates are passed in the background between hubs across the grid according to the access control lists and permissions set by the *sender and* receiver channels. Data is also synchronised between any number of channel clones so that hub members can access data and continue to collaborate seamlessly even if their primary hub is unavailable or offline.
+
+#### Identity
+
+Nomad's identity layer is unique. It provides an **invisible single sign-on** for all locations in the grid.
+It also provides a **nomadic identity** so that your communication with friends, family or other people you communicate with is not affected by the loss of your primary communication hub - either temporarily or permanently.
+
+The important parts of your identity and relationships can be backed up on a USB stick or your laptop and appear on any node on the network at any time - with all your friends and preferences.
+Crucially, these nomadic instances are kept synchronised so that any instance can take over if another is compromised or corrupted. This not only protects you from major system failures, but also from temporary website overload and government tampering or censorship.
+
+We believe that Hubzilla's nomadic identity, single sign-on and decentralisation bring a high level of **resilience** and **consistency** to internet communications, which is much needed in the face of global trends towards corporate centralisation and mass and indiscriminate government surveillance and censorship.
+When browsing the web, viewing channels and their unique content, you are seamlessly authenticated, even across completely different server hubs. No need to enter passwords. You don't have to type anything. You are simply greeted with your name on every new page you visit.
+
+How does this work with Nomad? We call it **‘magic-auth’** because Hubzilla hides the details of the complexity of single sign-on logins and nomadic identities from web browsing. This is one of Hubzilla's design goals: to increase privacy and freedom on the Internet while reducing the complexity and tedium of having to enter new passwords and login names every time you visit the Internet. You only log in once to your home hub (or a nomadic backup hub of your choice). This allows you to access all authenticated services offered anywhere on the web - such as shopping, blogs, forums and access to private information. Your password is not stored on a thousand different websites, but on servers that you control or trust.
+
+They cannot be silenced. They cannot be removed from the network unless you choose to leave it yourself.
+
+#### Access control
+
+Nomad's identity layer allows you to assign fine-grained permissions to any content you want to publish - and these permissions extend across the entire grid. It's like having a huge website made up of an army of small individual websites - where each channel in the grid can fully control its privacy and sharing preferences for all the web resources it creates.
+
+Currently, Hubzilla supports access control for many types of data, including discussion posts and comments, photo albums, events, cloud files, web pages, wikis and more. Each item and how and with whom it is shared is completely under your control.
+
+This type of control is trivial with large enterprise providers as they own the user database. In the Grid, you don't need a huge user database on your computer - because the Grid **is** your user database. It has essentially infinite capacity (limited by the total number of hubs online on the Internet) and is distributed across hundreds, possibly even millions of computers.
+
+Access can be granted or denied to any resource, channel or group of channels - anywhere on the grid. Others can access your content if you allow them to, and they don't even need to have an account in your hub. \ No newline at end of file
diff --git a/doc/en/developer/nomad_structures.md b/doc/en/developer/nomad_structures.md
new file mode 100644
index 000000000..b96279a97
--- /dev/null
+++ b/doc/en/developer/nomad_structures.md
@@ -0,0 +1,110 @@
+### Nomad structures
+
+#### Nomad signatures
+
+All signed data in Nomad is generated by an RSA signature operation with the initiator's private key. The binary result is then encoded for transport with base64url.
+
+#### Nomad encryption
+
+Encryption is currently performed using AES256CTR. Other algorithms MAY be supported. A 32-octet key and a 16-octet initialisation vector are generated at random. The desired data is then encoded with these generated strings and the result is base64url encoded. An array is then created:
+
+- data
+ The base64url-encoded encrypted data
+- alg
+ The selected algorithm, in this case the character string ‘aes256ctr’.
+- key
+ The randomly generated key, RSA-encrypted with the recipient's public key, and the base64url-encoded result
+- iv
+ The randomly generated initialisation vector, RSA-encrypted with the recipient's public key, and the base64url-encoded result
+
+#### Basic Nomad packet
+
+Used to initiate a dialogue with another Nomad site. This packet MAY be encrypted. The presence of an array element ‘iv’ indicates that encryption has been performed. When sending an ‘auth_check’ packet, this packet MUST be encrypted, using the target site's public key (the site key, as opposed to a sender key).
+
+```
+ {
+ ‘type’: ‘notify’,
+ ‘sender’:{
+ ‘guid’: ‘kgVFf_1_SSbyqH-BNWjWuhAvJ2EhQBTUdw-Q1LwwssAntr8KTBgBSzNVzUm9_RwuDpxI6X8me_QQhZMf7RfjdA’,
+ ‘guid_sig’: "PT9-TApzpm7QtMxC63MjtdK2nUyxNI0tUoWlOYTFGke3kNdtxSzSvDV4uzq_7SSBtlrNnVMAFx2_1FDgyKawmqVtRPmT7QSXrKOL2oPzL8Hu_nnVVTs_0YOLQJJ0GYACOOK- R5874WuXLEept5-KYg0uShifsvhHnxnPIlDM9lWuZ1hSJTrk3NN9Ds6AKpyNRqf3DUdz81- Xvs8I2kj6y5vfFtm-FPKAqu77XP05r74vGaWbqb1r8zpWC7zxXakVVOHHC4plG6rLINjQzvdSFKCQb5R_xtGsPPfvuE24bv4fvN4ZG2ILvb6X4Dly37WW_HXBqBnUs24mngoTxFaPgNmz1nDQNYQu91- ekX4-BNaovjDx4tP379qIG3-NygHTjFoOMDVUvs-pOPi1kfaoMjmYF2mdZAmVYS2nNLWxbeUymkHXF8lT_iVsJSzyaRFJS1Iqn7zbvwH1iUBjD_pB9EmtNmnUraKrCU9eHES27xTwD- yaaH_GHNc1XwXNbhWJaPFAm35U8ki1Le4WbUVRluFx0qwVqlEF3ieGO84PMidrp51FPm83B_oGt80xpvf6P8Ht5WvVpytjMU8UG7-js8hAzWQeYiK05YTXk-78xg0AO6NoNe_RSRk05zYpF6KlA2yQ_My79rZBv9GFt4kUfIxNjd9OiV1wXdidO7Iaq_Q’,
+ ‘url’: ‘http:\/\/podunk.edu’,
+ ‘url_sig’: "T8Bp7j5DHHhQDCFcAHXfuhUfGk2P3inPbImwaXXF1xJd3TGgluoXyyKDx6WDm07x0hqbupoAoZB1qBP3_WfvWiJVAK4N1FD77EOYttUEHZ7L43xy5PCpojJQmkppGbPJc2jnTIc_F1vvGvw5fv8gBWZvPqTdb6LWF6FLrzwesZpi7j2rsioZ3wyUkqb5TDZaNNeWQrIEYXrEnWkRI_qTSOzx0dRTsGO6SpU1fPWuOOYMZG8Nh18nay0kLpxReuHCiCdxjXRVvk5k9rkcMbDBJcBovhiSioPKv_yJxcZVBATw3z3TTE95kGi4wxCEenxwhSpvouwa5b0hT7NS4Ay70QaxoKiLb3ZjhZaUUn4igCyZM0h6fllR5I6J_sAQxiMYD0v5ouIlb0u8YVMni93j3zlqMWdDUZ4WgTI7NNbo8ug9NQDHd92TPmSE1TytPTgya3tsFMzwyq0LZ0b- g- zSXWIES__jKQ7vAtIs9EwlPxqJXEDDniZ2AJ6biXRYgE2Kd6W_nmI7w31igwQTms3ecXe5ENI3ckEPUAq__llNnND7mxp5ZrdXzd5HHU9slXwDShYcW3yDeQLEwAVomTGSFpBrCX8W77n9hF3JClkWaeS4QcZ3xUtsSS81yLrp__ifFfQqx9_Be89WVyIOoF4oydr08EkZ8zwlAsbZLG7eLXY"
+ ‘sitekey’:"-----BEGIN PUBLIC KEY-----
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxTeIwXZWrw/S+Ju6gewh
+LgkKnNNe2uCUqCqMZoYgJar3T5sHCDhvXc4dDCbDkxVIaA/+V1mURtBV60a3IGjn
+OAO0W0XGGLe2ED7G5o9U8T9mVGq8Mauv0v1oQ5wIR1gEAhBavkQ2OUGuF/YKn2nj
+HlKsv9HzUAHpcDMUe3Uklc2RhQbMcnJxEgkyjCkDyrTtCZzISkTAocHvpCG1KSog
+njUZdiz9UWxvM4rCFkCJvQU4RwRZJb7GA9ul+9JrF7NvUQTx8csRP2weBk1E9yyj
+wbe187E0eVj9RXX2Mx3mYhgrTdodxLOVMSXZLg1/SMpeFFl7QBhuM0SiOPg8a7Et
+e2iNA/RD4WiUFqCDfafasRa1TOozOm7LA+08lkAh5PeQPJsJbrX0wVVft++Y+5/z
+BvcUOP73vcbz7j5hJ7HLsbQtye/UUCfODBFybuDqRM84Aet8rjZohX7vukXdMD4I
+2HuB7pjR4uIfyYr0J63ANkvbsn8LR+RnirmHrK5H/OgxxjXcfYbGEQgFxvxhF6lA
+FpMu6Do4dx3CIb6pRmZ8bjSImXexJ0BSo9n3gtrz0XYLecsYFlQ9+QQjm83qxyLb
+M23in0xqMVsyQvzjNkpImrO/QdbEFRIIMee83IHq+adbyjQR49Z2hNEIZhkLPc3U
+2cJJ2HkzkOoF2K37qwIzk68CAwEAAQ==
+-----END PUBLIC KEY-----
+"
+ },
+ ‘recipients’:{
+ {
+ ‘guid’: ‘lql-1VnxtiO4-WF0h72wLX1Fu8szzHDOXgQaTbELwXW77k8AKFfh-hYr70vqMrc3SSvWN-Flrc5HFhRTWB7ICw’,
+ ‘guid_sig’: "PafvEL0VpKfxATxlCqDjfOeSIMdmpr3iU7X-Sysa1h5LzDpjSXsjO37tYZL- accb1M5itLlfnW5epkTa5I4flsW21zSY1A2jCuBQUTLLGV7rNyyBy7lgqJUFvAMRx0TfXzP9lcaPqlM9T1tA6jfWOsOmkdzwofGeXBnsjGfjsO2xdGYe6vwjOU0DSavukvzDMnOayB9DekpvDnaNBTxeGLM45Skzr7ZEMcNF7TeXMbnvpfLaALYEKeQs9bGH- UgAG8fBWgzVAzeBfx_XSR1rdixjyiZGP0kq0h35SlmMPcEjliodOBFwMXqpXFB7Ibp4F6o6te2p2ErViJccQVG8VNKB6SbKNXY6bhP5zVcVsJ- vR-p4xXoYJJvzTN7yTDsGAXHOLF4ZrXbo5yi5gFAlIrTLAF2EdWQwxSGyLRWKxG8PrDkzEzX6cJJ0VRcLh5z6OI5QqQNdeghPZbshMFMJSc_ApCPi9_hI4ZfctCIOi3T6bdgTNKryLm5fhy_eqjwLAZTGP- aUBgLZpb1mf2UojBn6Ey9cCyq-0T2RWyk-FcIcbV4qJ-p_8oODqw13Qs5FYkjLr1bGBq82SuolkYrXEwQClxnrfKa4KYc2_eHAXPL01iS9zVnI1ySOCNJshB97Odpooc4wk7Nb2Fo-Q6THU9zuu0uK_-JbK7IIl6go2qA"
+ },
+ },
+ ‘callback’:‘\/post’,
+ ‘version’: ‘1.2’,
+ ‘encryption’:{
+ ‘aes256ctr’
+ },
+ ‘secret’:‘1eaa6613699be6ebb2adcefa5379c61a3678aa0df89025470fac871431b70467’,
+ ‘secret_sig’: "0uShifsvhHnxnPIlDM9lWuZ1hSJTrk3NN9Ds6AKpyNRqf3DUdz81-Xvs8I2kj6y5vfFtm- FPKAqu77XP05r74vGaWbqb1r8zpWC7zxXakVVOHHC4plG6rLINjQzvdSFKCQb5R_xtGsPPfvuE24bv4fvN4ZG2ILvb6X4Dly37WW_HXBqBnUs24mngoTxFaPgNmz1nDQNYQu91-ekX4-BNaovjDx4tP379qIG3-NygHTjFoOMDVUvs- pOPi1kfaoMjmYF2mdZAmVYS2nNLWxbeUymkHXF8lT_iVsJSzyaRFJS1Iqn7zbvwH1iUBjD_pB9EmtNmnUraKrCU9eHES27xTwD- yaaH_GHNc1XwXNbhWJaPFAm35U8ki1Le4WbUVRluFx0qwVqlEF3ieGO84PMidrp51FPm83B_oGt80xpvf6P8Ht5WvVpytjMU8UG7-js8hAzWQeYiK05YTXk-78xg0AO6NoNe_RSRk05zYpF6KlA2yQ_My79rZBv9GFt4kUfIxNjd9OiV1wXdidO7Iaq_Q"
+ }
+```
+
+type
+
+The message type: **notify, purge, refresh, force_refresh, auth_check, ping** or **pickup**. The content of the packets varies depending on the message type. The **notify packet** is described here.
+
+callback
+
+A character string that is appended to the URL and identifies the Nomad communication endpoint on this system. This is usually the character string ‘/post’.
+
+version
+
+The identifier of the Nomad protocol so that future protocol revisions can co-exist.
+
+encryption
+
+Array of supported encryption algorithms, ordered by decreasing preference. If no compatible encryption methods are specified, applications MUST use ‘aes256cbc’.
+
+secret
+
+A 64-character string randomly generated by the sending side.
+
+secret_sig
+
+The RSA signature of the secret, signed with the sender's private key.
+
+sender
+
+An array of four components that provide a portable identity. We can contact the given URL and download a Nomad info packet to obtain the sender's public key and use it to verify the sender's guid and the signatures of the sending URL.
+
+- guid
+ Usually a 64 character base64url encoded string. It is generated when an identity is created and an attempt is made to make it unique, but this is not required.
+- guid_sig
+ The RSA signature of the guid, signed with the sender's private key and base64url-encoded.
+- url
+ The base URL of the location from which this post originated.
+- url_sig
+ The RSA signature of the url, signed with the sender's private key and base64url encoded.
+- sitekey
+ The public key of the website specified in the url
+
+recipients
+
+Only used for private messages. An array of envelope recipients. Each recipient is represented by an array of guid and guid_sig. If recipients are specified, the entire packet is also encapsulated with a negotiated cryptographic algorithm or ‘aes256cbc’ if none could be negotiated.
+
+- guid
+ The guid of a private recipient.
+- guid_sig
+ The RSA signature of the guid, signed with the recipient's private key and base64url-encoded \ No newline at end of file
diff --git a/doc/en/developer/our_pledge.md b/doc/en/developer/our_pledge.md
new file mode 100644
index 000000000..7f8f9da0b
--- /dev/null
+++ b/doc/en/developer/our_pledge.md
@@ -0,0 +1,3 @@
+#### Our pledge
+
+In the interest of fostering an open and welcoming environment, we as contributors and carers pledge to make participation in our project and community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, experience level, nationality, personal appearance, ethnicity, religion or sexual identity and orientation. \ No newline at end of file
diff --git a/doc/en/developer/our_responsibilities.md b/doc/en/developer/our_responsibilities.md
new file mode 100644
index 000000000..d083a570c
--- /dev/null
+++ b/doc/en/developer/our_responsibilities.md
@@ -0,0 +1,3 @@
+#### Our responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable behaviour and are expected to take appropriate and fair corrective action when unacceptable behaviour is identified. Project maintainers have the right and responsibility to remove, edit or reject comments, commits, code, wiki edits, issues and other contributions that do not comply with this Code of Conduct, or to temporarily or permanently ban contributions that they deem inappropriate, threatening, offensive or harmful. \ No newline at end of file
diff --git a/doc/en/developer/our_standards.md b/doc/en/developer/our_standards.md
new file mode 100644
index 000000000..583614347
--- /dev/null
+++ b/doc/en/developer/our_standards.md
@@ -0,0 +1,17 @@
+#### Our standards
+
+Examples of behaviours that contribute to creating a positive environment include
+
+- Using welcoming and inclusive language
+- Respecting different points of view and experiences
+- Accepting constructive criticism gracefully
+- Focusing on what is best for the community
+- Showing empathy towards other members of the community
+
+Examples of unacceptable behaviour from participants include
+
+- The use of sexualised language or images and unwanted sexual attention or advances
+- Trolling, offensive/degrading comments and personal or political attacks
+- Public or private harassment
+- Publishing the private information of others, such as a physical or electronic address, without express permission
+- Other behaviour that could be considered inappropriate in a professional environment \ No newline at end of file
diff --git a/doc/en/developer/scope.md b/doc/en/developer/scope.md
new file mode 100644
index 000000000..84c617cbb
--- /dev/null
+++ b/doc/en/developer/scope.md
@@ -0,0 +1,3 @@
+#### Scope
+
+This Code of Conduct applies both within the project areas and in the public sphere when a person is representing the project or its community. Examples of representing a project or community include using an official project email address, posting via an official social media account or acting as an appointed representative at an online or offline event. The representation of a project can be further defined and specified by the project supervisors. \ No newline at end of file
diff --git a/doc/en/developer/technical_introduction.md b/doc/en/developer/technical_introduction.md
new file mode 100644
index 000000000..731fd5934
--- /dev/null
+++ b/doc/en/developer/technical_introduction.md
@@ -0,0 +1,292 @@
+### Technical introduction
+
+Nomad is a JSON-based web framework for implementing secure decentralised communication and services. To provide this functionality, Nomad creates a decentralised, globally unique identifier for each node in the network. This global identifier is not inextricably linked to the DNS, ensuring the required mobility. Many of the existing decentralised communication frameworks provide the communication aspect, but no remote access control and authentication. Furthermore, most of these systems are based on the ‘web finger’, which still ties identity to domain names and cannot support nomadic identity.
+The main problems that Nomad addresses are
+
+- Fully decentralised communication
+- Independence from DNS-based identity
+- node mobility
+- seamless remote authentication
+- high performance
+
+We will rely on DNS-based user@host addresses as a ‘user-friendly’ mechanism to tell others where you are, namely on a named host with a specific username, and communication with DNS entities is handled over TCP and the web.
+
+However, the underlying protocol provides an abstraction layer on top of this so that a communication node (e.g. ‘identity’) can move to a different DNS location and recover (to the best of its ability) from location changes and/or maintain pre-existing communication relationships. A side effect of this requirement is the ability to communicate from alternative/multiple DNS locations and service providers and still maintain a single online identity.
+
+We call this overlay network the ‘grid’. The servers connected to this network are called ‘hubs’ and can support any number of individual identities.
+
+An identity does not necessarily have to correspond to a person. It is merely something that requires the ability to communicate within the grid.
+
+The ability to recover is achieved by communicating with the original location when a new or replacement identity is created, or as a fallback to a stored file describing the identity and its contacts in the event that the old location no longer responds.
+
+At least in the short term, mobility of existing content is not the highest priority. This may or may not happen at a later date. The most important things we want to keep are your identity and your friends.
+Addresses that are shared by multiple people are user@host and describe the **current** local credentials for a particular identity. They are DNS-based addresses that are used as a seed to localise a particular identity within the network. Machine communication binds this address to a globally unique ID. A single globally unique ID can be attached or bound to any number of DNS locations. Once an identity is mapped or bound to a DNS location, communication consists only of knowing the globally unique address and the DNS (url) currently in use (to recall and verify/complete the current communication). These concepts will be specified in more detail in the future.
+
+For an identity to persist across locations, one must be able to provide or recover
+
+- the globally unique ID for that identity
+- the private key assigned to that identity
+- (if the original server no longer exists) an address book of contacts for that identity.
+
+This information can be exported from the original server via an API and/or downloaded to a hard drive or USB stick.
+
+We can also attempt to restore the identity with even less information, but this is vulnerable to account hijacking and requires your contacts to confirm the change.
+
+To enable high performance communication, the data transfer format for all aspects of Nomad is JSON. XML communication requires far too much overhead.
+
+Bi-directional encryption is based on 4096-bit RSA keys expressed in DER/ASN.1 format using the PKCS#8 encoding variant, with AES encryption of variable length or large elements. The exact encryption algorithms are negotiable between sites.
+
+Some aspects of the well-known ‘federation protocols’ (Webfinger, Salmon, Activitystreams, Portablecontacts, etc.) can be used in Nomad, but we are not and will not be bound by them. The Hubzilla project is trying some fairly novel developments in the field of decentralised communication, and if it should be necessary to deviate from such ‘standard protocols’, we will do so without question or hesitation.
+To create a globally unique ID, we will base it on a whirlpool hash of the origin node's identity URL and a pseudo-random number, which should give us a 256-bit ID with an extremely low collision probability (256 bits equals about 115 quattuorviginitillion or 1.16 X 10^77 unique numbers). This is represented in the communication as a base64url encoded string. However, we will not rely on probabilities, and the ID must also be associated with a public key, using public key cryptography to provide an identity guarantee that has not been copied or somehow collided in the whirlpool hash space.
+
+Using the DNS as the basis for the ID provides a globally unique seed, which would not be the case if the ID was based entirely on pseudo-random number generation.
+
+We refer to the encoded globally unique uid string as zot_uid
+
+As there may be more than one DNS location associated/connected to a particular zot_uid identity, the delivery processes should deliver to all of these locations as we do not know with certainty which hub instance can be accessed at any given time. However, we will designate one DNS location as ‘primary’ which will be the preferred location for displaying web profile information.
+
+We also need to provide the ability to change the primary location to a new location. A lookup of information about the current primary location can provide a ‘redirect pointer’ that instructs us to update our listings and move everything to the new location. There is also the possibility that the primary location no longer exists and is no longer responding. In this case, a location that is already assigned to this zot_uid can take control and declare itself as primary. In both cases, the primary designation is automatically confirmed and moved. A request can also be made from a primary location requesting the removal of another location.
+
+To assign a zot_uid to a second (or tertiary) location, a secure exchange is required to verify that the new location is in possession of the private key for that zot_uid. The security of the private key is therefore essential to prevent identity hijacking.
+
+Communication then requires
+
+- zot_uid (character string)
+- uid_sig
+- callback (current location Nomad endpoint url)
+- callback_sig
+- spec (int)
+
+is transferred with every message. The spec is a revision number of the current Nomad specification so that communication with hubs that use older and possibly incompatible protocol specifications can be maintained. Communication is verified using a stored public key that was copied to this zot_uid when the connection was first established.
+
+The revocation and replacement of the key must be carried out from the primary hub. The exact form for this is still being worked out, but will likely be a notification to all other bound hubs to ‘phone home’ (to the primary hub) and request a copy of the new key. This notification should be verified with a site or hub key, as the original identity key may have been compromised and cannot be trusted.
+To avoid confusion, there should be exactly one canonical url for each hub so that it can be indexed and uniquely referenced.
+
+To avoid ambiguity of the scheme, it is strongly recommended that all addresses should be https with a browser valid certificate and a single valid host component (either [www.domain.ext](www.domain.ext) or domain.ext, but not both) used in all communication. Multiple URLs can be specified locally, but only a single URL should be used for all Nomad communication within the grid.
+
+Test installations that are not connected to the public network can use non-SSL, but all traffic flowing over public networks should be protected from session hijacking, preferably with a ‘browser recognised’ certificate.
+
+Where possible, the Nomad recommends the use of ‘batching’ to minimise network traffic between two hubs. This means that ‘Site A’ can send multiple messages to ‘Site B’ in a single transaction and also consolidate the delivery of identical messages to multiple recipients in the same hub.
+
+The messages themselves may or may not be encrypted in transit, depending on the private nature of the messages. SSL (strongly recommended) provides unconditional encryption of the data stream, however it makes little sense to encrypt public messages that have been categorised as having unrestricted visibility. Encryption of data storage and so-called ‘end-to-end encryption’ are outside the scope of Nomad. It is assumed that node operators take appropriate security precautions to ensure the security of their data stores, and these are functions of application and site integrity as opposed to protocol integrity.
+
+#### Messaging
+
+Given the constraints listed above, a Nomad message should therefore be a json array of individual messages. These can be mixed and combined within the same transmission.
+
+Each message then requires:
+
+- Type
+- (optional) recipient list
+
+The absence of a recipient list would indicate an unencrypted public message or a site-level message. The recipient list would contain an array of zot_uid with an individual decryption key and a common iv. The decryption key is encrypted with the public key of the recipient identity. The iv is encrypted with the private key of the sender.
+
+All messages should be digitally signed by the sender.
+
+The type can be one of the following (this list can be extended):
+
+- Mail (or activity)
+- Mail
+- identity
+- authenticate
+
+Identity messages have no recipients and notify the system social graph of an identity update, which can be a new or deleted identity, a new or deleted location, or a change to the primary hub. The signature for these messages uses system keys as opposed to identity-specific keys.
+
+Posts include many different types of activity, such as top-level posts, likes/dislikes, comments, tagging activity, etc. These types are specified in the message structure.
+
+Authentication messages result in mutual authentication and browser redirection to protected resources on the remote hub, such as the ability to post wall-to-wall messages and view private photo albums and events, etc.
+
+#### Exploration
+
+A known URL is used to probe a hub for Nomad capabilities and identity queries, including discovery of public keys, profile locations, profile photos, and the primary hub location.
+
+The location for this service is /.well-known/zot-info - and must be available in the root directory of the selected domain.
+
+To perform a query, a POST request is made to the discovery location with the following parameters:
+Required:
+
+Address => an address on the target system such as ‘john’
+
+Optional:
+
+target => the observer's Nomad ‘guid’ for the evaluation of authorisations
+
+target_sig => an RSA signature (base64url-encoded) of the guid
+
+key => The public key required to verify the signature
+
+token => a character string selected by the requesting service (possibly random). If present, an entry in the discovered packet labelled ‘signed_token’ is provided, which consists of the base64url_encoded RSA signature of the concatenation of the string ‘token.’ and the provided token using the private key of the discovered channel. This can be verified with the provided ‘key’ entry and provides assurance that the server is in possession of the private key for the discovered identity. After 1 January 2017, it is **required** that a server provides a signed_token *if* a token has been specified in the request.
+
+If no target is specified, the returned authorisations are generic authorisations for unknown or unauthenticated observers
+
+Example of a detection package for ‘`mike@zothub.com`’
+
+```
+ {
+
+ ‘success’: true,
+ ‘signed_token’: "KBJrKTq1qrctNuxF3GwVh3GAGRqmgkirlXANPcJZAeWlvSt_9TMV097slR4AYnYCBEushbVqHEJ9Rb5wHTa0HzMbfRo8cRdl2yAirvvv5d98dtwHddQgX1jB0xEypXtmIYMdPGDLvhI1RNdIBhHkkrRcNreRzoy4xD- -HM6m1W0-A8PJJ9BcNxmGPcBtLzW08wzoP9trJ3M7DQ6Gkk6j7iwVsyApw1ZBaDvabGTdc_SFV-Iegtqw3rjzT_xXWsfzMlKBy-019MYn_KS- gu23YzjvGu5tS_zDfkQb8DMUlPLz5yyxM0yOMlUDtG2qQgIJAU2O0X6T5xDdJ6mtolNyhepg845PvFDEqBQGMIH1nc47CNumeudDi8IWymEALhjG_U8KAK7JVlQTJj2EKUb0au1g6fpiBFab5mmxCMtZEX3Jreyak5GOcFFz- WpxuXJD9TdSoIvaBfBFOoJnXkg2zE4RHXeQzZ2FotmrbBG5dm8B- _6byYGoHBc08ZsWze1K96JIeRnLpBaj6ifUDcVHxZMPcGHHT27dvU2PNbgLiBjlAsxhYqkhN5qOHN8XBcg2KRjcMBaI3V0YMxlzXz5MztmZq3fcB1p-ccIoIyMPMzSj3yMB7J9CEU2LYPSTHMdPkIeDE6GaCkQKviaQJQde346tK_YjA2k7_SOBmvPYE’,
+ ‘guid’: ‘sebQ-IC4rmFn9d9iu17m4BXO-kHuNutWo2ySjeV2SIW1LzksUkss12xVo3m3fykYxN5HMcc7gUZVYv26asx-Pg’,
+ ‘guid_sig’: "Llenlbl4zHo6-g4sa63MlQmTP5dRCrsPmXHHFmoCHG63BLq5CUZJRLS1vRrrrr_MNxr7zob_Ykt_m5xPKe5H0_i4pDj-UdP8dPZqH2fqhhx00kuYL4YUMJ8gRr5eO17vsZQ3XxTcyKewtgeW0j7ytwMp6- hFVUx_Cq08MrXas429ZrjzaEwgTfxGnbgeQYQ0R5EXpHpEmoERnZx77VaEahftmdjAUx9R4YKAp13pGYadJOX5xnLfqofHQD8DyRHWeMJ4G1OfWPSOlXfRayrV_jhnFlZjMU7vOdQwHoCMoR5TFsRsHuzd- qepbvo3pzvQZRWnTNu6oPucgbf94p13QbalYRpBXKOxdTXJrGdESNhGvhtaZnpT9c1QVqC46jdfP0LOX2xrVdbvvvG2JMWFv7XJUVjLSk_yjzY6or2VD4V6ztYcjpCi9d_WoNHruoxro_br1YO3KatySxJs-LQ7SOkQI60FpysfbphNyvYMkotwUFI59G08IGKTMu3- GPnV1wp7NOQD1yzJbGGEGSEEysmEP0SO9vnN45kp3MiqbffBGc1r4_YM4e7DPmqOGM94qksOcLOJk1HNESw2dQYWxWQTBXPfOJT6jW9_crGLMEOsZ3Jcss0XS9KzBUA2p_9osvvhUKuKXbNztqH0oZIWlg37FEVsDs_hUwUJpv2Ar09k4’,
+ ‘key’: "-----BEGIN PUBLIC KEY----- \nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7QCwvuEIwCHjhjbpz3Oc\ntyei/Pz9nDksNbsc44Cm8jxYGMXsTPFXDZYCcCB5rcAhPPdZSlzaPkv4vPVcMIrw\n5cdX0tvbwa3rNTng6uFE7qkt15D3YCTkwF0Y9FVZiZ2Ko+G23QeBt9wqb9dlDN1d\nuPmu9BLYXIT/JXoBwf0vjIPFM9WBi5W/EHGaiuqw7lt0qI7zDGw77yO5yehKE4cu\n7dt3SakrXphL70LGiZh2XGoLg9Gmpz98t+gvPAUEotAJxIUqnoiTA8jlxoiQjeRK\nHlJkwMOGmRNPS33awPos0kcSxAywuBbh2X3aSqUMjcbE4cGJ++/13zoa6RUZRObC\nZnaLYJxqYBh13/N8SfH7d005hecDxWnoYXeYuuMeT3a2hV0J84ztkJX5OoxIwk7S\nWmvBq4+m66usn6LNL+p5IAcs93KbvOxxrjtQrzohBXc6+elfLVSQ1Rr9g5xbgpub\npSc+hvzbB6p0tleDRzwAy9X16NI4DYiTj4nkmVjigNo9v2VPnAle5zSam86eiYLO\nt2u9YRqysMLPKevNdj3CIvst+BaGGQONlQalRdIcq8Lin+BhuX+1TBgqyav4XD9K\nd+JHMb1aBk/rFLI9/f2S3BJ1XqpbjXz7AbYlaCwKiJ836+HS8PmLKxwVOnpLMbfH\nPYM8k83Lip4bEKIyAuf02qkCAwEAAQ==\n- ----END PUBLIC KEY-----\n’,
+ ‘name’: ‘Mike Macgirvin’,
+ ‘name_updated’: ‘2012-12-06 04:59:13’,
+ ‘address’: ‘mike@zothub.com’,
+ ‘photo_mimetype’: ‘image/jpeg’,
+ ‘photo’: ‘https://zothub.com/photo/profile/l/1’,
+ ‘photo_updated’: ‘2012-12-06 05:06:11’,
+ ‘url’: ‘https://zothub.com/channel/mike’,
+ ‘connections_url’: ‘https://zothub.com/poco/mike’,
+ ‘target’: ‘’,
+ ‘target_sig’: ‘’,
+ ‘searchable’: false,
+ ‘permissions’: {
+ ‘view_stream’: true,
+ ‘view_profile’: true,
+ ‘view_photos’: true,
+ ‘view_contacts’: true,
+ ‘view_storage’: true,
+ ‘view_pages’: true,
+ ‘send_stream’: false,
+ ‘post_wall’: false,
+ ‘post_comments’: false,
+ ‘post_mail’: false,
+ ‘post_photos’: false,
+ ‘tag_deliver’: false,
+ ‘chat’: false,
+ ‘write_storage’: false,
+ ‘write_pages’: false,
+ ‘delegate’: false
+ },
+ ‘profile’: {
+ ‘description’: ‘Freedom Fighter’,
+ ‘birthday’: ‘0000-05-14’,
+ ‘next_birthday’: ‘2013-05-14 00:00:00’,
+ ‘gender’: ‘Male’,
+ ‘marital’: ‘It's complicated’,
+ ‘sexual’: ‘Females’,
+ ‘locale’: ‘’,
+ ‘region’: ‘’,
+ ‘postcode’: ‘’,
+ ‘country’: ‘Australia’
+ },
+ ‘locations’: [
+ {
+ ‘host’: ‘zothub.com’,
+ ‘address’: ‘mike@zothub.com’,
+ ‘primary’: true,
+ ‘url’: ‘https://zothub.com’,
+ ‘url_sig’: "eqkB_9Z8nduBYyyhaSQPPDN1AhSm5I4R0yfcFxPeFpuu17SYk7jKD7QzvmsyahM5Kq7vDW6VE8nx8kdFYpcNaurqw0_IKI2SWg15pGrhkZfrCnM- g6A6qbCv_gKCYqXvwpSMO8SMIO2mjQItbBrramSbWClUd2yO0ZAceq3Z_zhirCK1gNm6mGRJaDOCuuTQNb6D66TF80G8kGLklv0o8gBfxQTE12Gd0ThpUb5g6_1L3eDHcsArW_RWM2XnNPi_atGNyl9bS_eLI2TYq0fuxkEdcjjYx9Ka0- Ws-lXMGpTnynQNCaSFqy-Fe1aYF7X1JJVJIO01LX6cCs- kfSoz29ywnntj1I8ueYldLB6bUtu4t7eeo__4t2CUWd2PCZkY3PKcoOrrnm3TJP5_yVFV_VpjkcBCRj3skjoCwISPcGYrXDufJxfp6bayGKwgaCO6QoLPtqqjPGLFm- fbn8sVv3fYUDGilaR3sFNxdo9mQ3utxM291XE2Pd0jGgeUtpxZSRzBuhYeOybu9DPusID320QbgNcbEbEbEImO8DuGIxuVRartzEXQF4WSYRdraZzbOqCzmU0O55P836JAfrWjgxTQkXlYCic- DBk-iE75JeT72smCtZ4AOtoFWCjZAABCw42J7JELY9APixZXWriKtjy6JI0G9d3fs6r7SrXr1JMy0’,
+ ‘callback’: ‘https://zothub.com/post’,
+ ‘sitekey’: "-----BEGIN PUBLIC KEY----- \nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1IWXwd/BZuevq8jzNFoR\n3VkenduQH2RpR3Wy9n4+ZDpbrUKGJddUGm/zUeWEdKMVkgyllVA/xHdB7jdyKs1X\nuIet9mIdnzvhdLO/JFD5hgbNG2wpSBIUY6aSNeCFTzszqXmuSXMW5U0Ef5pCbzEA\nnhoCoGL1KAgPqyxnGKUlj7q2aDwC9IRNtAqNyFQL67oT91vOQxuMThjlDhbR/29Q\ncYR4i1RzyahgEPCnHCPkT2GbRrkAPjNZAdlnk9UesgP16o8QB3tE2j50TVrbVc/d\nYRbzC56QMPP9UgUsapNeSJBHji75Ip/E5Eg/kfJC/HEQgyCqjCGfb7XeUaeQ7lLO\nqc7CGuMP+Jqr/cE54/aSHg8boTwxkMp11Ykb+ng17fl57MHTM2RJ99qZ1KBkXezR\nuH1lyvjzeJPxEFr9rkUqc4GH74/AgfbgaFvQc8TS7ovEa5I/7Pg04m7vLSEYc6UF\nYJYxXKrzmZT2TDoKeJzaBBx5MFLhW19l68h9dQ8hJXIpTP0hJrpI+Sr6VUAEfFQC\ndIDRiFcgjz6j7T/x8anqh63/hpsyf2PMYph1+4/fxtSCWJdvf+9jCRM8F1IDfluX\n87gm+88KBNaklYpchmGIohbjivJyru41CsSLe0uinQFvA741W00w6JrcrOAX+hkS\nRQuK1dDVwGKoIY85KtTUiMcCAwEAAQ==\n- ----END PUBLIC KEY-----\n"
+ }
+ ],
+ ‘site’: {
+ ‘url’: ‘https://zothub.com’,
+ ‘directory_mode’: ‘primary’,
+ ‘directory_url’: ‘https://zothub.com/dirsearch’
+ }
+
+ }
+```
+
+Discovery returns a JSON array with the following components:
+
+‘success’ => (true or false) Operation was successful if true. Otherwise, there may be an optional ‘message’ indicating the cause of the error.
+
+‘signed_token’ => If a token parameter was specified in the request, it is prefixed with the text ‘token.’ and then RSA-signed and base64url-encoded with the private key of the channel and returned as ‘signed_token’.
+
+guid' => the guid of the address on the target system
+
+guid_sig’ => the RSA signature of the guid encoded with base64url, signed with the private key associated with this guid.
+
+‘key’ => the public key associated with this guid
+
+name' => name of the channel
+
+name_updated' => timestamp in MySQL style “2012-01-01 00:00:00”, when the name was last changed (UTC)
+
+address' => “webbie” or user@host address associated with this channel
+
+photo' => URL of a profile photo for this channel (ideally 175x175)
+
+photo_mimetype' => content type of the profile photo
+
+photo_updated' => MySQL-style timestamp of when the photo was last updated (UTC)
+
+‘url’ => location of the channel homepage
+
+‘connections_url’ => location of the URL for portable contacts (extended for Nomad) for this channel
+
+target' => if an authorisation target has been specified, it will be mirrored
+
+‘target_sig’ => if an authorisation target has been specified, the signature is mirrored
+
+‘searchable’ => (true or false) true means that this entry can be searched for in a directory
+
+##### Authorisations
+
+‘permissions’ => expandable array of permissions suitable for this target, values are true or false
+Permissions can include
+
+- view_stream
+- view_profile
+- view_photos
+- view_contacts
+- view_storage
+- view_pages
+- send_stream
+- post_wall
+- post_comments
+- post_mail
+- post_photos
+- tag_deliver
+- chat
+- write_storage
+- write_pages
+- delegate
+
+##### profile
+
+‘Profile’ => Array with important profile fields
+
+- description
+- birthday YYYY-MM-DD , all fields are optional, any field (such as year) may be zero
+- next_birthday => MySQL datetime string representing the next upcoming birthday, converted from the channel's default timezone to UTC.
+- gender (free form)
+- marital (marital status)
+- sexual (preference)
+- locale (city)
+- region (state)
+- postcode
+- country
+
+##### locations
+
+‘locations’ => Array of registered locations (DNS locations) from which this channel can be visible or can be booked
+
+Each location is an array of
+
+‘host’ => DNS host name, e.g. example.com
+
+‘address’ => the webbie or user@host identifier associated with this location
+
+‘primary’ => (true or false) whether this is the primary location for this channel where files and web pages are generally found
+
+‘url’ => url of the root directory of this DNS location, e.g. `https://example`.
+
+url_sig' => base64url encoded RSA signature of the URL, signed with the private key of the channel
+
+‘callback’ => Nomad communication endpoint on this site, normally `https://example.com/post`
+
+sitekey' => public key of this site/host
+
+##### site
+
+‘site’ => array specifying the directory role of the site responding to this request
+
+url' => url of this site e.g. `https://example`.
+
+directory_mode' => one of “primary”, “secondary”, “normal” or “standalone”
+
+directory_url' => if it is a directory server or a standalone site, the URL for the directory search module \ No newline at end of file
diff --git a/doc/en/developer/testing.md b/doc/en/developer/testing.md
index f7e8ffeba..3ca1ba0aa 100644
--- a/doc/en/developer/testing.md
+++ b/doc/en/developer/testing.md
@@ -1,12 +1,12 @@
-# Testing
+### Testing
Hubzilla uses [PHPUnit] for automated testing, often called _unit testing_ or _integration testing_.
The tests are written as PHP classes, and live under the `tests/unit` subdirectory of the main Hubzilla repository. This guide will explain how to run the tests, how the tests are structured, and how you can write your own tests.
-## Running the test suite
+#### Running the test suite
-### Installing the dependencies
+##### Installing the dependencies
To be able to run the tests you have to install the developer dependencies listen in the `composer.json` file. Make sure you have [composer installed] on your development system, and then run:
@@ -16,7 +16,7 @@ This will install phpunit and a few other dependencies. It will also update some
**Warning:** Do not commit the changes to the files in the `vendor/composer` directory to your repository!
-### Setting up the test database
+##### Setting up the test database
We have included a script (`tests/create_test_db.sh`) that will help you set up the test database. You can run it like this:
@@ -28,7 +28,7 @@ If you are running PostgreSQL instead, you create the test db like this:
The script make some assumptions about your setup, but everything is configurable using environment variables. If you need any customization, see the script source for the details.
-### Running the tests
+##### Running the tests
Once you have installed the developer dependencies and set up the test database, you can run the tests like this:
@@ -42,7 +42,7 @@ You can also run a specific test, or a specific set of tests using the `--filter
Will run any test mathcing "Autoname".
-### Generating coverage reports
+##### Generating coverage reports
To generate coverage reports you need a driver that is able to generate the coverage info that PHPUnit will collect. We recommend [Xdebug], but see the PHPUnit [page on code coverage analysis](https://docs.phpunit.de/en/9.6/code-coverage-analysis.html) for alternatives and details.
@@ -54,11 +54,11 @@ This will generate a number of HTML files in directories under the `tests/result
Open the `index.php file in your web browser to view the stats.
-### Debugging
+##### Debugging
With Xdebug installed, you can also do step debugging and a number of other things to debug and get information about the execution of the tests. See the [Xdebug] pages and your prefered editor for how to set this up.
-## Test structure and organization
+#### Test structure and organization
Tests are located in the `tests/unit` subdirectory, and subdirectories under there again, more or less reflecting the directory layout of the core code repository.
@@ -91,9 +91,9 @@ The class can also contain any number of other functions to keep things tidy and
Results and artifacts from the test runs will be left in the `tests/results/` directory. This will typically include the test log, code coverage report etc.
-### Hubzilla specific features
+#### Hubzilla specific features
-#### Test database access:
+##### Test database access:
Ideally it should be able to test each part of the code in isolation, where any dependencies should be replaced by stubs, mocks or fakes.
@@ -107,7 +107,7 @@ When the test finishes, the test database is wiped clean, so that we have the sa
All of this is handled by the `UnitTestCase` base class.
-#### Database fixtures:
+##### Database fixtures:
We need some predictable content in the database to set up things like logging, and other content that's useful in general for the tests. These are database fixtures that are loaded into the database for each test run.
@@ -115,16 +115,8 @@ The database fixtures are located in the `tests/unit/include/dba/_files` directo
While database fixtures are nice to have, we try to keep the number of them as minimal as possible. It's usually better to add any content needed for a specific test in the test itself.
-#### Fakes:
+##### Fakes:
Fakes are classes that we can pass to the code under test that will look and (to the code under test) behave the same as the original class. These are useful when we're able to pass objects to the code under test, as we can control it completely from the test code.
Fakes are located under the `tests/fakes` directory.
-
-## Writing your own tests
-
-To be done
-
-[PHPUnit]: https://phpunit.de
-[composer installed]: https://getcomposer.org/
-[Xdebug]: https://xdebug.org/ \ No newline at end of file
diff --git a/doc/en/developer/tools_workflows.md b/doc/en/developer/tools_workflows.md
new file mode 100644
index 000000000..ab55f75f8
--- /dev/null
+++ b/doc/en/developer/tools_workflows.md
@@ -0,0 +1,5 @@
+### Tools and workflows for developers
+
+#### Hub snapshots
+
+The [hub snapshots](/help/adminmanual/hub_snapshot_tools.md) page contains instructions and scripts for creating full snapshots of a hub to support switching between consistent and fully known states. This is useful to avoid situations where the content or database schema may be incompatible with the code.
diff --git a/doc/en/developer/translations.md b/doc/en/developer/translations.md
new file mode 100644
index 000000000..474fd392f
--- /dev/null
+++ b/doc/en/developer/translations.md
@@ -0,0 +1,51 @@
+### Translations
+
+Our translations are managed through Transifex. If you would like to help translate Hubzilla into another language, sign up at transifex.com, visit [Transifex](https://www.transifex.com/Friendica/hubzilla/?f=&zid=pepecyb@hub.hubzilla.hu) and apply to join one of the existing language teams or create a new one. Notify one of the lead developers if you have a translation update that needs merging, or ask if you can merge it yourself if you are familiar with Git and PHP. We have a string file called ‘messages.po’ which is gettext compatible, and a handful of email templates from which we automatically generate the application language files.
+
+#### The translation process
+
+The strings used in Hubzilla's user interface are translated at [Transifex](https://www.transifex.com/Friendica/hubzilla/?f=&zid=pepecyb@hub.hubzilla.hu) and then added to the Git repository on github. If you would like to help translate a language, be it correcting terms or translating Hubzilla into a currently unsupported language, please register an account on transifex.com and contact the translation team there.
+
+Translating Hubzilla is easy. Simply use the online tool on transifex. If you don't want to bother with Git & Co. it's no problem, we regularly check the status of the translations and import them into the source tree on github for others to use.
+
+We do not include every translation of transifex in the source tree to avoid a scattered and disrupted overall experience. As a rough estimate, we have a lower limit of 50% translated strings before we include the language. This limit is only based on the amount of translated strings, assuming that the most important strings for the user interface are translated first by a translation team. If you feel that your translation is usable before this limit, please contact us and we will likely include your team's work in the source tree.
+If you would like to add your work to the source tree yourself, please feel free to do so and contact us with any questions that arise. The process is simple and Hubzilla comes with all the necessary tools.
+
+The location of the translated files in the source tree is
+
+`/View/LNG-CODE/`
+
+where LNG-CODE is the code of the language used, e.g. de for German or fr for French. For the e-mail templates (the *.tpl files), simply place them in the directory and you're done. The translated strings come as an ‘hmessages.po’ file from Transifex, which needs to be translated into the PHP file that Hubzilla uses. To do this, place the file in the directory mentioned above and use the ‘po2php’ utility from the util directory of your Hubzilla installation.
+
+Assuming you want to convert the German localisation, which is located in view/en/hmessages.po, you would proceed as follows.
+
+1. At the command prompt, navigate to the base directory of your
+
+Hubzilla installation
+
+1. Execute the po2php script that translates the
+
+into the hstrings.php file used by Hubzilla.
+
+`$> php util/po2php.php view/en/hmessages.po`
+
+The output of the script will be placed in the view/en/hstrings.php file where froemdoca expects it, so you can test your translation immediately.
+
+1. Visit your Hubzilla page and check that it is in the language you just translated.
+
+language you have just translated. If not, try to find the error, probably PHP will give you a hint in the log/warnings.about the error.
+
+For debugging you can also try to ‘execute’ the file with PHP. This should give no output if the file is ok, but may give you a hint for the error in the file.
+
+`$> php view/en/hstrings.php`
+
+1. Commit the two files to your git repository with a meaningful commit message, push it to your fork of the Hubzilla repository on github and make a pull request for this commit.
+
+#### Utilities
+
+In addition to the po2php script, there are several other utilities for translation in the ‘util’ directory of the Hubzilla source tree. If you just want to translate Hubzilla into another language, you probably won't need any of these tools, but it will give you an idea of how Hubzilla's translation process works.
+See the utils/README file for more information.
+
+#### Known issues
+
+\* Hubzilla uses the language setting of the visitor's browser to set the language for the user interface. Most of the time this works, but there are some known quirks. * the early translations are based on the friendica translations, if you find some rough translations please let us know or correct them at Transifex. \ No newline at end of file
diff --git a/doc/en/developer/unorganized.md b/doc/en/developer/unorganized.md
index 5ba719226..e27581ce0 100644
--- a/doc/en/developer/unorganized.md
+++ b/doc/en/developer/unorganized.md
@@ -30,7 +30,7 @@ First, you'll need to create a new theme. This is in /view/theme, and I chose to
Oh, and don't forget to rename the _init function in /php/theme.php to be _init() instead of redbasic_init().
-At that point, if you need to add javascript or css files, add them to /js or /css, and then "register" them in _init() through head_add_js('file.js') and head_add_css('file.css').
+At that point, if you need to add javascript or css files, add them to /js or /css, and then "register" them in `_init()` through `head_add_js('file.js')` and `head_add_css('file.css')`.
Now you'll probably want to alter a template. These can be found in in /view/tpl OR view//tpl. All you should have to do is copy whatever you want to tweak from the first place to your theme's own tpl directory.
@@ -44,9 +44,9 @@ doing development.
Create your own github account.
-You may fork/clone the Red repository from [url=https://framagit.org/hubzilla/core.git]https://framagit.org/hubzilla/core.git[/url]
+You may fork/clone the hubzilla repository from https://framagit.org/hubzilla/core.git
-Follow the instructions provided here: [url=http://help.github.com/fork-a-repo/]http://help.github.com/fork-a-repo/[/url]
+Follow the instructions provided here: http://help.github.com/fork-a-repo/]http://help.github.com/fork-a-repo/
to create and use your own tracking fork on github
Then go to your github page and create a "Pull request" when you are ready
@@ -59,15 +59,15 @@ Please pull in any changes from the project repository and merge them with your
Also - **test your changes**. Don't assume that a simple fix won't break something else. If possible get an experienced Red developer to review the code.
-Further documentation can be found at the Github wiki pages at: [url=https://github.com/friendica/red/wiki]https://github.com/friendica/red/wiki[/url]
+Further documentation can be found at the Github wiki pages at: https://github.com/friendica/red/wiki
**Concensus Building**
Code changes which fix an obvious bug are pretty straight-forward. For instance if you click "Save" and the thing you're trying to save isn't saved, it's fairly obvious what the intended behaviour should be. Often when developing feature requests, it may affect large numbers of community members and it's possible that other members of the community won't agree with the need for the feature, or with your proposed implementation. They may not see something as a bug or a desirable feature.
-We encourage consensus building within the community when it comes to any feature which might be considered controversial or where there isn't unanimous decision that the proposed feature is the correct way to accomplish the task. The first place to pitch your ideas is to [url=https://zothub.com/channel/one]Channel One[/url]. Others may have some input or be able to point out facets of your concept which might be problematic in our environment. But also, you may encounter opposition to your plan. This doesn't mean you should stop and/or ignore the feature. Listen to the concerns of others and try and work through any implementation issues.
+We encourage consensus building within the community when it comes to any feature which might be considered controversial or where there isn't unanimous decision that the proposed feature is the correct way to accomplish the task. The first place to pitch your ideas is to [Channel One](https://zothub.com/channel/one)]. Others may have some input or be able to point out facets of your concept which might be problematic in our environment. But also, you may encounter opposition to your plan. This doesn't mean you should stop and/or ignore the feature. Listen to the concerns of others and try and work through any implementation issues.
There are places where opposition cannot be resolved. In these cases, please consider making your feature **optional** or non-default behaviour that must be specifically enabled. This technique can often be used when a feature has significant but less than unanimous support. Those who desire the feature can turn it on and those who don't want it - will leave it turned off.
If a feature uses other networks or websites and or is only seen as desirable by a small minority of the community, consider making the functionality available via an addon or plugin. Once again, those who don't desire the feature won't need to install it. Plugins are relatively easy to create and "hooks" can be easily added or modified if the current hooks do not do what is needed to allow your plugin to work.
-
+ ``
diff --git a/doc/en/developer/versions.md b/doc/en/developer/versions.md
new file mode 100644
index 000000000..00384b295
--- /dev/null
+++ b/doc/en/developer/versions.md
@@ -0,0 +1,22 @@
+### Versions and releases
+
+Hubzilla currently uses a standard version numbering sequence of $x.$y(.$z), for example ‘1.12’ or ‘1.12.1’. The first digit is the major version number. Major versions are released ‘approximately’ once a year, often in December.
+
+The second digit is the minor version number. If this number is odd, it is a development version. If the number is even, it is a released version. Minor versions are usually released once a month (moved from the development version to the major version) when development is ‘stable’, but this is likely to increase. In the future, minor releases will be released between one and three months; this corresponds to a stable code point and when there is a general consensus in the community that the current code base is stable enough to consider a release.
+
+The last digit is an interface or patch identifier.
+
+The release process involves changing the version number (by definition, the minor version number is odd, and the minor number is incremented). Once a year, the major version number of a major version is incremented and the minor version number is reset to 0.
+
+The version candidate is moved to a new branch and testing begins or continues for a period of 1-2 weeks, or until all major issues have been resolved. This branch is usually labelled RC (Release Candidate); for example, 1.8RC stands for the upcoming release of version 1.8. At this point, the version number of the development branch is increased to the next odd number. (For example 1.9). New developments can then take place in the development branch.
+
+Bug fixes should always be applied to ‘dev’ and transferred from there (usually with git cherry-pick) to the RC branch and, if necessary, to the master or official release branch.
+
+At the time a release candidate is created, the language string file is frozen until a new version is released. Translation work can continue, but all translations should be submitted to ‘dev’ and merged into RC.
+Once RC testing is complete, RC will be merged into ‘master’ and the RC version identifier removed; this will result in a final checkin to change the version number. The CHANGELOG file should also be updated at this point or shortly before. If there are conflicts during this final merge, the merge is cancelled and ‘git merge -s ours’ is applied. This results in the master branch being replaced by the content of the RC branch. Conflicts often arise due to string updates that were made to master after the last release and cannot simply be resolved without manual editing. As this is a release of tested code, manual editing is not recommended and the replacement merge strategy should be used instead. It is assumed that RC now contains the latest, well-tested code.
+
+Once the release is live and merged into the master branch, the RC branch can be removed.
+
+After the release, corrections can be made to master. If possible, these should be made in dev and ‘git cherry-pick’ should be used to merge; this preserves the commit information and avoids conflicts when merging in the next cycle. Only rarely does a patch only apply to the master branch. If necessary, this can be done. If the change is major, the version number of the interface should be increased. This is at the discretion of the community. In any case, a ‘git pull’ of the master branch should always result in the latest version, to which all patches are applied after release.
+
+The interface number (the $z in $x.$y.$z) should be incremented in dev whenever a change is made that alters the interfaces or API in an incompatible way, so that any external packages (especially addons and API clients) that rely on the current behaviour can detect their own interfaces at the point where it has changed and change them accordingly. \ No newline at end of file
diff --git a/doc/en/developer/who_is_a_hubzilla_developer.md b/doc/en/developer/who_is_a_hubzilla_developer.md
new file mode 100644
index 000000000..a6047788d
--- /dev/null
+++ b/doc/en/developer/who_is_a_hubzilla_developer.md
@@ -0,0 +1,14 @@
+### Who is a Hubzilla developer? Should I be reading this?
+
+Anyone who contributes to making Hubzilla better is a developer. There are many different and important ways you can contribute to this amazing technology, *even if you don't know how to write code*. The software itself is only one part of the Hubzilla project. You can contribute by
+
+- translating the text into your language so that people all over the world have the opportunity to use Hubzilla
+- Promote Hubzilla and spread awareness of the platform through blog posts, articles and word of mouth
+- Create artwork and graphics for project resources such as icons and marketing materials
+- Supporting the project infrastructure such as the project website and demo servers
+
+*Software developers* are of course welcome; there are so many great ideas that can be realised and not enough people to make them all happen! The Hubzilla codebase is an advanced and mature system, but the platform is still very flexible and open to new ideas.
+
+We are pretty relaxed when it comes to developers. We don't have a lot of rules. Some of us are overworked, and if you want to help, we're happy to let you help. However, if you follow a few guidelines, the process will be smoother and collaboration easier. All developers are expected to adhere to our [code of conduct](https://hub.hubzilla.hu/help/developer/covenant). We have developers from all over the world with different skills, different cultural backgrounds and different levels of patience. Our number one rule is to respect others. Sometimes this is difficult, and sometimes we have very different views on how things should work, but if everyone makes an effort, we will get along well.
+
+This document will help you get to know and help shape Hubzilla. \ No newline at end of file
diff --git a/doc/en/developer/zot_protocol.bb b/doc/en/developer/zot_protocol.bb
deleted file mode 100644
index e9355bca8..000000000
--- a/doc/en/developer/zot_protocol.bb
+++ /dev/null
@@ -1,478 +0,0 @@
-[h3] What is Zot?[/h3]
-Zot is the revolutionary protocol that powers $Projectname, providing [b]communications[/b], [b]identity management[/b], and [b]access control[/b] across a fully [b]decentralised[/b] network of independent websites, often called "the grid". The resulting platform is a robust system that supports privacy and security while enabling the kind of rich web services typically seen only in centralized, proprietary solutions.
-
-Consider this typical scenario:
-
-Jaquelina wishes to share photos with Roberto from her blog at [b]jaquelina.org[/b], but to nobody else. Roberto maintains his own family hub at [b]roberto.net[/b] on a completely independent server. Zot allows Jaquelina to publish her photos using an [i]access control list (ACL)[/i] that includes only Roberto. That means that while Roberto can see the photos when he visits her blog, his brother Marco cannot, and neither can any of his other family members who have accounts on [b]roberto.net[/b].
-
-The magic in this scenario comes from the fact that Roberto never logged in to Jaquelina's website. Instead, he had to login only once using his password on his [i]own[/i] website at [b]roberto.net[/b]. When Roberto visits [b]jaquelina.org[/b], her hub seamlessly authenticates him by remotely querying his server in the background.
-
-It is not uncommon for servers to have technical problems or become inaccessible for a variety of reasons. Zot provides robustness for Roberto's online activities by allowing him to have [i]clones[/i] of his online identity, or [i]channel[/i], on multiple independent hubs. Imagine that Roberto's server crashes for some reason and he cannot log in there. He simply logs in to one of his clones at [b]gadfly.com[/b], a site operated by his friend Peter. Once authenticated at [b]gadfly.com[/b], Roberto can view Jaquelina's blog as before, without Jaquelina having to grant any additional access!
-
-[h4] Communications[/h4]
-Communications and social networking are an integral part of the grid. Any channel (and any services provided by that channel) can make full use of feature-rich social communications on a global scale. These communications may be public or private - and private communications comprise not only fully encrypted transport, but also encrypted storage to help protect against accidental snooping and disclosure by rogue system administrators and internet service providers.
-
-Zot supports a wide array of background services in the grid, from friend suggestions to directory services. New content and data updates are propagated in the background between hubs across the grid according to access control lists and permissions specified by both sender [i]and[/i] receiver channels. Data is also synchronized between an arbitrary number of channel clones, allowing hub members to access data and continue collaborating seamlessly in the event that their primary hub is inaccessible or offline.
-
-[h4] Identity [/h4]
-Zot's identity layer is unique. It provides [b]invisible single sign-on[/b] across all sites in the grid.
-
-It also provides [b]nomadic identity[/b], so that your communications with friends, family, and or anyone else you're communicating with won't be affected by the loss of your primary communication node - either temporarily or permanently.
-
-The important bits of your identity and relationships can be backed up to a thumb drive, or your laptop, and may appear at any node in the grid at any time - with all your friends and preferences intact.
-
-Crucially, these nomadic instances are kept in sync so any instance can take over if another one is compromised or damaged. This protects you against not only major system failure, but also temporary site overloads and governmental manipulation or censorship.
-
-Nomadic identity, single sign-on, and $Projectname's decentralisation of hubs, we believe, introduce a high degree of degree of [b]resiliency[/b] and [b]persistence[/b] in internet communications, that are sorely needed amidst global trends towards corporate centralization, as well as mass and indiscriminate government surveillance and censorship.
-
-As you browse the grid, viewing channels and their unique content, you are seamlessly authenticated as you go, even across completely different server hubs. No passwords to enter. Nothing to type. You're just greeted by name on every new site you visit.
-
-How does Zot do that? We call it [b]magic-auth[/b], because $Projectname hides the details of the complexities that go into single sign-on logins, and nomadic identities, from the experience of browsing on the grid. This is one of the design goals of $Projectname: to increase privacy, and freedom on the web, while reducing the complexity and tedium brought by the need to enter new passwords and login names for every different sight that someone might visit online. You login only once on your home hub (or any nomadic backup hub you have chosen). This allows you to access any authenticated services provided anywhere in the grid - such as shopping, blogs, forums, and access to private information. Your password isn't stored on a thousand different sites; it is stored on servers that you control or that you have chosen to trust.
-
-You cannot be silenced. You cannot be removed from the grid unless you yourself choose to exit it.
-
-[h4] Access Control[/h4]
-Zot's identity layer allows you to provide fine-grained permissions to any content you wish to publish - and these permissions extend across the grid. This is like having one super huge website made up of an army of small individual websites - and where each channel in the grid can completely control their privacy and sharing preferences for any web resources they create.
-
-Currently, $Projectname supports access control for many types of data, including post/comment discussion threads, photo albums, events, cloud files, web pages, wikis, and more. Every object and how it is shared and with whom is completely under your control.
-
-This type of control is trivial on large corporate providers because they own the user database. Within the grid, there is no need for a huge user database on your machine - because the grid [b]is[/b] your user database. It has what is essentially infinite capacity (limited by the total number of hubs online across the internet), and is spread amongst hundreds, and potentially millions of computers.
-
-Access can be granted or denied for any resource, to any channel, or any group of channels; anywhere within the grid. Others can access your content if you permit them to do so, and they do not even need to have an account on your hub.
-
-[h3]Technical Introduction[/h3]
-Zot is a JSON-based web framework for implementing secure decentralised communications and services. In order to provide this functionality, Zot creates a decentralised globally unique identifier for each hub on the network. This global identifier is not linked inextricably to DNS, providing the requisite mobility. Many existing decentralised communications frameworks provide the communication aspect, but do not provide remote access control and authentication. Additionally most of these are based on 'webfinger', which still binds identity to domain names and cannot support nomadic identity.
-
-The primary issues Zot addresses are
-
-[list]
-[*] completely decentralised communications
-[*] independence from DNS-based identity
-[*] node mobility
-[*] seamless remote authentication
-[*] high performance
-[/list]
-We will rely on DNS-based user@host addresses as a "user-friendly" mechanism to let people know where you are, specifically on a named host with a given username, and communication will be carried out to DNS entities using TCP and the web.
-
-But the underlying protocol will provide an abstraction layer on top of this, so that a communications node (e.g. "identity") can move to an alternate DNS location and (to the best of our ability) gracefully recover from site re-locations and/or maintain pre-existing communication relationships. A side effect of this requirement is the ability to communicate from alternate/multiple DNS locations and service providers and yet maintain a single online identity.
-
-We will call this overlay network the "grid". Servers attached to this network are known as "hubs" and may support any number of individual identities.
-
-An identity does not necessarily correspond to a person. It is just something which requires the ability to communicate within the grid.
-
-The ability to recover will be accomplished by communication to the original location when creating a new or replacement identity, or as a fallback from a stored file describing the identity and their contacts in the case where the old location no longer responds.
-
-At least on the short term, the mobility of existing content is not a top priority. This may or may not take place at a later stage. The most important things we want to keep are your identity and your friends.
-
-Addresses which are shared amongst people are user@host, and which describe the [b]current[/b] local account credentials for a given identity. These are DNS based addresses and used as a seed to locate a given identity within the grid. The machine communications will bind this address to a globally unique ID. A single globally unique ID may be attached or bound to any number of DNS locations. Once an identity has been mapped or bound to a DNS location, communications will consist of just knowing the globally unique address, and what DNS (url) is being used currently (in order to call back and verify/complete the current communication). These concepts will be specified in better detail.
-
-In order for an identity to persist across locations, one must be able to provide or recover
-
-[list]
-[*] the globally unique ID for that identity
-[*] the private key assigned to that identity
-[*] (if the original server no longer exists) an address book of contacts for that identity.
-[/list]
-This information will be exportable from the original server via API, and/or downloadable to disk or thumb-drive.
-
-We may also attempt to recover with even less information, but doing so is prone to account hijacking and will require that your contacts confirm the change.
-
-In order to implement high performance communications, the data transfer format for all aspects of Zot is JSON. XML communications require way too much overhead.
-
-Bi-directional encryption is based on RSA 4096-bit keys expressed in DER/ASN.1 format using the PKCS#8 encoding variant, with AES encryption of variable length or large items. The precise encryption algorithms are negotiable between sites.
-
-Some aspects of well known "federation protocols" (webfinger, salmon, activitystreams, portablecontacts, etc.) may be used in zot, but we are not tied to them and will not be bound by them. $Projectname project is attempting some rather novel developments in decentralised communications and if there is any need to diverge from such "standard protocols" we will do so without question or hesitation.
-
-In order to create a globally unique ID, we will base it on a whirlpool hash of the identity URL of the origination node and a psuedo-random number, which should provide us with a 256 bit ID with an extremely low probability of collision (256 bits represents approximately 115 quattuorviginitillion or 1.16 X 10^77 unique numbers). This will be represented in communications as a base64url-encoded string. We will not depend on probabilities however and the ID must also be attached to a public key with public key cryptography used to provide an assurance of identity which has not been copied or somehow collided in whirlpool hash space.
-
-Basing this ID on DNS provides a globally unique seed, which would not be the case if it was based completely on psuedo-random number generation.
-
-We will refer to the encoded globally unique uid string as zot_uid
-
-As there may be more than one DNS location attached/bound to a given zot_uid identity, delivery processes should deliver to all of them - as we do not know for sure which hub instance may be accessed at any given time. However we will designate one DNS location as "primary" and which will be the preferred location to view web profile information.
-
-We must also provide the ability to change the primary to a new location. A look-up of information on the current primary location may provide a "forwarding pointer" which will tell us to update our records and move everything to the new location. There is also the possibility that the primary location is defunct and no longer responding. In that case, a location which has already been mapped to this zot_uid can seize control, and declare itself to be primary. In both cases the primary designation is automatically approved and moved. A request can also be made from a primary location which requests that another location be removed.
-
-In order to map a zot_uid to a second (or tertiary) location, we require a secure exchange which verifies that the new location is in possession of the private key for this zot_uid. Security of the private key is thus essential to avoid hijacking of identities.
-
-Communications will then require
-[list]
-[*] zot_uid (string)
-[*] uid_sig
-[*] callback (current location Zot endpoint url)
-[*] callback_sig
-[*] spec (int)
-[/list]
-passed with every communique. The spec is a revision number of the applicable Zot spec so that communications can be maintained with hubs using older and perhaps incompatible protocol specifications. Communications are verified using a stored public key which was copied when the connection to this zot_uid was first established.
-
-Key revocation and replacement must take place from the primary hub. The exact form for this is still being worked out, but will likely be a notification to all other bound hubs to "phone home" (to the primary hub) and request a copy of the new key. This communique should be verified using a site or hub key; as the original identity key may have been compromised and cannot be trusted.
-
-In order to eliminate confusion, there should be exactly one canonical url for any hub, so that these can be indexed and referenced without ambiguity.
-
-So as to avoid ambiguity of scheme, it is strongly encouraged that all addresses to be https with a "browser valid" cert and a single valid host component (either www.domain.ext or domain.ext, but not both), which is used in all communications. Multiple URLs may be provided locally, but only one unique URL should be used for all Zot communications within the grid.
-
-Test installation which do not connect to the public grid may use non-SSL, but all traffic flowing over public networks should be safe from session-hijacking, preferably with a "browser recognised" cert.
-
-Where possible, Zot encourages the use of "batching" to minimise network traffic between two hubs. This means that site 'A' can send multiple messages to site 'B' in a single transaction, and also consolidate deliveries of identical messages to multiple recipients on the same hub.
-
-Messages themselves may or may not be encrypted in transit, depending on the private nature of the messages. SSL (strongly encouraged) provides unconditional encryption of the data stream, however there is little point in encrypting public communications which have been designated as having unrestricted visibility. The encryption of data storage and so-called "end-to-end encryption" is outside the scope of zot. It is presumed that hub operators will take adequate safeguards to ensure the security of their data stores and these are functions of application and site integrity as opposed to protocol integrity.
-
-
-[h4]Messages[/h4]
-
-Given the constraints listed previously, a Zot communique should therefore be a json array of individual messages. These can be mixed and combined within the same transmission.
-
-Each message then requires:
-[list]
-[*] type
-[*] (optional) recipient list
-[/list]
-Lack of a recipient list would indicate an unencrypted public or site level message. The recipient list would contain an array of zot_uid with an individual decryption key, and a common iv. The decryption key is encoded with the recipient identity's public key. The iv is encrypted with the sender's private key.
-
-All messages should be digitally signed by the sender.
-
-The type can be one of (this list is extensible):
-[list]
-[*] post (or activity)
-[*] mail
-[*] identity
-[*] authenticate
-[/list]
-Identity messages have no recipients and notify the system social graph of an identity update, which could be a new or deleted identity, a new or deleted location, or a change in primary hub. The signature for these messages uses system keys as opposed to identity-specific keys.
-
-Posts include many different types of activities, such as top-level posts, likes/dislikes, comments, tagging activities, etc. These types are indicated within the message sturcture.
-
-authenticate messages result in mutual authentication and browser redirect to protected resources on the remote hub such as the ability to post wall-to-wall messages and view private photo albums and events, etc.
-
-[h4]Discovery[/h4]
-
-A well-known url is used to probe a hub for Zot capabilities and identity lookups, including the discovery of public keys, profile locations, profile photos, and primary hub location.
-
-The location for this service is /.well-known/zot-info - and must be available at the root of the chosen domain.
-
-To perform a lookup, a POST request is made to the discovery location with the following parameters:
-
-Required:
-
-address => an address on the target system such as "john"
-
-Optional
-
-target => the Zot "guid" of the observer for evaluating permissions
-
-target_sig => an RSA signature (base64url encoded) of the guid
-
-key => The public key needed to verify the signature
-
-token => a string (possibly random) chosen by the requesting service. If provided, an entry in the discovered packet will be provided called 'signed_token' which consists of the base64url_encoded RSA signature of the concatenation of the string 'token.' and the provided token using the private key of the discovered channel. This can be verified using the provided 'key' entry, and provides assurance that the server is in possession of the private key for the discovered identity. After 2017-01-01 it is [b]required[/b] that a server provide a signed_token [i]if[/i] a token was provided in the request.
-
-With no target provided, the permissions returned will be generic permissions
-for unknown or unauthenticated observers
-
-Example of discovery packet for 'mike@zothub.com'
-[code nowrap]
- {
-
- "success": true,
- "signed_token": "KBJrKTq1qrctNuxF3GwVh3GAGRqmgkirlXANPcJZAeWlvSt_9TMV097slR4AYnYCBEushbVqHEJ9Rb5wHTa0HzMbfRo8cRdl2yAirvvv5d98dtwHddQgX1jB0xEypXtmIYMdPGDLvhI1RNdIBhHkkrRcNreRzoy4xD--HM6m1W0-A8PJJJ9BcNxmGPcBtLzW08wzoP9trJ3M7DQ6Gkk6j7iwVsyApw1ZBaDvabGTdc_SFV-Iegtqw3rjzT_xXWsfzMlKBy-019MYn_KS-gu23YzjvGu5tS_zDfkQb8DMUlPLz5yyxM0yOMlUDtG2qQgIJAU2O0X6T5xDdJ6mtolNyhepg845PvFDEqBQGMIH1nc47CNumeudDi8IWymEALhjG_U8KAK7JVlQTJj2EKUb0au1g6fpiBFab5mmxCMtZEX3Jreyak5GOcFFz-WpxuXJD9TdSoIvaBfBFOoJnXkg2zE4RHXeQzZ2FotmrbBG5dm8B-_6byYGoHBc08ZsWze1K96JIeRnLpBaj6ifUDcVHxZMPcGHHT27dvU2PNbgLiBjlAsxhYqkhN5qOHN8XBcg2KRjcMBaI3V0YMxlzXz5MztmZq3fcB1p-ccIoIyMPMzSj3yMB7J9CEU2LYPSTHMdPkIeDE6GaCkQKviaQQJQde346tK_YjA2k7_SOBmvPYE",
- "guid": "sebQ-IC4rmFn9d9iu17m4BXO-kHuNutWo2ySjeV2SIW1LzksUkss12xVo3m3fykYxN5HMcc7gUZVYv26asx-Pg",
- "guid_sig": "Llenlbl4zHo6-g4sa63MlQmTP5dRCrsPmXHHFmoCHG63BLq5CUZJRLS1vRrrr_MNxr7zob_Ykt_m5xPKe5H0_i4pDj-UdP8dPZqH2fqhhx00kuYL4YUMJ8gRr5eO17vsZQ3XxTcyKewtgeW0j7ytwMp6-hFVUx_Cq08MrXas429ZrjzaEwgTfxGnbgeQYQ0R5EXpHpEmoERnZx77VaEahftmdjAUx9R4YKAp13pGYadJOX5xnLfqofHQD8DyRHWeMJ4G1OfWPSOlXfRayrV_jhnFlZjMU7vOdQwHoCMoR5TFsRsHuzd-qepbvo3pzvQZRWnTNu6oPucgbf94p13QbalYRpBXKOxdTXJrGdESNhGvhtaZnpT9c1QVqC46jdfP0LOX2xrVdbvvG2JMWFv7XJUVjLSk_yjzY6or2VD4V6ztYcjpCi9d_WoNHruoxro_br1YO3KatySxJs-LQ7SOkQI60FpysfbphNyvYMkotwUFI59G08IGKTMu3-GPnV1wp7NOQD1yzJbGGEGSEEysmEP0SO9vnN45kp3MiqbffBGc1r4_YM4e7DPmqOGM94qksOcLOJk1HNESw2dQYWxWQTBXPfOJT6jW9_crGLMEOsZ3Jcss0XS9KzBUA2p_9osvvhUKuKXbNztqH0oZIWlg37FEVsDs_hUwUJpv2Ar09k4",
- "key": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7QCwvuEIwCHjhjbpz3Oc\ntyei/Pz9nDksNbsc44Cm8jxYGMXsTPFXDZYCcCB5rcAhPPdZSlzaPkv4vPVcMIrw\n5cdX0tvbwa3rNTng6uFE7qkt15D3YCTkwF0Y9FVZiZ2Ko+G23QeBt9wqb9dlDN1d\nuPmu9BLYXIT/JXoBwf0vjIPFM9WBi5W/EHGaiuqw7lt0qI7zDGw77yO5yehKE4cu\n7dt3SakrXphL70LGiZh2XGoLg9Gmpz98t+gvPAUEotAJxIUqnoiTA8jlxoiQjeRK\nHlJkwMOGmRNPS33awPos0kcSxAywuBbh2X3aSqUMjcbE4cGJ++/13zoa6RUZRObC\nZnaLYJxqYBh13/N8SfH7d005hecDxWnoYXeYuuMeT3a2hV0J84ztkJX5OoxIwk7S\nWmvBq4+m66usn6LNL+p5IAcs93KbvOxxrjtQrzohBXc6+elfLVSQ1Rr9g5xbgpub\npSc+hvzbB6p0tleDRzwAy9X16NI4DYiTj4nkmVjigNo9v2VPnAle5zSam86eiYLO\nt2u9YRqysMLPKevNdj3CIvst+BaGGQONlQalRdIcq8Lin+BhuX+1TBgqyav4XD9K\nd+JHMb1aBk/rFLI9/f2S3BJ1XqpbjXz7AbYlaCwKiJ836+HS8PmLKxwVOnpLMbfH\nPYM8k83Lip4bEKIyAuf02qkCAwEAAQ==\n-----END PUBLIC KEY-----\n",
- "name": "Mike Macgirvin",
- "name_updated": "2012-12-06 04:59:13",
- "address": "mike@zothub.com",
- "photo_mimetype": "image/jpeg",
- "photo": "https://zothub.com/photo/profile/l/1",
- "photo_updated": "2012-12-06 05:06:11",
- "url": "https://zothub.com/channel/mike",
- "connections_url": "https://zothub.com/poco/mike",
- "target": "",
- "target_sig": "",
- "searchable": false,
- "permissions": {
- "view_stream": true,
- "view_profile": true,
- "view_photos": true,
- "view_contacts": true,
- "view_storage": true,
- "view_pages": true,
- "send_stream": false,
- "post_wall": false,
- "post_comments": false,
- "post_mail": false,
- "post_photos": false,
- "tag_deliver": false,
- "chat": false,
- "write_storage": false,
- "write_pages": false,
- "delegate": false
- },
- "profile": {
- "description": "Freedom Fighter",
- "birthday": "0000-05-14",
- "next_birthday": "2013-05-14 00:00:00",
- "gender": "Male",
- "marital": "It's complicated",
- "sexual": "Females",
- "locale": "",
- "region": "",
- "postcode": "",
- "country": "Australia"
- },
- "locations": [
- {
- "host": "zothub.com",
- "address": "mike@zothub.com",
- "primary": true,
- "url": "https://zothub.com",
- "url_sig": "eqkB_9Z8nduBYyyhaSQPPDN1AhSm5I4R0yfcFxPeFpuu17SYk7jKD7QzvmsyahM5Kq7vDW6VE8nx8kdFYpcNaurqw0_IKI2SWg15pGrhkZfrCnM-g6A6qbCv_gKCYqXvwpSMO8SMIO2mjQItbBrramSbWClUd2yO0ZAceq3Z_zhirCK1gNm6mGRJaDOCuuTQNb6D66TF80G8kGLklv0o8gBfxQTE12Gd0ThpUb5g6_1L3eDHcsArW_RWM2XnNPi_atGNyl9bS_eLI2TYq0fuxkEdcjjYx9Ka0-Ws-lXMGpTnynQNCaSFqy-Fe1aYF7X1JJVJIO01LX6cCs-kfSoz29ywnntj1I8ueYldLB6bUtu4t7eeo__4t2CUWd2PCZkY3PKcoOrrnm3TJP5_yVFV_VpjkcBCRj3skjoCwISPcGYrXDufJxfp6bayGKwgaCO6QoLPtqqjPGLFm-fbn8sVv3fYUDGilaR3sFNxdo9mQ3utxM291XE2Pd0jGgeUtpxZSRzBuhYeOybu9DPusID320QbgNcbEbEImO8DuGIxuVRartzEXQF4WSYRdraZzbOqCzmU0O55P836JAfrWjgxTQkXlYCic-DBk-iE75JeT72smCtZ4AOtoFWCjZAABCw42J7JELY9APixZXWriKtjy6JI0G9d3fs6r7SrXr1JMy0",
- "callback": "https://zothub.com/post",
- "sitekey": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1IWXwd/BZuevq8jzNFoR\n3VkenduQH2RpR3Wy9n4+ZDpbrUKGJddUGm/zUeWEdKMVkgyllVA/xHdB7jdyKs1X\nuIet9mIdnzvhdLO/JFD5hgbNG2wpSBIUY6aSNeCFTzszqXmuSXMW5U0Ef5pCbzEA\nnhoCoGL1KAgPqyxnGKUlj7q2aDwC9IRNtAqNyFQL67oT91vOQxuMThjlDhbR/29Q\ncYR4i1RzyahgEPCnHCPkT2GbRrkAPjNZAdlnk9UesgP16o8QB3tE2j50TVrbVc/d\nYRbzC56QMPP9UgUsapNeSJBHji75Ip/E5Eg/kfJC/HEQgyCqjCGfb7XeUaeQ7lLO\nqc7CGuMP+Jqr/cE54/aSHg8boTwxkMp11Ykb+ng17fl57MHTM2RJ99qZ1KBkXezR\nuH1lyvjzeJPxEFr9rkUqc4GH74/AgfbgaFvQc8TS7ovEa5I/7Pg04m7vLSEYc6UF\nYJYxXKrzmZT2TDoKeJzaBBx5MFLhW19l68h9dQ8hJXIpTP0hJrpI+Sr6VUAEfFQC\ndIDRiFcgjz6j7T/x8anqh63/hpsyf2PMYph1+4/fxtSCWJdvf+9jCRM8F1IDfluX\n87gm+88KBNaklYpchmGIohbjivJyru41CsSLe0uinQFvA741W00w6JrcrOAX+hkS\nRQuK1dDVwGKoIY85KtTUiMcCAwEAAQ==\n-----END PUBLIC KEY-----\n"
- }
- ],
- "site": {
- "url": "https://zothub.com",
- "directory_mode": "primary",
- "directory_url": "https://zothub.com/dirsearch"
- }
-
- }
-[/code]
-
-
-Discovery returns a JSON array with the following components:
-
-'success' => (true or false) Operation was successful if true. Otherwise an optional 'message' may be present indicating the source of error.
-
-'signed_token' => If a token parameter was provided in the request, it is prepended with the text 'token.' and then RSA signed with the channel private key and base64url encoded and returned as 'signed_token'.
-
-'guid' => the guid of the address on the target system
-
-'guid_sig' => the base64url encoded RSA signature of the guid, signed with the private key associated with that guid.
-
-'key' => the public key associated with that guid
-
-'name' => channel name
-
-'name_updated' => MySQL style timestamp '2012-01-01 00:00:00' when the name was last changed (UTC)
-
-'address' => "webbie" or user@host address associated with this channel
-
-'photo' => URL of a profile photo for this channel (ideally 175x175)
-
-'photo_mimetype' => content-type of the profile photo
-
-'photo_updated' => MySQL style timestamp when photo was last updated (UTC)
-
-'url' => location of channel homepage
-
-'connections_url' => location of Portable Contacts (extended for zot) URL for this channel
-
-'target' => if a permissions target was specified, it is mirrored
-
-'target_sig' => if a permissions target was specified, the signature is mirrored.
-
-'searchable' => (true or false) true indicates this entry can be searched in a directory
-
-[h5]Permissions[/h5]
-
-'permissions' => extensible array of permissions appropriate to this target, values are true or false
-
- Permissions may include:
-[list]
-[*] view_stream
-[*] view_profile
-[*] view_photos
-[*] view_contacts
-[*] view_storage
-[*] view_pages
-[*] send_stream
-[*] post_wall
-[*] post_comments
-[*] post_mail
-[*] post_photos
-[*] tag_deliver
-[*] chat
-[*] write_storage
-[*] write_pages
-[*] delegate
-[/list]
-
-
-[h5]Profile[/h5]
-
-
-'profile' => array of important profile fields
-[list]
-[*] description
-[*] birthday YYYY-MM-DD , all fields are optional, any field (such as year) may be zero
-[*] next_birthday => MySQL datetime string representing the next upcoming birthday, converted from the channel's default timezone to UTC.
-[*] gender (free form)
-[*] marital (marital status)
-[*] sexual (preference)
-[*] locale (city)
-[*] region (state)
-[*] postcode
-[*] country
-[/list]
-
-[h5]Locations[/h5]
-
-
-'locations' => array of registered locations (DNS locations) this channel may be visible or may be posting from
-
-Each location is an array of
-
-'host' => DNS hostname, e.g. example.com
-
-'address' => the webbie or user@host identifier associated with this location
-
-'primary' => (true or false) whether or not this is the primary location for this channel where files and web pages are generally found
-
-'url' => url of the root of this DNS location e.g. https://example.com
-
-'url_sig' => base64url encoded RSA signature of the URL, signed with the channel private key
-
-'callback' => Zot communications endpoint on this site, usually https://example.com/post
-
-'sitekey' => public key of this site/host
-
-
-[h5]Site[/h5]
-
-
-'site' => array providing the directory role of the site responding to this request
-
-'url' => url of this site e.g. https://example.com
-
-'directory_mode' => one of 'primary', 'secondary', 'normal', or 'standalone'
-
-'directory_url' => if this is a directory server or standalone, the URL for the directory search module
-
-
-
-[h3]Magic Auth[/h3]
-
-So-called "magic auth" takes place by a special exchange. On the remote computer, a redirection is made to the Zot endpoint with special GET parameters.
-
-Endpoint: https://example.com/post/name
-
-where 'name' is the left hand side of the channel webbie, for instance 'mike' where the webbie is 'mike@zothub.com'
-
-Additionally four parameters are supplied:
-[list]
-[*] auth => the webbie of the person requesting access
-[*] dest => the desired destination URL (urlencoded)
-[*] sec => a random string which is also stored locally for use during the verification phase.
-[*] version => the Zot revision
-[/list]
-When this packet is received, a Zot message is initiated to the auth identity:
-
-[code nowrap]
- {
- "type":"auth_check",
- "sender":{
- "guid":"kgVFf_1_SSbyqH-BNWjWuhAvJ2EhQBTUdw-Q1LwwssAntr8KTBgBSzNVzUm9_RwuDpxI6X8me_QQhZMf7RfjdA",
- "guid_sig":"PT9-TApzpm7QtMxC63MjtdK2nUyxNI0tUoWlOYTFGke3kNdtxSzSvDV4uzq_7SSBtlrNnVMAFx2_1FDgyKawmqVtRPmT7QSXrKOL2oPzL8Hu_nnVVTs_0YOLQJJ0GYACOOK-R5874WuXLEept5-KYg0uShifsvhHnxnPIlDM9lWuZ1hSJTrk3NN9Ds6AKpyNRqf3DUdz81-Xvs8I2kj6y5vfFtm-FPKAqu77XP05r74vGaWbqb1r8zpWC7zxXakVVOHHC4plG6rLINjQzvdSFKCQb5R_xtGsPPfvuE24bv4fvN4ZG2ILvb6X4Dly37WW_HXBqBnUs24mngoTxFaPgNmz1nDQNYQu91-ekX4-BNaovjDx4tP379qIG3-NygHTjFoOMDVUvs-pOPi1kfaoMjmYF2mdZAmVYS2nNLWxbeUymkHXF8lT_iVsJSzyaRFJS1Iqn7zbvwH1iUBjD_pB9EmtNmnUraKrCU9eHES27xTwD-yaaH_GHNc1XwXNbhWJaPFAm35U8ki1Le4WbUVRluFx0qwVqlEF3ieGO84PMidrp51FPm83B_oGt80xpvf6P8Ht5WvVpytjMU8UG7-js8hAzWQeYiK05YTXk-78xg0AO6NoNe_RSRk05zYpF6KlA2yQ_My79rZBv9GFt4kUfIxNjd9OiV1wXdidO7Iaq_Q",
- "url":"http:\/\/podunk.edu",
- "url_sig":"T8Bp7j5DHHhQDCFcAHXfuhUfGk2P3inPbImwaXXF1xJd3TGgluoXyyKDx6WDm07x0hqbupoAoZB1qBP3_WfvWiJVAK4N1FD77EOYttUEHZ7L43xy5PCpojJQmkppGbPJc2jnTIc_F1vvGvw5fv8gBWZvPqTdb6LWF6FLrzwesZpi7j2rsioZ3wyUkqb5TDZaNNeWQrIEYXrEnWkRI_qTSOzx0dRTsGO6SpU1fPWuOOYMZG8Nh18nay0kLpxReuHCiCdxjXRVvk5k9rkcMbDBJcBovhiSioPKv_yJxcZVBATw3z3TTE95kGi4wxCEenxwhSpvouwa5b0hT7NS4Ay70QaxoKiLb3ZjhZaUUn4igCyZM0h6fllR5I6J_sAQxiMYD0v5ouIlb0u8YVMni93j3zlqMWdDUZ4WgTI7NNbo8ug9NQDHd92TPmSE1TytPTgya3tsFMzwyq0LZ0b-g-zSXWIES__jKQ7vAtIs9EwlPxqJXEDDniZ2AJ6biXRYgE2Kd6W_nmI7w31igwQTms3ecXe5ENI3ckEPUAq__llNnND7mxp5ZrdXzd5HHU9slXwDShYcW3yDeQLEwAVomTGSFpBrCX8W77n9hF3JClkWaeS4QcZ3xUtsSS81yLrp__ifFfQqx9_Be89WVyIOoF4oydr08EkZ8zwlAsbZLG7eLXY"
- },
- "recipients":{
- {
- "guid":"ZHSqb3yGar3TYV_o9S-JkD-6o_V4DhUcxtv0VeyX8Kj_ENHPI_M3SyAUucU835-mIayGMmTpqJz3ujPkcavVhA",
- "guid_sig":"JsAAXigNghTkkbq8beGMJjj9LBKZn28hZ-pHSsoQuwYWvBJ2lSnfc4r9l--WgO6sucH-SR6RiBo78eWn1cZrh_cRMu3x3LLx4y-tjixg-oOOgtZakkBg4vmOhkKPkci0mFtzvUrpY4YHySqsWTuPwRx_vOlIYIGEY5bRXpnkNCoC8J4EJnRucDrgSARJvA8QQeQQL0H4mWEdGL7wlsZp_2VTC6nEMQ48Piu6Czu5ThvLggGPDbr7PEMUD2cZ0jE4SeaC040REYASq8IdXIEDMm6btSlGPuskNh3cD0AGzH2dMciFtWSjmMVuxBU59U1I6gHwcxYEV6BubWt_jQSfmA3EBiPhKLyu02cBMMiOvYIdJ3xmpGoMY1Cn__vhHnx_vEofFOIErb6nRzbD-pY49C28AOdBA5ffzLW3ss99d0A-6GxZmjsyYhgJu4tFUAa7JUl84tMbq28Tib0HW6qYo6QWw8K1HffxcTpHtwSL5Ifx0PAoGMJsGDZDD1y_r9a4vH5pjqmGrjL3RXJJUy-m4eLV5r7xMWXsxjqu3D8r04_dcw4hwwexpMT1Nwf8CTB0TKb8ElgeOpDFjYVgrqMYWP0XdhatcFtAJI7gsS-JtzsIwON9Kij66-VAkqy_z1IXI0ziyqV1yapSVYoUV1vMScRZ_nMqwiB5rEDx-XLfzko"
- }
- }
- "callback":"\/post",
- "version":1,
- "secret":"1eaa6613699be6ebb2adcefa5379c61a3678aa0df89025470fac871431b70467",
- "secret_sig":"eKV968b1sDkOVdSMi0tLRtOhQw4otA8yFKaVg6cA4I46_zlAQGbFptS-ODiZlSAqR7RiiZQv4E2uXCKar52dHo0vvNKbpOp_ezWYcwKRu1shvAlYytsflH5acnDWL-FKOOgz5zqLLZ6cKXFMoR1VJGG_Od-DKjSwajyV9uVzTry58Hz_w0W2pjxwQ-Xv11rab5R2O4kKSW77YzPG2R5E6Q7HN38FrLtyWD_ai3K9wlsFOpwdYC064dk66X7BZtcIbKtM6zKwMywcfJzvS5_0U5yc5GGbIY_lY6SViSfx9shOKyxkEKHfS29Ynk9ATYGnwO-jnlMqkJC7t149H-sI9hYWMkLuCzaeLP56k2B2TmtnYvE_vHNQjzVhTwuHCIRVr-p6nplQn_P3SkOpYqPi3k_tnnOLa2d3Wtga8ClEY90oLWFJC3j2UkBf_VEOBNcg-t5XO3T-j9O4Sbk96k1Qoalc-QlznbGx4bOVsGkRBBMiH4YUqiiWB_OkFHtdqv7dqGeC-u-B4u9IxzYst46vvmyA3O-Q4APSZ1RY8ITUH0jLTbh6EAV7Oki8pIbOg0t56p-8RlanOZqmFvR-grVSc7Ak1ZcD8NACmvidUpa1B7WEvRcOeffx9lype0bt5XenDnMyx6szevwxZIiM8qGM2lsSk4fu8HI9cW0mLywzZT0"
- }
-[/code]
-
-auth_check messages MUST be encrypted. This message is sent to the origination site, which checks the 'secret' to see if it is the same as the 'sec' which it passed originally. It also checks the secret_sig which is the secret signed by the destination channel's private key and base64url encoded. If everything checks out, a json packet is returned:
-[code nowrap]
- {
- "success":1,
- "confirm":"q0Ysovd1uQRsur2xG9Tg6bC23ynzw0191SkVd7CJcYoaePy6e_v0vnmPg2xBUtIaHpx_aSuhgAkd3aVjPeaVBmts6aakT6a_yAEy7l2rBydntu2tvrHhoVqRNOmw0Q1tI6hwobk1BgK9Pm0lwOeAo8Q98BqIJxf47yO9pATa0wktOg6a7LMogC2zkkhwOV5oEqjJfeHeo27TiHr1e2WaphfCusjmk27V_FAYTzw05HvW4SPCx55EeeTJYIwDfQwjLfP4aKV-I8HQCINt-2yxJvzH7Izy9AW-7rYU0Il_gW5hrhIS5MTM12GBXLVs2Ij1CCLXIs4cO0x6e8KEIKwIjf7iAu60JPmnb_fx4QgBlF2HLw9vXMwZokor8yktESoGl1nvf5VV5GHWSIKAur3KPS2Tb0ekNh-tIk9u-xob4d9eIf6tge_d3aq1LcAtrDBDLk8AD0bho5zrVuTmZ9k-lBVPr_DRHSV_dlpu088j3ThaBsuV1olHK3vLFRhYCDIO0CqqK5IuhqtRNnRaqhlNN6fQUHpXk2SwHiJ2W36RCYMTnno6ezFk_tN-RA2ly-FomNZoC5FPA9gFwoJR7ZmVFDmUeK3bW-zYTA5vu15lpBPnt7Up_5rZKkr0WQVbhWJmylqOuwuNWbn3SrMQ8rYFZ23Tv300cOfKVgRBaePWQb4"
- }
-[/code]
-'confirm' in this case is the base64url encoded RSA signature of the concatenation of 'secret' with the base64url encoded whirlpool hash of the source guid and guid_sig; signed with the source channel private key. This prevents a man-in-the-middle from inserting a rogue success packet. Upon receipt and successful verification of this packet, the destination site will redirect to the original destination URL and indicate a successful remote login.
-
-[h3]Zot Structures[/h3]
-[h4]Zot Signatures[/h4]
-All signed data in Zot is accomplished by performing an RSA sign operation using the private key of the initiator. The binary result is then base64url encoded for transport.
-[h4]Zot Encryption[/h4]
-Encryption is currently provided by AES256CTR. Additional algorithms MAY be supported. A 32-octet key and 16-octet initialisation vector are randomly generated. The desired data is then encrypted using these generated strings and the result base64url encoded. Then we build an array:
-
-[dl terms="b"]
-[*= data]The base64url encoded encrypted data
-[*= alg]The chosen algorithm, in this case the string 'aes256ctr'.
-[*= key]The randomly generated key, RSA encrypted using the recipients public key, and the result base64url encoded
-[*= iv]The randomly generated initialization vector, RSA encrypted using the recipient's public key, and the result base64url encoded
-[/dl]
-
-[h4]Basic Zot Packet[/h4]
-Used for initiating a dialogue with another Zot site. This packet MAY be encrypted. The presence of an array element 'iv' indicates encryption has been applied. When sending an 'auth_check' packet type, this packet MUST be encrypted, using the public key of the destination site (the site key, as opposed to a sender key).
-
-[code nowrap]
- {
- "type":"notify",
- "sender":{
- "guid":"kgVFf_1_SSbyqH-BNWjWuhAvJ2EhQBTUdw-Q1LwwssAntr8KTBgBSzNVzUm9_RwuDpxI6X8me_QQhZMf7RfjdA",
- "guid_sig":"PT9-TApzpm7QtMxC63MjtdK2nUyxNI0tUoWlOYTFGke3kNdtxSzSvDV4uzq_7SSBtlrNnVMAFx2_1FDgyKawmqVtRPmT7QSXrKOL2oPzL8Hu_nnVVTs_0YOLQJJ0GYACOOK-R5874WuXLEept5-KYg0uShifsvhHnxnPIlDM9lWuZ1hSJTrk3NN9Ds6AKpyNRqf3DUdz81-Xvs8I2kj6y5vfFtm-FPKAqu77XP05r74vGaWbqb1r8zpWC7zxXakVVOHHC4plG6rLINjQzvdSFKCQb5R_xtGsPPfvuE24bv4fvN4ZG2ILvb6X4Dly37WW_HXBqBnUs24mngoTxFaPgNmz1nDQNYQu91-ekX4-BNaovjDx4tP379qIG3-NygHTjFoOMDVUvs-pOPi1kfaoMjmYF2mdZAmVYS2nNLWxbeUymkHXF8lT_iVsJSzyaRFJS1Iqn7zbvwH1iUBjD_pB9EmtNmnUraKrCU9eHES27xTwD-yaaH_GHNc1XwXNbhWJaPFAm35U8ki1Le4WbUVRluFx0qwVqlEF3ieGO84PMidrp51FPm83B_oGt80xpvf6P8Ht5WvVpytjMU8UG7-js8hAzWQeYiK05YTXk-78xg0AO6NoNe_RSRk05zYpF6KlA2yQ_My79rZBv9GFt4kUfIxNjd9OiV1wXdidO7Iaq_Q",
- "url":"http:\/\/podunk.edu",
- "url_sig":"T8Bp7j5DHHhQDCFcAHXfuhUfGk2P3inPbImwaXXF1xJd3TGgluoXyyKDx6WDm07x0hqbupoAoZB1qBP3_WfvWiJVAK4N1FD77EOYttUEHZ7L43xy5PCpojJQmkppGbPJc2jnTIc_F1vvGvw5fv8gBWZvPqTdb6LWF6FLrzwesZpi7j2rsioZ3wyUkqb5TDZaNNeWQrIEYXrEnWkRI_qTSOzx0dRTsGO6SpU1fPWuOOYMZG8Nh18nay0kLpxReuHCiCdxjXRVvk5k9rkcMbDBJcBovhiSioPKv_yJxcZVBATw3z3TTE95kGi4wxCEenxwhSpvouwa5b0hT7NS4Ay70QaxoKiLb3ZjhZaUUn4igCyZM0h6fllR5I6J_sAQxiMYD0v5ouIlb0u8YVMni93j3zlqMWdDUZ4WgTI7NNbo8ug9NQDHd92TPmSE1TytPTgya3tsFMzwyq0LZ0b-g-zSXWIES__jKQ7vAtIs9EwlPxqJXEDDniZ2AJ6biXRYgE2Kd6W_nmI7w31igwQTms3ecXe5ENI3ckEPUAq__llNnND7mxp5ZrdXzd5HHU9slXwDShYcW3yDeQLEwAVomTGSFpBrCX8W77n9hF3JClkWaeS4QcZ3xUtsSS81yLrp__ifFfQqx9_Be89WVyIOoF4oydr08EkZ8zwlAsbZLG7eLXY"
- "sitekey":"-----BEGIN PUBLIC KEY-----
-MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxTeIwXZWrw/S+Ju6gewh
-LgkKnNNe2uCUqCqMZoYgJar3T5sHCDhvXc4dDCbDkxVIaA/+V1mURtBV60a3IGjn
-OAO0W0XGGLe2ED7G5o9U8T9mVGq8Mauv0v1oQ5wIR1gEAhBavkQ2OUGuF/YKn2nj
-HlKsv9HzUAHpcDMUe3Uklc2RhQbMcnJxEgkyjCkDyrTtCZzISkTAocHvpCG1KSog
-njUZdiz9UWxvM4rCFkCJvQU4RwRZJb7GA9ul+9JrF7NvUQTx8csRP2weBk1E9yyj
-wbe187E0eVj9RXX2Mx3mYhgrTdodxLOVMSXZLg1/SMpeFFl7QBhuM0SiOPg8a7Et
-e2iNA/RD4WiUFqCDfafasRa1TOozOm7LA+08lkAh5PeQPJsJbrX0wVVft++Y+5/z
-BvcUOP73vcbz7j5hJ7HLsbQtye/UUCfODBFybuDqRM84Aet8rjZohX7vukXdMD4I
-2HuB7pjR4uIfyYr0J63ANkvbsn8LR+RnirmHrK5H/OgxxjXcfYbGEQgFxvxhF6lA
-FpMu6Do4dx3CIb6pRmZ8bjSImXexJ0BSo9n3gtrz0XYLecsYFlQ9+QQjm83qxyLb
-M23in0xqMVsyQvzjNkpImrO/QdbEFRIIMee83IHq+adbyjQR49Z2hNEIZhkLPc3U
-2cJJ2HkzkOoF2K37qwIzk68CAwEAAQ==
------END PUBLIC KEY-----
-"
- },
- "recipients":{
- {
- "guid":"lql-1VnxtiO4-WF0h72wLX1Fu8szzHDOXgQaTbELwXW77k8AKFfh-hYr70vqMrc3SSvWN-Flrc5HFhRTWB7ICw",
- "guid_sig":"PafvEL0VpKfxATxlCqDjfOeSIMdmpr3iU7X-Sysa1h5LzDpjSXsjO37tYZL-accb1M5itLlfnW5epkTa5I4flsW21zSY1A2jCuBQUTLLGV7rNyyBy7lgqJUFvAMRx0TfXzP9lcaPqlM9T1tA6jfWOsOmkdzwofGeXBnsjGfjsO2xdGYe6vwjOU0DSavukvzDMnOayB9DekpvDnaNBTxeGLM45Skzr7ZEMcNF7TeXMbnvpfLaALYEKeQs9bGH-UgAG8fBWgzVAzeBfx_XSR1rdixjyiZGP0kq0h35SlmMPcEjliodOBFwMXqpXFB7Ibp4F6o6te2p2ErViJccQVG8VNKB6SbKNXY6bhP5zVcVsJ-vR-p4xXoYJJvzTN7yTDsGAXHOLF4ZrXbo5yi5gFAlIrTLAF2EdWQwxSGyLRWKxG8PrDkzEzX6cJJ0VRcLh5z6OI5QqQNdeghPZbshMFMJSc_ApCPi9_hI4ZfctCIOi3T6bdgTNKryLm5fhy_eqjwLAZTGP-aUBgLZpb1mf2UojBn6Ey9cCyq-0T2RWyk-FcIcbV4qJ-p_8oODqw13Qs5FYkjLr1bGBq82SuolkYrXEwQClxnrfKa4KYc2_eHAXPL01iS9zVnI1ySOCNJshB97Odpooc4wk7Nb2Fo-Q6THU9zuu0uK_-JbK7IIl6go2qA"
- },
- },
- "callback":"\/post",
- "version":"1.2",
- "encryption":{
- "aes256ctr"
- },
- "secret":"1eaa6613699be6ebb2adcefa5379c61a3678aa0df89025470fac871431b70467",
- "secret_sig":"0uShifsvhHnxnPIlDM9lWuZ1hSJTrk3NN9Ds6AKpyNRqf3DUdz81-Xvs8I2kj6y5vfFtm-FPKAqu77XP05r74vGaWbqb1r8zpWC7zxXakVVOHHC4plG6rLINjQzvdSFKCQb5R_xtGsPPfvuE24bv4fvN4ZG2ILvb6X4Dly37WW_HXBqBnUs24mngoTxFaPgNmz1nDQNYQu91-ekX4-BNaovjDx4tP379qIG3-NygHTjFoOMDVUvs-pOPi1kfaoMjmYF2mdZAmVYS2nNLWxbeUymkHXF8lT_iVsJSzyaRFJS1Iqn7zbvwH1iUBjD_pB9EmtNmnUraKrCU9eHES27xTwD-yaaH_GHNc1XwXNbhWJaPFAm35U8ki1Le4WbUVRluFx0qwVqlEF3ieGO84PMidrp51FPm83B_oGt80xpvf6P8Ht5WvVpytjMU8UG7-js8hAzWQeYiK05YTXk-78xg0AO6NoNe_RSRk05zYpF6KlA2yQ_My79rZBv9GFt4kUfIxNjd9OiV1wXdidO7Iaq_Q"
- }
-[/code]
-
-[dl terms="b"]
-[*= type] The message type: [b]notify, purge, refresh, force_refresh, auth_check, ping[/b] or [b]pickup[/b]. The packet contents vary by message type. Here we will describe the [b]notify[/b] packet.
-[*= callback]A string to be appended onto the url which identifies the Zot communications endpoint on this system. It is typically the string "/post".
-[*= version]The Zot protocol identifier, to allow future protocol revisions to co-exist.
-[*= encryption] array of supported encryption algorithms, order by decreasing preference. If no compatible encryption methods are provided, applications MUST use 'aes256cbc'.
-[*= secret]A 64-char string which is randomly generated by the sending site.
-[*= secret_sig]The RSA signature of the secret, signed with the sender's private key.
-[*= sender] An array of four components that provide a portable identity. We can contact the URL provided and download a Zot info packet to obtain the public key of the sender, and use that to verify the sender guid and the posting URL signatures.
- [dl terms="b"]
- [*= guid]Typically a 64 character base64url encoded string. This is generated when an identity is created and an attempt is made that it be unique; though this isn't required.
- [*= guid_sig]The RSA signature of the guid, signed by the sender's private key and base64url encoded.
- [*= url]The base url of the location this post is originating from.
- [*= url_sig]The RSA signature of url, signed by the sender's private key and base64url encoded.
- [*= sitekey]The public key of the website specified in the url
- [/dl]
-[*= recipients] Only used for private messages. An array of envelope recipients. Each recipient is represented by an array of guid and guid_sig. When recipients are specified, the entire packet is also encapsulated using a negotiated cryptographic algorithm or 'aes256cbc' if none could be negotiated.
- [dl terms="b"]
- [*= guid]The guid of a private recipient.
- [*= guid_sig]The RSA signature of the guid, signed by the recipient's private key and base64url encoded
- [/dl]
-[/dl]
diff --git a/doc/en/developer/zot_protocol.md b/doc/en/developer/zot_protocol.md
new file mode 100644
index 000000000..c734ab9eb
--- /dev/null
+++ b/doc/en/developer/zot_protocol.md
@@ -0,0 +1,44 @@
+### The Nomad protocol
+
+#### What is Nomad?
+
+Nomad is the revolutionary protocol that powers Hubzilla, enabling **communication**, **identity management** and **access control** across a fully **decentralised** network of independent websites, often referred to as ‘the grid’. The resulting platform is a robust system that supports privacy and security while enabling the kind of rich web services typically found only in centralised, proprietary solutions.
+
+Consider this typical scenario:
+
+Jaquelina wants to share photos from her blog at **jaquelina.org** with Roberto, but with no one else. Roberto maintains his own family hub at **roberto.net** on a completely independent server. Nomad allows Jaquelina to publish her photos with an *access control list (ACL)* that only includes Roberto. This means that while Roberto can see the photos when he visits her blog, his brother Marco cannot, nor can any other family member who has an account on **roberto.net**.
+
+The twist in this scenario is the fact that Roberto never logged in to Jaquelina's website. Instead, he only had to log in once with his password on his *own* **roberto.net** website. When Roberto visits **jaquelina.org**, he is seamlessly authenticated by their hub by querying his server in the background.
+
+It's not uncommon for servers to have technical issues or become inaccessible for various reasons. Nomad provides robustness to Roberto's online activities by allowing him to have *clones* of his online identity or *channel* on multiple independent hubs. Imagine that Roberto's server goes down for some reason and he can no longer log in there. He simply logs into one of his clones on **gadfly.com**, a website run by his friend Peter. Once he has authenticated himself at **gadfly.com**, Roberto can view Jaquelina's blog as before, without Jaquelina having to grant additional access!
+
+#### Communication
+
+Communication and social networks are an essential part of the grid. Any channel (and any service provided by that channel) can take full advantage of feature-rich social communication on a global scale. These communications can be public or private - and private communications include not only fully encrypted transport, but also encrypted storage to protect against accidental snooping and disclosure by rogue system administrators and ISPs.
+
+Nomad supports a wide range of background services in the grid, from friend suggestions to directory services. New content and data updates are passed in the background between hubs across the grid according to the access control lists and permissions set by the *sender and* receiver channels. Data is also synchronised between any number of channel clones so that hub members can access data and continue to collaborate seamlessly even if their primary hub is unavailable or offline.
+
+#### Identity
+
+Nomad's identity layer is unique. It provides an **invisible single sign-on** for all locations in the grid.
+It also provides a **nomadic identity** so that your communication with friends, family or other people you communicate with is not affected by the loss of your primary communication hub - either temporarily or permanently.
+
+The important parts of your identity and relationships can be backed up on a USB stick or your laptop and appear on any node on the network at any time - with all your friends and preferences.
+Crucially, these nomadic instances are kept synchronised so that any instance can take over if another is compromised or corrupted. This not only protects you from major system failures, but also from temporary website overload and government tampering or censorship.
+
+We believe that Hubzilla's nomadic identity, single sign-on and decentralisation bring a high level of **resilience** and **consistency** to internet communications, which is much needed in the face of global trends towards corporate centralisation and mass and indiscriminate government surveillance and censorship.
+When browsing the web, viewing channels and their unique content, you are seamlessly authenticated, even across completely different server hubs. No need to enter passwords. You don't have to type anything. You are simply greeted with your name on every new page you visit.
+
+How does this work with Nomad? We call it **‘magic-auth’** because Hubzilla hides the details of the complexity of single sign-on logins and nomadic identities from web browsing. This is one of Hubzilla's design goals: to increase privacy and freedom on the Internet while reducing the complexity and tedium of having to enter new passwords and login names every time you visit the Internet. You only log in once to your home hub (or a nomadic backup hub of your choice). This allows you to access all authenticated services offered anywhere on the web - such as shopping, blogs, forums and access to private information. Your password is not stored on a thousand different websites, but on servers that you control or trust.
+
+They cannot be silenced. They cannot be removed from the network unless you choose to leave it yourself.
+
+#### Access control
+
+Nomad's identity layer allows you to assign fine-grained permissions to any content you want to publish - and these permissions extend across the entire grid. It's like having a huge website made up of an army of small individual websites - where each channel in the grid can fully control its privacy and sharing preferences for all the web resources it creates.
+
+Currently, Hubzilla supports access control for many types of data, including discussion posts and comments, photo albums, events, cloud files, web pages, wikis and more. Each item and how and with whom it is shared is completely under your control.
+
+This type of control is trivial with large enterprise providers as they own the user database. In the Grid, you don't need a huge user database on your computer - because the Grid **is** your user database. It has essentially infinite capacity (limited by the total number of hubs online on the Internet) and is distributed across hundreds, possibly even millions of computers.
+
+Access can be granted or denied to any resource, channel or group of channels - anywhere on the grid. Others can access your content if you allow them to, and they don't even need to have an account in your hub. \ No newline at end of file
diff --git a/doc/en/developer/zot_structures.md b/doc/en/developer/zot_structures.md
new file mode 100644
index 000000000..b96279a97
--- /dev/null
+++ b/doc/en/developer/zot_structures.md
@@ -0,0 +1,110 @@
+### Nomad structures
+
+#### Nomad signatures
+
+All signed data in Nomad is generated by an RSA signature operation with the initiator's private key. The binary result is then encoded for transport with base64url.
+
+#### Nomad encryption
+
+Encryption is currently performed using AES256CTR. Other algorithms MAY be supported. A 32-octet key and a 16-octet initialisation vector are generated at random. The desired data is then encoded with these generated strings and the result is base64url encoded. An array is then created:
+
+- data
+ The base64url-encoded encrypted data
+- alg
+ The selected algorithm, in this case the character string ‘aes256ctr’.
+- key
+ The randomly generated key, RSA-encrypted with the recipient's public key, and the base64url-encoded result
+- iv
+ The randomly generated initialisation vector, RSA-encrypted with the recipient's public key, and the base64url-encoded result
+
+#### Basic Nomad packet
+
+Used to initiate a dialogue with another Nomad site. This packet MAY be encrypted. The presence of an array element ‘iv’ indicates that encryption has been performed. When sending an ‘auth_check’ packet, this packet MUST be encrypted, using the target site's public key (the site key, as opposed to a sender key).
+
+```
+ {
+ ‘type’: ‘notify’,
+ ‘sender’:{
+ ‘guid’: ‘kgVFf_1_SSbyqH-BNWjWuhAvJ2EhQBTUdw-Q1LwwssAntr8KTBgBSzNVzUm9_RwuDpxI6X8me_QQhZMf7RfjdA’,
+ ‘guid_sig’: "PT9-TApzpm7QtMxC63MjtdK2nUyxNI0tUoWlOYTFGke3kNdtxSzSvDV4uzq_7SSBtlrNnVMAFx2_1FDgyKawmqVtRPmT7QSXrKOL2oPzL8Hu_nnVVTs_0YOLQJJ0GYACOOK- R5874WuXLEept5-KYg0uShifsvhHnxnPIlDM9lWuZ1hSJTrk3NN9Ds6AKpyNRqf3DUdz81- Xvs8I2kj6y5vfFtm-FPKAqu77XP05r74vGaWbqb1r8zpWC7zxXakVVOHHC4plG6rLINjQzvdSFKCQb5R_xtGsPPfvuE24bv4fvN4ZG2ILvb6X4Dly37WW_HXBqBnUs24mngoTxFaPgNmz1nDQNYQu91- ekX4-BNaovjDx4tP379qIG3-NygHTjFoOMDVUvs-pOPi1kfaoMjmYF2mdZAmVYS2nNLWxbeUymkHXF8lT_iVsJSzyaRFJS1Iqn7zbvwH1iUBjD_pB9EmtNmnUraKrCU9eHES27xTwD- yaaH_GHNc1XwXNbhWJaPFAm35U8ki1Le4WbUVRluFx0qwVqlEF3ieGO84PMidrp51FPm83B_oGt80xpvf6P8Ht5WvVpytjMU8UG7-js8hAzWQeYiK05YTXk-78xg0AO6NoNe_RSRk05zYpF6KlA2yQ_My79rZBv9GFt4kUfIxNjd9OiV1wXdidO7Iaq_Q’,
+ ‘url’: ‘http:\/\/podunk.edu’,
+ ‘url_sig’: "T8Bp7j5DHHhQDCFcAHXfuhUfGk2P3inPbImwaXXF1xJd3TGgluoXyyKDx6WDm07x0hqbupoAoZB1qBP3_WfvWiJVAK4N1FD77EOYttUEHZ7L43xy5PCpojJQmkppGbPJc2jnTIc_F1vvGvw5fv8gBWZvPqTdb6LWF6FLrzwesZpi7j2rsioZ3wyUkqb5TDZaNNeWQrIEYXrEnWkRI_qTSOzx0dRTsGO6SpU1fPWuOOYMZG8Nh18nay0kLpxReuHCiCdxjXRVvk5k9rkcMbDBJcBovhiSioPKv_yJxcZVBATw3z3TTE95kGi4wxCEenxwhSpvouwa5b0hT7NS4Ay70QaxoKiLb3ZjhZaUUn4igCyZM0h6fllR5I6J_sAQxiMYD0v5ouIlb0u8YVMni93j3zlqMWdDUZ4WgTI7NNbo8ug9NQDHd92TPmSE1TytPTgya3tsFMzwyq0LZ0b- g- zSXWIES__jKQ7vAtIs9EwlPxqJXEDDniZ2AJ6biXRYgE2Kd6W_nmI7w31igwQTms3ecXe5ENI3ckEPUAq__llNnND7mxp5ZrdXzd5HHU9slXwDShYcW3yDeQLEwAVomTGSFpBrCX8W77n9hF3JClkWaeS4QcZ3xUtsSS81yLrp__ifFfQqx9_Be89WVyIOoF4oydr08EkZ8zwlAsbZLG7eLXY"
+ ‘sitekey’:"-----BEGIN PUBLIC KEY-----
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxTeIwXZWrw/S+Ju6gewh
+LgkKnNNe2uCUqCqMZoYgJar3T5sHCDhvXc4dDCbDkxVIaA/+V1mURtBV60a3IGjn
+OAO0W0XGGLe2ED7G5o9U8T9mVGq8Mauv0v1oQ5wIR1gEAhBavkQ2OUGuF/YKn2nj
+HlKsv9HzUAHpcDMUe3Uklc2RhQbMcnJxEgkyjCkDyrTtCZzISkTAocHvpCG1KSog
+njUZdiz9UWxvM4rCFkCJvQU4RwRZJb7GA9ul+9JrF7NvUQTx8csRP2weBk1E9yyj
+wbe187E0eVj9RXX2Mx3mYhgrTdodxLOVMSXZLg1/SMpeFFl7QBhuM0SiOPg8a7Et
+e2iNA/RD4WiUFqCDfafasRa1TOozOm7LA+08lkAh5PeQPJsJbrX0wVVft++Y+5/z
+BvcUOP73vcbz7j5hJ7HLsbQtye/UUCfODBFybuDqRM84Aet8rjZohX7vukXdMD4I
+2HuB7pjR4uIfyYr0J63ANkvbsn8LR+RnirmHrK5H/OgxxjXcfYbGEQgFxvxhF6lA
+FpMu6Do4dx3CIb6pRmZ8bjSImXexJ0BSo9n3gtrz0XYLecsYFlQ9+QQjm83qxyLb
+M23in0xqMVsyQvzjNkpImrO/QdbEFRIIMee83IHq+adbyjQR49Z2hNEIZhkLPc3U
+2cJJ2HkzkOoF2K37qwIzk68CAwEAAQ==
+-----END PUBLIC KEY-----
+"
+ },
+ ‘recipients’:{
+ {
+ ‘guid’: ‘lql-1VnxtiO4-WF0h72wLX1Fu8szzHDOXgQaTbELwXW77k8AKFfh-hYr70vqMrc3SSvWN-Flrc5HFhRTWB7ICw’,
+ ‘guid_sig’: "PafvEL0VpKfxATxlCqDjfOeSIMdmpr3iU7X-Sysa1h5LzDpjSXsjO37tYZL- accb1M5itLlfnW5epkTa5I4flsW21zSY1A2jCuBQUTLLGV7rNyyBy7lgqJUFvAMRx0TfXzP9lcaPqlM9T1tA6jfWOsOmkdzwofGeXBnsjGfjsO2xdGYe6vwjOU0DSavukvzDMnOayB9DekpvDnaNBTxeGLM45Skzr7ZEMcNF7TeXMbnvpfLaALYEKeQs9bGH- UgAG8fBWgzVAzeBfx_XSR1rdixjyiZGP0kq0h35SlmMPcEjliodOBFwMXqpXFB7Ibp4F6o6te2p2ErViJccQVG8VNKB6SbKNXY6bhP5zVcVsJ- vR-p4xXoYJJvzTN7yTDsGAXHOLF4ZrXbo5yi5gFAlIrTLAF2EdWQwxSGyLRWKxG8PrDkzEzX6cJJ0VRcLh5z6OI5QqQNdeghPZbshMFMJSc_ApCPi9_hI4ZfctCIOi3T6bdgTNKryLm5fhy_eqjwLAZTGP- aUBgLZpb1mf2UojBn6Ey9cCyq-0T2RWyk-FcIcbV4qJ-p_8oODqw13Qs5FYkjLr1bGBq82SuolkYrXEwQClxnrfKa4KYc2_eHAXPL01iS9zVnI1ySOCNJshB97Odpooc4wk7Nb2Fo-Q6THU9zuu0uK_-JbK7IIl6go2qA"
+ },
+ },
+ ‘callback’:‘\/post’,
+ ‘version’: ‘1.2’,
+ ‘encryption’:{
+ ‘aes256ctr’
+ },
+ ‘secret’:‘1eaa6613699be6ebb2adcefa5379c61a3678aa0df89025470fac871431b70467’,
+ ‘secret_sig’: "0uShifsvhHnxnPIlDM9lWuZ1hSJTrk3NN9Ds6AKpyNRqf3DUdz81-Xvs8I2kj6y5vfFtm- FPKAqu77XP05r74vGaWbqb1r8zpWC7zxXakVVOHHC4plG6rLINjQzvdSFKCQb5R_xtGsPPfvuE24bv4fvN4ZG2ILvb6X4Dly37WW_HXBqBnUs24mngoTxFaPgNmz1nDQNYQu91-ekX4-BNaovjDx4tP379qIG3-NygHTjFoOMDVUvs- pOPi1kfaoMjmYF2mdZAmVYS2nNLWxbeUymkHXF8lT_iVsJSzyaRFJS1Iqn7zbvwH1iUBjD_pB9EmtNmnUraKrCU9eHES27xTwD- yaaH_GHNc1XwXNbhWJaPFAm35U8ki1Le4WbUVRluFx0qwVqlEF3ieGO84PMidrp51FPm83B_oGt80xpvf6P8Ht5WvVpytjMU8UG7-js8hAzWQeYiK05YTXk-78xg0AO6NoNe_RSRk05zYpF6KlA2yQ_My79rZBv9GFt4kUfIxNjd9OiV1wXdidO7Iaq_Q"
+ }
+```
+
+type
+
+The message type: **notify, purge, refresh, force_refresh, auth_check, ping** or **pickup**. The content of the packets varies depending on the message type. The **notify packet** is described here.
+
+callback
+
+A character string that is appended to the URL and identifies the Nomad communication endpoint on this system. This is usually the character string ‘/post’.
+
+version
+
+The identifier of the Nomad protocol so that future protocol revisions can co-exist.
+
+encryption
+
+Array of supported encryption algorithms, ordered by decreasing preference. If no compatible encryption methods are specified, applications MUST use ‘aes256cbc’.
+
+secret
+
+A 64-character string randomly generated by the sending side.
+
+secret_sig
+
+The RSA signature of the secret, signed with the sender's private key.
+
+sender
+
+An array of four components that provide a portable identity. We can contact the given URL and download a Nomad info packet to obtain the sender's public key and use it to verify the sender's guid and the signatures of the sending URL.
+
+- guid
+ Usually a 64 character base64url encoded string. It is generated when an identity is created and an attempt is made to make it unique, but this is not required.
+- guid_sig
+ The RSA signature of the guid, signed with the sender's private key and base64url-encoded.
+- url
+ The base URL of the location from which this post originated.
+- url_sig
+ The RSA signature of the url, signed with the sender's private key and base64url encoded.
+- sitekey
+ The public key of the website specified in the url
+
+recipients
+
+Only used for private messages. An array of envelope recipients. Each recipient is represented by an array of guid and guid_sig. If recipients are specified, the entire packet is also encapsulated with a negotiated cryptographic algorithm or ‘aes256cbc’ if none could be negotiated.
+
+- guid
+ The guid of a private recipient.
+- guid_sig
+ The RSA signature of the guid, signed with the recipient's private key and base64url-encoded \ No newline at end of file