⌈⌋ ⎇ branch:  freshcode


Artifact [9d06251a9a]

Artifact 9d06251a9ac5fe0065aea517e8977f6f97fb1d5f:

Wiki page [API2] by mario 2015-04-13 19:27:12.
D 2015-04-13T19:27:12.431
L API2
N text/x-markdown
P 1b389a8ef3cddebaf68ba9c328010c9ee8ff448d
U mario
W 12328
State: ***design***, *testing*


## Simpler JSON API

To update and submit project records, there's going to be a simplified
JSON interface. Both JSON object keys and URLs are up for discussion.


## URL scheme

Updating and release publishing can now be combined into one PUT
request. The URL dict can now be embedded even. And DELETE works
with just the version string now, no arbitrary numeric `<id>`.

method	| URL path						|function	| state
----------------------------------------------------------------------------------------
GET	|`/projects/<name>.json`				|query		|kept
PUT	|`/projects/<name>.json`				|update_core	|combined
CREATE	|`/projects/<name>.json`				|new_project	|new
POST	|`/projects/<name>/releases.json`			|publish        |redundant
DELETE	|`/projects/<name>/releases/<verstr>.json`*?auth_code=*	|withdraw	|simpler
PUSH	|`/projects/<name>/urls.json`				|update_urls	|redundant
GET	|`/feed/<name>.json`					|release_list	|external


The POST .../releases.json and PUSH .../urls.json methods could really be
dropped.


## 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>


 method       |  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" is now just "name"
  * "changelog" became just "changes" now

New:

  * "title"
  * "summary"
  * "urls" as dict {…}, no more "approved_urls"
  * "submitter" for Author name, optional@email

Changes:

  * "project_tag_list" is now just a CSV text field, not JSON `[ ]` wrapped
  * same as "license_list" is now CSV, accepts "bsd,mitl" or "SPACE, LICENSE"

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.
Primarily this is 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 contain the
password wrapped in the JSON payload outermost:

    {
        "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",
            "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"
        }
    }

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 <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 Examplary, 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.


## 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.

    DELETE /projects/<name>/1.2.3-rc2.json?auth_code=pw123 HTTP/1.1

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



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

The JSON payload for creating a new project listing is also practically
identical to the regular PUT update.

    {
        "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.

It can however also just be completed with the next <kbd>PUT</kbd>
Update-core.
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 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.

SSL Spamguard: *Undecided* / *Testing*. See /doc/trunk/doc/submit.pem


Z 1f01d11c5cf6875e2b0c97af25fca2d4