<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Joltem — An Open Incubator - Medium]]></title>
        <description><![CDATA[Openly collaborate to build and launch a startup. — @thejolted - Medium]]></description>
        <link>https://medium.com/joltem-an-open-incubator?source=rss----fd44dd72da3d---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Joltem — An Open Incubator - Medium</title>
            <link>https://medium.com/joltem-an-open-incubator?source=rss----fd44dd72da3d---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 03:37:05 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/joltem-an-open-incubator" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Building a Git Server]]></title>
            <link>https://medium.com/joltem-an-open-incubator/building-a-git-server-1dfb89adca1d?source=rss----fd44dd72da3d---4</link>
            <guid isPermaLink="false">https://medium.com/p/1dfb89adca1d</guid>
            <dc:creator><![CDATA[Emil Davtyan]]></dc:creator>
            <pubDate>Fri, 11 Apr 2014 13:26:37 GMT</pubDate>
            <atom:updated>2016-06-17T18:49:32.325Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KYLnkd8XqOYy24hey9TY1A.jpeg" /></figure><h4>A dive into Twisted, SSH, &amp; Git</h4><p>Our intention was simple — enable people to <a href="https://github.com/emil2k/joltem">openly collaborate on projects that could turn into startups</a>. Groups would be open, dynamic, and grow with the popularity of a project.</p><p>We needed a place to store our code. The <a href="https://medium.com/joltem-an-open-incubator/c88d1154f1c6"><em>fork and pull </em>model did not meet our needs</a> so integrating with GitHub was not an option. <a href="https://medium.com/joltem-an-open-incubator/c88d1154f1c6">Our proposed access model</a> required branch level permissions. A makeshift <a href="http://gitolite.com/gitolite/index.html">Gitolite</a> solution proved to be buggy, difficult to test, and hard to setup.</p><p>Building our own git server was the best option. Our main requirement was that it would need to enforce branch level push permissions. Additionally, credentials such as <a href="http://en.wikipedia.org/wiki/RSA_%28cryptosystem%29">public RSA keys</a> would need to be stored in the database.</p><p>Tasked with building the Git server, I quickly found myself knee-deep in Twisted’s source. Several SSH RFCs helped me piece it together. While specifications of Git’s transfer protocols helped guide me towards a suitable solution. What follows is a distillation of what I learned.</p><h4><strong>Connections — Protocols, Factories, Services</strong></h4><p>With some Twisted basics we can make the server listen. <a href="http://twistedmatrix.com/documents/current/api/twisted.internet.protocol.Protocol.html">Protocol</a>s are used to manage a connection and receive data. Connections are represented by <a href="http://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.ITransport.html">ITransport</a> implementations.</p><p>With a buildProtocol method <a href="http://twistedmatrix.com/documents/current/api/twisted.internet.protocol.Factory.html">Factory</a> instances create Protocol instances for each connection. A <a href="http://twistedmatrix.com/documents/10.1.0/api/twisted.application.internet.html"><em>service</em></a><em> </em>is used to bind a Factory instance to a port.</p><p>SSHFactory is the base factory class for SSH. It has to be extended to provide the host keys used in the SSH handshake. The <a href="http://twistedmatrix.com/documents/current/api/twisted.conch.ssh.keys.Key.html">Key</a> class represents RSA or DSA keys.</p><p>The factory for our Git server ( we call it a “gateway” ) provides its RSA keys.</p><pre>from twisted.conch.ssh.keys import Key<br>from twisted.conch.ssh.factory import SSHFactory</pre><pre>from django.conf import settings</pre><pre>SERVER_PRIVATE_KEY = Key.fromFile(settings.GATEWAY_PRIVATE_KEY_FILE_PATH)<br>SERVER_PUBLIC_KEY = Key.fromFile(settings.GATEWAY_PUBLIC_KEY_FILE_PATH)</pre><pre><br>class GatewayFactory(SSHFactory):</pre><pre>    def getPrivateKeys(self):<br>        return {‘ssh-rsa’: SERVER_PRIVATE_KEY}</pre><pre>    def getPublicKeys(self):<br>        return {‘ssh-rsa’: SERVER_PUBLIC_KEY}</pre><p>We use a <a href="http://twistedmatrix.com/documents/current/api/twisted.application.internet.html">TCPServer</a> service to bind our factory to a port. To start the server as a daemon we put the following in a gateway.tac file :</p><pre>import sys<br>import os<br>os.environ.setdefault(“DJANGO_SETTINGS_MODULE”, “joltem.settings.local”)</pre><pre>from django.conf import settings <br>from gateway.libs.factory import factory<br>from twisted.application import service, internet</pre><pre>application = service.Application(“Gateway”)<br>internet.TCPServer(settings.GATEWAY_PORT, factory).setServiceParent(application)</pre><p>And then run <a href="http://twistedmatrix.com/documents/current/core/howto/basics.html">twistd</a> :</p><pre>twistd -y gateway.tac</pre><h4><strong>Authentication — Credentials, Realms, Portals</strong></h4><p>A user must present credentials when attempting to open up a connection. Twisted stores them in implementations of the <a href="http://twistedmatrix.com/documents/current/api/twisted.cred.credentials.ICredentials.html">ICredentials</a> class.</p><p>An implementation of <a href="https://twistedmatrix.com/documents/current/api/twisted.cred.checkers.ICredentialsChecker.html">ICredentialsChecker</a> is responsible for verifying the credentials. The requestAvatarId method should return an identification for the user or an UnauthorizedLogin exception. To deal with Twisted’s asynchronous nature, the returned value should be wrapped with the <a href="http://twistedmatrix.com/documents/8.1.0/api/twisted.internet.defer.succeed.html">success</a> ( a form of a <a href="http://twistedmatrix.com/documents/13.0.0/core/howto/defer.html">Deffered</a> ) function, while an exception should be wrapped with the <a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.python.failure.Failure.html">Failure</a> class.</p><p><a href="https://twistedmatrix.com/documents/current/api/twisted.cred.portal.IRealm.html">IRealm</a> implementations are responsible for creating an avatar instance representing the connected user. Identification provided by a ICredentialChecker are passed through its requestAvatar method to instantiate the avatar.</p><p>A <a href="http://twistedmatrix.com/documents/current/api/twisted.cred.portal.Portal.html">Portal</a> instance is used to attach multiple credential checkers to a realm. Credentials are funneled through a portal, checked against the first capable credentials checker, and if the login is successful create an avatar using the realm.</p><p>Since our users provide RSA keys as credentials we use the <a href="https://twistedmatrix.com/documents/current/api/twisted.cred.credentials.ISSHPrivateKey.html">ISSHPrivateKey</a> implementation of ICredentials in our credential checker.</p><pre>class GatewayCredentialChecker(object):</pre><pre>    implements(ICredentialsChecker)<br>    credentialInterfaces = (ISSHPrivateKey, )</pre><pre>    @staticmethod<br>    def requestAvatarId(credentials):<br>        … # check source ;)</pre><p>The requestAvatarId method checks whether it is a valid RSA key. If so computes a fingerprint and uses it to query the database for matching credentials. If successful it returns an instance of our Authentication model representing the RSA key.</p><p>The realm then uses an extension of the <a href="http://twistedmatrix.com/documents/current/api/twisted.conch.avatar.ConchUser.html">ConchUser</a> ( SSH specific avatar ) class to create an avatar instance.</p><pre>class GatewayUser(ConchUser):</pre><pre>     def __init__(self, key):<br>          ConchUser.__init__(self)<br>          self.user = key.user<br>          self.project = key.project</pre><pre>     @staticmethod<br>     def logout():<br>          pass</pre><pre><br>class GatewayRealm(object):</pre><pre>     implements(IRealm)</pre><pre>     @staticmethod<br>     def requestAvatar(authentication, mind, *interfaces):<br>         user = GatewayUser(authentication)<br>         return interfaces and interfaces[0] or None, user, user.logout</pre><p>Authentication is enabled by attaching our portal to our GatewayFactory instance.</p><pre>portal = Portal(GatewayRealm())<br>portal.registerChecker(GatewayCredentialChecker())<br>factory = GatewayFactory()<br>factory.portal = portal</pre><h4><strong>SSH — Channels, Sessions, Requests</strong></h4><p>A small primer on SSH and how Twisted implements it is required before proceeding.</p><p>In SSH, requests and data are transferred over <a href="http://tools.ietf.org/html/rfc4254#section-5"><em>channels</em></a><em> </em>:</p><blockquote><em>All terminal sessions, forwarded connections, etc., are channels. Either side may open a channel. Multiple channels are multiplexed into a single connection.</em></blockquote><p>To execute something on the remote end a <a href="http://tools.ietf.org/html/rfc4254#section-6"><em>session</em></a><em> </em>channel will have to be opened.</p><blockquote><em>A session is a remote execution of a program. The program may be a shell, an application, a system command, or some built-in subsystem. It may or may not have a tty, and may or may not involve X11 forwarding. Multiple sessions can be active simultaneously.</em></blockquote><p>Once the session is opened a <em>request </em>is sent to begin the session’s process. It can <em>either </em><a href="http://tools.ietf.org/html/rfc4254#section-6.5">run the default shell, execute a command, or open a subsystem</a>.</p><p>Since Git uses SSH to execute a command on the remote end, we are interested in the “exec” request :</p><pre> byte     SSH_MSG_CHANNEL_REQUEST<br> uint32   recipient channel<br> string   “exec”<br> boolean  want reply<br> string   command</pre><blockquote><em>This message will request that the server start the execution of the given command. The ‘command’ string may contain a path. Normal precautions MUST be taken to prevent the execution of unauthorized commands.</em></blockquote><p>Twisted represents channels and sessions with <a href="http://twistedmatrix.com/documents/current/api/twisted.conch.ssh.channel.SSHChannel.html">SSHChannel</a> and <a href="http://twistedmatrix.com/documents/current/api/twisted.conch.ssh.session.SSHSession.html">SSHSession</a> respectively. SSHChannel contains general methods to write and receive data from channels. SSHSession extends SSHChannel and handles session specific channel requests.</p><p>Instances of SSHSession contain a session attribute with an instance of an <a href="http://twistedmatrix.com/documents/current/api/twisted.conch.interfaces.ISession.html">ISession</a> implementing callbacks for processed session requests.</p><p>Our ISession implementation is initiated with a GatewayUser avatar an handles “exec” requests.</p><pre>class GatewaySessionInterface():</pre><pre>    implements(ISession)</pre><pre>    def __init__(self, avatar):<br>        self.avatar = avatar</pre><pre>    def execCommand(self, protocol, command_string):<br>        log.msg(“Execute command : %s” % command_string)</pre><p>We extend the SSHSession class so it will use GatewaySessionInterface as an ISession. There is another way to do this mentioned in the docs, but it is less explicit.</p><pre>class GatewaySession(SSHSession):</pre><pre>    def channelOpen(self, specificData):<br>        self.session = GatewaySessionInterface(self.avatar)</pre><p>To enable our new GatewaySession class we override our avatar’s channel lookup “session” entry.</p><pre>class GatewayUser(ConchUser):</pre><pre>    def __init__(self, key):<br>        ConchUser.__init__(self)<br>        self.user = key.user<br>        self.project = key.project<br>        self.channelLookup[‘session’] = GatewaySession</pre><h4><strong>Git — Processes, Reference Discovery, Packfile Negotiation</strong></h4><p>To serve up Git we will need to understand its <a href="https://github.com/git/git/blob/master/Documentation/technical/pack-protocol.txt">protocol</a> and transport mechanisms. Git can utilize several transports, but we are only interested in SSH.</p><p>Each time a user fetches or pushes data a command is executed on the server using SSH. The process spawned from the command allows the server and client to communicate.</p><p>All commands are handled by two executables on the server : git-upload-pack and git-receive-pack. Sending data to the server fires up the git-receive-pack executable. Fetching data which includes cloning executes git-upload-pack.</p><p>For example, the command :</p><pre>git clone emil@joltem.com:1</pre><p>Is mapped to this command :</p><pre>ssh emil@joltem.com “git-upload-pack ‘1&#39;”</pre><p>Which establishes an SSH connection and executes the command :</p><pre>git-upload-pack ‘1&#39;</pre><p>Once the line of communication is opened <a href="https://github.com/git/git/blob/master/Documentation/technical/pack-protocol.txt">Git’s protocol</a> proceeds. The protocol uses <a href="https://github.com/git/git/blob/master/Documentation/technical/protocol-common.txt">packet lines</a> ( or pkt-lines ) to communicate :</p><blockquote><em>A pkt-line is a variable length binary string. The first four bytes of the line, the pkt-len, indicates the total length of the line, in hexadecimal. The pkt-len includes the 4 bytes used to contain the length’s hexadecimal representation.</em></blockquote><pre>Examples (as C-style strings):</pre><pre>——<br> pkt-line actual value<br> ————————————————-<br> “0006a\n”       “a\n”<br> “0005a”         “a”<br> “000bfoobar\n”  “foobar\n”<br> “0004&quot;          “”<br>——</pre><p>A 0000 flush packet indicates an end of a group of statements.</p><p>The first order of business is <em>reference discovery </em>:</p><blockquote><em>When the client initially connects the server will immediately respond with a listing of each reference it has (all branches and tags) along with the object name that each reference currently points to.</em></blockquote><p>Along with the first reference in the list the server informs the client of its <a href="https://github.com/git/git/blob/master/Documentation/technical/protocol-capabilities.txt">capabilities</a>.</p><pre>009bb8915a670ec46e39f25ff700eb260ef5e8d045b1 HEAD\x00multi_ack thin-pack side-band side-band-64k ofs-delta shallow no-progress include-tag multi_ack_detailed<br>0040cbb40cbc1f82c5d823484b1ccaf742fe210bcf52 refs/heads/develop<br>003fb8915a670ec46e39f25ff700eb260ef5e8d045b1 refs/heads/master<br>0040964838da3cd6e95f71d6bf6b425431769f76c22e refs/tags/1.3.2^{}<br>003d101c5cb5601d9ac04533bf3db810095d0faf7568 refs/tags/1.3.3<br>003d5da834fffb7e252418b080cca78041517bcd9734 refs/tags/1.3.4<br>0000</pre><p>The next step depends on whether the client is fetching or pushing. If the client is fetching a process called <a href="https://github.com/git/git/blob/master/Documentation/technical/pack-protocol.txt"><em>pack file negotiation</em></a><em> </em>proceeds. During the process the client informs the server what it has and what it wants. The server uses this to compile the necessary objects into the smallest <a href="https://github.com/git/git/blob/master/Documentation/technical/pack-format.txt">pack file</a> possible.</p><p>Since our main goals is to enforce branch level <em>push </em>permissions, let us examine what happens during a push.</p><blockquote><em>Once the client knows what references the server is at, it can send a list of reference update requests. For each reference on the server that it wants to update, it sends a line listing the obj-id currently on the server, the obj-id the client would like to update it to and the name of the reference.</em></blockquote><p>An example, pushing the develop and master branches :</p><pre>00859d4c1ed658ee2617521d846bf601cec06001a2c8 cbb40cbc1f82c5d823484b1ccaf742fe210bcf52 refs/heads/develop\x00report-status side-band-64k<br>00676860ded8258f538407e9eb1d2017ffc7a3015abe b8915a670ec46e39f25ff700eb260ef5e8d045b1 refs/heads/master<br>0000</pre><p>Immediately after this, the client compiles and sends a pack file. The file contains all the objects the server will need to fill the gap between the old and new commit.</p><p>To enforce branch level permissions we decided to create a middleware. Something that sits between the client and server, listens to Git’s transfer protocols, and interrupts when necessary.</p><p>Twisted uses <a href="https://twistedmatrix.com/documents/current/api/twisted.internet.protocol.ProcessProtocol.html">ProcessProtocol</a>s to connect to and receive data from process. Since an SSH session intends to execute something it is represented as a process. An instance of <a href="https://twistedmatrix.com/documents/current/api/twisted.conch.ssh.session.SSHSessionProcessProtocol.html">SSHSessionProcessProtocol</a> is created by SSHSession and passed to our GatewaySessionInterface execCommand method as protocol.</p><pre>def execCommand(self, protocol, command_string):<br>    …</pre><p>The commands the server gets will require execution of git-receive-pack and git-upload-pack in their own separate processes. We extend ProcessProtocols for each of these to mediate the protocol.</p><p>Our GitReceivePackProcessProtocol buffers the client’s input and processes packet lines. If a client attempts to push to a prohibited branch the server ignores their pack file and reports back with an informative error message.</p><p>To demonstrate our ProcessProtocols requires a lot of code and I didn’t want to complicate the article too much. Luckily, we are an open company and our code is publicly visible. You can clone the repository on <a href="http://joltem.com/1/?utm_source=medium&amp;utm_medium=article&amp;utm_content=clone%20the%20repository%20on%20our%20site&amp;utm_campaign=twisted%20git%20server">our site</a> and test the server out.</p><p>If you want to get involved in the development read over <a href="http://joltem.com/help/?utm_source=medium&amp;utm_medium=article&amp;utm_content=get%20involved%20in%20the%20development%20read%20over%20this&amp;utm_campaign=twisted%20git%20server">this</a> and jump right in.</p><h3><strong>Caveat — Terminal Access</strong></h3><p>When a user directly SSHs to our server a terminal appears implemented completely using Twisted. It only handle a few basic commands and I won’t cover it here, but nonetheless some may find it interesting.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/684/1*-HTAHDzBUkhooH459EqwFw.png" /><figcaption>Terminal access to joltem.com</figcaption></figure><p>Joltem didn’t work out, but the code is <a href="https://github.com/emil2k/joltem">open sourced here</a>. Feel free to fork and put it to use.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1dfb89adca1d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/joltem-an-open-incubator/building-a-git-server-1dfb89adca1d">Building a Git Server</a> was originally published in <a href="https://medium.com/joltem-an-open-incubator">Joltem — An Open Incubator</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Fork and Pull Alternative]]></title>
            <link>https://medium.com/@forEmil/fork-and-pull-alternative-c88d1154f1c6?source=rss----fd44dd72da3d---4</link>
            <guid isPermaLink="false">https://medium.com/p/c88d1154f1c6</guid>
            <dc:creator><![CDATA[Emil Davtyan]]></dc:creator>
            <pubDate>Sun, 12 Oct 2014 18:07:00 GMT</pubDate>
            <atom:updated>2016-06-17T18:46:47.877Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wrMv7hCsTB8LS_ZNCdZnsQ.jpeg" /></figure><h4>How to scale and improve collaboration</h4><p>Collaboration depends on a compromise between access and control. As a maintainer gives up access, control is lost. With lost control a project may lose conceptual integrity. Tuning access is the foundation of any collaboration.</p><p>Our goal is to determine a scalable open source access model. It should allow contributors to easily submit contribution, without prior approval. Scale well beyond ten contributors. As contributors come and go, transience should not produce overhead. Most importantly, communication should be fast and simple.</p><h3><strong>Fork &amp; Pull</strong></h3><p>Popularized by GitHub, the most popular access model is the <em>fork and pull. </em>Each contributor not granted read access maintains a copy of the codebase called a “fork”. Work progresses independently on forks. Once completed, a “pull” request is submitted to the maintainers of the codebase to merge in the changes. A technically simple solution that enables mass collaboration. Naturally it has spread quickly despite shortcomings that convolute the collaboration process.</p><h4><strong>Managing forks and remotes</strong></h4><p>The most tangible source of friction is the management of remotes and forks. To a setup a contributor must create a fork, clone it, and then add an<em>upstream </em>remote representing the repository forked. Afterwards they must periodically update their clone and fork with changes from upstream. Each contributor represents a remote that must be added and maintained. Fetching changes fires a separate request for each remote. Trivial for small projects, but it fails to scale as the number of contributors grows.</p><h4><strong>Absence of structure</strong></h4><p>Branches represent threads that follow a progression. On independent forks, branching structure is defined by the owner of the fork. Context is lost without a consistent naming structure. A multitude of forks erodes meaning even from conventional branches such as a <em>master</em> and <em>develop</em>. Context must be gathered either from commits or by waiting for a pull request.</p><h4><strong>Communication via pull requests</strong></h4><p>Communication depends on awareness. Specifically, awareness of the code’s state and direction. When this is represented by a hundreds or even thousands of independent forks it becomes incomprehensible. Sporadic pull requests become the main mode of communication. Combined with a lack of shared branches, communication can become frustrating and slow to a crawl. Code is the preferred communication medium.</p><h3><strong>Branch Allocation</strong></h3><p>Working on <a href="https://github.com/emil2k/joltem">Joltem</a> we needed an access model capable of housing a dynamic workforce open to contributors. To ease and scale collaboration we chose against the fork and pull model, devised our own scheme, and <a href="https://medium.com/joltem-an-open-incubator/building-a-git-server-1dfb89adca1d">build a custom git server</a>.</p><p>Our model depends on branch allocation. Replacing forks with branches, we enable one repository to serve all contributors. Trusted individuals can obtain complete push access. Other contributors can allocate branches through our task management system. Branch allocation does not require prior approval. It allows the contributor to push changes to the branch.</p><h4><strong>One remote</strong></h4><p>The obvious advantage is the single remote. Without setup and maintains of a fork, contributing is simplified. Each contributor no longer represents a separate remote, removing the overhead of maintaing them as contributors come and go. Branch tracking is simplified, making it easier to keep branches up to date. All changes are fetched from a single remote, making it fast and simple.</p><h4><strong>Definitive structure</strong></h4><p>Branching structure is well defined. Solution branches are allocated under the s namespace ( i.e. <em>s/123</em> or<em> s/89</em>). While maintainers of the project decide the rest of the structure. By assigning meaning to branch names they develop and enforce a branching convention throughout the whole project. Convention saves time for everyone involved.</p><h4><strong>Communication via code</strong></h4><p>By unifying the codebase, communication is accelerated. The state and direction of the codebase is a git fetch away. The access model provides shared branches between maintainers and contributors, enabling communication directly through code. Small corrections can be made to guide contributors away from compounding on small mistakes.</p><p>Joltem didn’t work out, but the code is <a href="https://github.com/emil2k/joltem">open sourced here</a>. Feel free to fork and put it to use.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c88d1154f1c6" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Broken Startup Process]]></title>
            <link>https://medium.com/@forEmil/the-broken-startup-process-4c42cf1a9724?source=rss----fd44dd72da3d---4</link>
            <guid isPermaLink="false">https://medium.com/p/4c42cf1a9724</guid>
            <dc:creator><![CDATA[Emil Davtyan]]></dc:creator>
            <pubDate>Tue, 01 Apr 2014 19:15:01 GMT</pubDate>
            <atom:updated>2018-04-15T12:20:26.748Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/960/desat/multiply/yellow/60/overlay/yellow/1*_EUEItaEsVc6_zNLAeI-pg.jpeg" /></figure><h4>What’s wrong and how we plan to fix it</h4><p>Late in 2012, I found a cease and desist in my mailbox.</p><p>Over four years I had developed and ran a couple products around a popular classified site.</p><p>It started in 2008 with an image hosting site that grew quickly and at one point served 2 million unique visitors a month. Then in 2011 an Android app to search and post to the classified site, which has been installed over 200 thousand times.</p><p>The whole time I worked alone. I was the system admin, the database administrator, the PHP developer, the Perl developer, the Android developer, the marketing department, the support department, and now the legal department all in one. I did everything from manually deleting nude photos to setting up Bind servers.</p><p>As I read the cease and desist which referred to a clause in their terms of use that prohibited development of mobile applications, I reminisced over all the work I had done and became infuriated. However as a lone developer, I had little power and my work would eventually be squashed out of existence. I decided for my next venture I would form a company more resilient to such circumstances.</p><p>Building a team was imperative. When working alone you are forced to fill so many holes, that you rarely have the time to do anything properly. In a constant state of compromise which can demotivate and exhaust the most resilient, lone developers are often relegated to chase small ideas with an incredible inefficiency. Overly reliant on other companies, they stand at the bottom of the food chain. In my mind, a serious pursuit would require a team.</p><p>As I set out to build a team, I ran across a much bigger problem.</p><p>I began by scouring my personal network. Having worked alone for so many years and generally being an introvert, my network was small and contained few developers.</p><p>My pool was narrowed to three potential people : a friend who studied computer science, another friend who studied physics, and a friend of a friend who made a website once. We were nearing graduation, so I sat down with my friend from the CS department and pitched to him a partnership. He found the idea compelling but told me he was accepted to a strong master’s program and couldn’t handle the risk. My other friend was in a similar position except with physics. I didn’t bother contacting the third guy.</p><p>Maybe it was my fault the pool was so small. Generally I avoided anyone who would ask me what I did. And except for the occasional drunken night, I rarely professed my love of AWS in a public setting. Networking was repulsive to me, but I had to venture out of my comfort zone.</p><p>First step, was to set up a profile on MeetUp.com. I searched for groups related to web technologies and entrepreneurship. After a few moments of cringing at the photographs of people meeting each other, I booked two events.</p><p>One was an Android group and the other was an HTML5 group. For Android there was about 80 to 100 people and for HTML5 there was about 20 people in the room. In each room there was a couple of intimidating people, a recruiter, and a random group that wondered in for pizza.</p><p>After the talks ended, I walked around the room and jumped into some conversations. It was quickly apparent that most people in the room were either beginners or had never programmed. Except for the organizers, there were very few professional programmers in the room. And the few I found were older men who had long lost their inclination to pursue anything ambitious.</p><p>I was at a major disadvantage, I was in Dallas, Texas. The concentration of technical talent was small, and it could take me months to find and convince just one other person to partner with. For a second I entertained the thought of moving to San Francisco, joining a startup, going to conferences, and building up network. But I quickly realized how absurd the whole process was.</p><p>In an age where people can start revolutions via a tweet, I was going door to door to start a company.</p><p>The web is the best distribution system ever devised. It’s cheap, fast, and allows anyone to participate. Yet the companies building it, are formed out of closed, inefficient networks. Outside the network anyone can participate but major disadvantages arise that make many ventures moot. Even for those inside, pursuits often hinge on the willingness of venture capitalist to absorb immense amounts of risk.</p><p>The problem was real, I faced it head on and began working on a solution. I imagined a place that people could spontaneously come together and prototype an idea, possibly without any venture capital. A place where anyone in their spare time could participate in forming a company. A place where a completely dynamic workforce could reside.</p><p>Over 6 months I worked alone to build an alpha version. At which point I stopped to look for partners again.</p><p>Being new to Python and Django, I was constantly landing on StackOverflow threads. I would bookmark profiles of the people whose answers I found helpful. Looking to leverage the internet, this time, I began contacting them one by one. For those that provided contact information, I sent a general email stating I had an interesting project and if they were interested I could discuss it with them over Skype.</p><p>Out of around a 100 people, 15 responded, and out of those I Skyped with 10. Some got the idea immediately. Others provided an array of questions, just to have they idea comfortably settle in moments later. During the conversations, it was exhilarating to see the facial expression when the problem was fully highlighted and the realization kicked in. With a caution that I might wrong, I offered a solution and an invitation to peck away at the problem.</p><p>Working full time, this took nearly a month and a half. The vast majority did not respond to the initial email. And even though many of the people I Skyped with sounded convinced and mentioned that they wanted to contribute, none actually did. Also making things worse, busy recruiting, I was not coding during the time. It was an incredibly slow and at times demoralizing process. But it hit me, despite the time I had spent only <strong>10</strong> people knew of the idea. A thousand may be necessary just to get one to contribute.</p><p>Also the low response rate could be attributed to two things. First, I had no profile. When you Googled my name, buried under my cousin’s LinkedIn profile there was an empty <a href="http://stackoverflow.com/users/220710/emil-davtyan">StackOverflow profile</a> where I occasionally answered questions and an even more desolate <a href="https://github.com/emil2k">GitHub profile</a>. No one was listening, and rightfully so. Ironically though I would only discuss the idea with people who had profiles and that would Skype with me. Leading to the second factor, I had fallen into a common trap. I was too protective of the idea. There was little of value built, and I was suffocating it.</p><p>Broadcasting the idea was the only way. It required opening up the doors. Revealing the idea and the unfinished code to the world. To seek feedback and contribution publicly.</p><p>What came about was <a href="https://github.com/emil2k/joltem"><em>Joltem.com</em></a>, short for “jolt them”. We call it “an open incubator”. Founded on the idea that at least in the early stages many companies can benefit from being open. It was built to organize and compensate an open and dynamic workforce.</p><p>We chose against the conventional <em>pull &amp; fork</em> model popularized on GitHub to develop a way for all contributors to work off of one repository. Having everyone work off of one repository facilitates and equips groups for much larger scales of collaboration. Running a simple `git fetch` provides you with all the code from all the contributors. There is no need to add a remote for each contributor and at all times there is only one `develop` or `master` branch to focus development.</p><p>To accomplish this we developed a task management model based on tasks and solutions and tied it closely with a custom git server that enforces branch level permissions. Trusted people are able to push to all branches, while all other contributors are only allowed to push to solution branches allocated to them.</p><p>For compensation, we simply tweaked a conventional tool — the <em>stock option pool</em>. In regular companies during each round of financing a certain number of stocks is allocated to be awarded to new hires. Hires are then promised a certain number of shares and placed on a <em>vesting plan</em>, where overtime if they stay employed they receive portions of the promised shares. At Joltem, when a company is founded a portion of the shares is allocated towards contributors. For the Joltem project this is 85% of the shares, and essentially represents the conventional stock option pool. The only thing we modified was the distribution of the pool.</p><p>Through a continuous process each person’s contribution to the project is tracked by a metric we call <em>impact</em>. Each time a person contributes something to the project they submit it along with the amount of impact they deem fair for the work. The other contributors determine whether the work is satisfactory and whether the evaluation is reasonable. When their is a disagreement, a bargaining process follows to determine a fair value. From experience on the Joltem project itself, there is rarely a disagreement. A contributor quickly develops a sense of what each contribution is worth. Then periodically, much like a vesting plan, a portion of earned impact is exchanged for shares in the company that is being built.</p><p>Now, <a href="https://github.com/emil2k/joltem">Joltem</a>, is open to anyone.</p><p>You can post a project. Collaborate privately by inviting others or completely openly. You can even contribute to the <a href="https://github.com/emil2k/joltem">Joltem project</a> itself.</p><p>Joltem didn’t work out, but the code is <a href="https://github.com/emil2k/joltem">open sourced here</a>. Feel free to fork and put it to use.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4c42cf1a9724" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>