⌈⌋ ⎇ branch:  freshcode


Artifact [4bc8153593]

Artifact 4bc81535936ea89dc2449b0618b2bad59658c8c9:

Wiki page [API2] by mario 2015-04-14 10:54:51.
D 2015-04-14T10:54:51.994
L API2
N text/x-markdown
P 767cc525e6aa87baf7074c0fc780eb86453384ef
U mario
W 13306
State: ***design***, *testing*


## Simpler JSON API

To update and submit project records, there's going to be a simplified
JSON interface.

 * The testing API endpoint is <kbd>`https://test.freshcode.club/…`</kbd>,  
   which can be used for browsing as well.

 * The regular API endpoint is <kbd>`https://api.freshcode.club/…`</kbd>,  
   but is *currently* fixated on the test database too.

## URL scheme

Updating and release publishing can now be combined into one PUT/POST
request. The URL dict can now be embedded everywhere or passed alongside.


method	| URL path						|function+purpose
--------------------------------------------------------------------------------
GET	|`/projects/<name>.json`				|query all fields
PUT	|`/projects/<name>.json`				|update_core+release
CREATE	|`/projects/<name>.json`				|new_project+update
<s>POST	|<s>`/projects/<name>/releases.json`</s>		|<s>publish</s>	
DELETE	|`/projects/<name>/releases/<verstr>.json`*?auth_code=*	|withdraw version	
<s>PUSH	|<s>`/projects/<name>/urls.json`</s>			|<s>update_urls</s>
GET	|`/feed/<name>.json`					|release_list+federation

The <kbd>PUT</kbd> method likewise works with <kbd>POST</kbd> or
<kbd>PUSH</kbd> ("PUSH" because it's a programming site, and entries are
a stack). Fields are equivalent for the initializing <kbd>CREATE</kbd>.


## JSON object keys

Where the JSON field names are mapped as follows:

<style>
 .content table { width: 95%; }
 .content table tr td:nth-child(5) { color: #99c; font-style: italic; }
 .content table tr td:nth-child(3) { font-weight: bold; color: #272; } 
 .content table tr td:nth-child(1) { color: #bbb; font-weight: bold; }
</style>


 works with   |  freshcode DB   |  JSON field     | freecode-submit  | Sample
------------------------------------------------------------------------------------------
 CREATE       |  name           |  `<name>`       | Project          | unix-name
   PUT        |  title          |  title          | Project          | Foo Bar Gtk+
   PUT        |  summary        |  summary        | Summary          | short slogan
   PUT        |  description    |  description    | Description      | Long  text...
   PUT        |  tags         |`project_tag_list`:| Project-Tag-List | c, c++, cli
   PUT        |  license        | `license_list`: | License-List     | MITL, GNU GPL
   PUT, URL   |  homepage       |  urls {…}       | Homepage-URL     | http://exmpl
   PUT, URL   |  homepage       |  urls {…}       | Website-URL      | http://exmpl
   PUT, URL   |  image:         |  urls {…}       | Screenshot-URL   | http://png
   PUT, URL   |  autoupdate_url |  urls {…}       | Changelog-URL    | .../NEWS.md
   PUT, URL   |  urls {…}       |  urls {…}       | *******-URL      | Title = http://...
     RELEASE  |  download       |  download       | Download-URL     | http://sf.net
     RELEASE  |  version        |  version        | Version          | 1.0.3-rc5
     RELEASE  |  changes        |  changes        | Changes          | Added Xy. Fixed Zy.
     RELEASE  |  hidden         |`hidden_from_fp`:| Hide             | 0
     RELEASE  |  state        |`release_tag_list`:| Release-Tag-List | stable
     RELEASE  |  scope        |`release_tag_list`:| Release-Tag-List | minor, bugfix
 CREATE       |  submitter      |  author         | Author           | Bob
 CREATE       |  submitter_img  |  -              | Author           | Bob, bob@gitub
      -       |  editor_note    |  -              | -                | -  
      -       |  flag           |  -              | -                | -  
 CREATE       |  lock           |  `<auth_code>`  | <kbd>.netrc</kbd>| -
      -       |  social_links   |  -              | -                | -  
      -       |  autoupdate_*   |  -              | -                | -  
       DELETE |  name           |  name           | -P name          | -  
       DELETE |  deleted        |  -              | -d               | -  
<s>PENDING</s>|  t_published    |  created_at     | -q -d            | -  
<s>PENDING</s>|  t_changed      |  approved_at    | -q -d            | -  


- Renamed: `permalink` → `name`, and `changelog` → `changes`
- New: `title`, `summary` (oneliner), `urls` as dict {…}, `author` for `submitter`
- Changes: `project_tag_list` now CSV text instead of JSON list, same for
  `license_list` with spacing irrelevant
- Internal / Unassigned yet: `editor_note`, `flag`, `lock`, `social_links`,
  `autoupdate_***`


### Authorization:

All requests can append an `?auth_code=` to request URLs to carry a plain password.
Which is primarily used with the <kbd>DELETE</kbd> method. The <kbd>GET</kbd> method
only hides a few internal fields when unauthorized.

<kbd>POST</kbd>/<kbd>PUT</kbd>/etc. requests instead should wrap the
password outermost in the JSON payloadt:

    {
        "auth_code": "plain_pw_123",
        "project": {
            "key": "Value",
            ...
        }
    }


## Query <kbd>GET</kbd> `/projects/<name>.json`

Returns an almost literal database dump:

    {
        "project": {
            "name": "foo-bar",
            "title": "Foo Bar",
            "summary": "iCal-compatible calendaring app",
            "description": "Here comes a very long description ...",
            "image": "",
            "author": "Bob",
            "license_list": "MITL, CC-BY-SA",
            "project_tags": "desktop, c++, qt5, calendar",
            "homepage": "http://example.org",
            "download": "http://example.org/dwnld/",
            "urls": {
                "homepage": "http://example.org",
                "changelog": "https://example.org/downl/NEWS.md",
                "DEB": "http://example.org/downl/foo-bar_1.deb",
                "download": "http://example.org/dwnld/"
            },
            "version": "5.0.1",
            "state": "stable",
            "scope": "minor feature",
            "changes": "Fixed the thing, and added the stuff.",
            "download": "http://example.org/dwnld/",
            "t_published": "1427461501"
        },
	"$feed-origin": "http://freshcode.club/",
    	"$feed-license": "CC-BY-SA 3.0"
    }

The release fields (second half in the example) represent the latest
known version.

  * The URLs are partly duplicated. Because "homepage" and "download" are
    core fields, they show up in two places.
  * This GET response blob might carry a few more internal fields (autoupdate_*,
    lock, t_published, flag, editor_note) if an `?auth_code=` was supplied.


## Update core+release <kbd>PUT</kbd> `/projects/<name>.json`

For changing general project information, all fields can be sent wrapped
in the same structure. The only difference is the required `auth_code`.

    {
        "auth_code": "plain_pw_123",
        "project": {
            "title": "New Title",
            "summary": "Shorter project slogan",
            "description": "New and longer description...",
            "image": "http://new.png",
            "license_list": "BSDL",
            "project_tags": "qt6, dlang, desktop, calendar",
            "author": "Elise Exemplary, dj_ical@launchpad",
            "urls": {
                "homepage": "http://google-code.com",
                "DEB": "http://example.org/SECOND-REALEASE.deb",
                "download": "http://example.org/dwnld/"
            },
            "version": "6.0.2",
            "state": "stable",
            "scope": "minor bugfix",
            "changes": "Fixed the thing, and added the stuff.",
            "download": "http://example.org/dwnld/",
        }
    }

Now interestingly, this scheme can be used to:
 
 1. Just update the basic project description.
 2. Or publish new release "version" and "changes" right along.

Either, or, and both.


#### Sectioned variant

As variation of that, the JSON struct ***may*** be split into:

    {
        "auth_code": "plain_pw_123",
        "project": {
            "title": "New Title",
            "summary": "Shorter project slogan",
            "description": "New and longer description...",
            "image": "http://new.png",
            "license_tags": "BSDL",
            "project_tags": "qt6, dlang, desktop, calendar",
            "urls": {
                "homepage": "http://google-code.com",
                "DEB": "http://example.org/SECOND-REALEASE.deb",
                "download": "http://example.org/dwnld/"
            }
        },
        "release": {
            "version": "6.0.2",
            "state": "stable",
            "scope": "minor bugfix",
            "changes": "Fixed the thing, and added the stuff.",
            "download": "http://example.org/dwnld/",
            "hide": false,
        }
    }

It'll simply be rejoined server-side. Which doesn't make a difference
to the internal database scheme. Might be more convenient to implement.


#### URL section moved out

And as further variation, you can also split out the `url:{}` dict:

    {
        "auth_code": "plain_pw_123",
        "project": {
            "title": "New Title",
            "description": "................"
            "editor_note": "Please reset the social bookmark counter!
                            Project moved from Sourceforge to GitHub."
        },
        "urls": {
            "homepage": "http://example.org/",
            "proprietary-hoster": "http://github.com/proj/name/",
            "PYZ-package": "http://example.org/calendar.pyzw",
        }
        "release": {
            "version": "7.5.3",
            "changes": "Rome sprang up...",
        }
    }

The API is pretty much indifferent if this wraps up just the "project"
base information, a lone "urls" dict, or just a "release" or any
combination thereof.


## URLs dict <kbd>GET</kbd>/<kbd>PUSH</kbd> `/projects/<name>/urls.json`

There's still a separate API endpoint for just retrieving or updating
the URLs though:

    {
        "auth_code": "plain_pw_123",
        "urls": {
            "homepage": "http://example.org/",
            "image": "http://launchpad.com/proj/screenshot.png",
        }
    }

Note that a projects "homepage" or "download" or "image" URL only get
updated when listed herein. All other project links get completely
discarded and replaced by whatever is in the new list.

 * Incoming link titles are *free-form*.
 * The case is preserved for custom entries.
 * Non-word characters are replaced.
 * Titles will always be stored with "Dashed-Names" (it's internally
   a `Key=Url` text/yaml field).
 * The core URLs (homepage, download, screenshot) however are always
   lowercased (when returned on GET requests).
 * The API is indifferent if you pass the "homepage" or "download"
   link as literal `project:{…}` dict entry, or wrapped in `urls:{…}`.


## Release publishing <kbd>POST</kbd> `/projects/<name>/releases.json`

This is entirely redundant now. But a new release can be published
with that alternative URL scheme. It's basically identical to
"PUT `/projec/<name>.json`" now:

    {
        "auth_code": "plain_pw_123",
        "release": {
            "version": "0.0.1",
            "state": "beta",
            "scope": "cleanup",
            "changes": "Initial release. No docs or code.",
            "hidden": true,
        }
    }

Note that even the "hidden" field is already available with regular
project PUT / core updates.


## Withdraw_release <kbd>DELETE</kbd> `/projects/<name>/<versionstr>.json`

Now release retraction became simpler as well. There are no longer
arbitrary numeric IDs exposed. (They were faked anyway.)

Instead the *literal version number*  can now be used to delete
a release entry.

  -  <kbd>DELETE</kbd> `/projects/<name>/`*1.2.3-rc2*`.json?auth_code=pw123`

The version string has to be URL-encoded as needed of course.



## New_project <kbd>CREATE</kbd> `/projects/<name>.json`

The JSON payload for creating a new project might look familiar.
Well in fact, *it is* identical to the regular PUT payload:

    {
        "auth_code": "this:is-a/brand#new+password_567",
        "project": {
            "title": "Initial Title",
            "author": "Username, user@localhost",
            "summary": "ONELINER",
            "description": "Description REQUIRED.",
            "image": null,
            "license": null,
            "project_tags": "bash, script",
            "author": null,
            "urls": {
                "homepage": "http://example.org/",
            },
            "version": null,
        }
    }

The `null` fields are just for brevity. In fact the first project
submission *can and **should** even* contain a full record - including
the current release version/infos. (CREATE cannot be used to register
all-empty or stub project records.)

It can however also just be completed with the next <kbd>PUT</kbd>/Update.
The only requirements for <kbd>CREATE</kbd> are a new Unix project`<name>`
(taken from the request URL), and a "`title`" and "`description`",
"`license`" or "`tag_list`", and a "`homepage`" URL.

And obviously this is the only time the ‹`auth_code`› is used for
populating the internal authorization hash. All other requests just
compare it, but CREATE does the creative step.

Client SSL cert as CREATE spamguard: **Undecided** / *Testing*.  
See also [/doc/trunk/doc/submit.pem](doc/trunk/doc/submit.pem) for public
authorization key.


Z deec1a37abf9f48024ab5236a4c3e015