<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>joeandrieu.com</title>
	<atom:link href="http://blog.joeandrieu.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.joeandrieu.com</link>
	<description>My personal space</description>
	<lastBuildDate>Wed, 24 Apr 2013 06:52:22 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Destroying contract law: CISPA violates more than privacy</title>
		<link>http://blog.joeandrieu.com/2013/04/19/destroying-contract-law-cispa-violates-more-than-privacy/</link>
		<comments>http://blog.joeandrieu.com/2013/04/19/destroying-contract-law-cispa-violates-more-than-privacy/#comments</comments>
		<pubDate>Fri, 19 Apr 2013 16:42:03 +0000</pubDate>
		<dc:creator>Joe Andrieu</dc:creator>
				<category><![CDATA[Information Sharing]]></category>
		<category><![CDATA[privacy]]></category>
		<category><![CDATA[ProjectVRM]]></category>
		<category><![CDATA[regulatory]]></category>
		<category><![CDATA[Shared Information]]></category>

		<guid isPermaLink="false">http://blog.joeandrieu.com/?p=1137</guid>
		<description><![CDATA[Don&#8217;t let Congress undermine our best free market tool for fixing our relationships with companies. The US House of Representatives just passed a bill (CISPA, aka HR264) that explicitly allows companies to ignore their privacy agreements in the name of cybersecurity. Here&#8217;s the Huffington Post report: http://www.huffingtonpost.com/2013/04/18/cispa-vote-house-approves_n_3109504.html SOPA. The Monsanto Protection Act. CISPA. Regulatory capture of [...]]]></description>
				<content:encoded><![CDATA[<p>Don&#8217;t let Congress undermine our best free market tool for fixing our relationships with companies.</p>
<p>The US House of Representatives just passed a bill (<a href="http://en.wikipedia.org/wiki/Cyber_Intelligence_Sharing_and_Protection_Act" target="_blank">CISPA</a>, aka <a href="http://www.govtrack.us/congress/bills/113/hr624" target="_blank">HR264</a>) that explicitly allows companies to ignore their privacy agreements in the name of cybersecurity.</p>
<p>Here&#8217;s the Huffington Post report:</p>
<p><a href="http://www.huffingtonpost.com/2013/04/18/cispa-vote-house-approves_n_3109504.html" target="_blank">http://www.huffingtonpost.com/2013/04/18/cispa-vote-house-approves_n_3109504.html</a></p>
</p>
<p><a href="http://en.wikipedia.org/wiki/Stop_Online_Piracy_Act" target="_blank">SOPA</a>. The <a href="http://www.snopes.com/politics/business/mpa.asp" target="_blank">Monsanto Protection Act</a>. CISPA.<a href="http://en.wikipedia.org/wiki/Regulatory_capture" target="_blank"> Regulatory capture</a> of the worst kind.</p>
<p>Please get the word out. Fight this thing.</p>
<p>If we can&#8217;t even depend on the blatantly one-sided Terms of Service and Privacy Policies of our service providers, entire fields of solutions evaporate.  Efforts to improve, fix, clarify, negotiate or automate the privacy and service agreements will be essentially worthless if Congress is willing to give corporations a free pass.</p>
<blockquote><p>
&#8220;Notwithstanding any other provision of law, a self-protected entity may, for cybersecurity purposes &#8230; share such cyber threat information with any other entity, including the Federal Government.&#8221;</p></blockquote>
<p>Enshrining corporate protections like this in law isn&#8217;t just a privacy problem. It undermines the very notion of contract as a mechanism for constructing agreements in a free society.</p>
<p>This is unaccepatble.</p>
<p>Fight CISPA. Call your senator. Call the white house. Blog it. Tweet it. Repost this.</p>
<p>Tell everyone.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.joeandrieu.com/2013/04/19/destroying-contract-law-cispa-violates-more-than-privacy/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Google sees the value of Free Customers</title>
		<link>http://blog.joeandrieu.com/2013/03/01/google-sees-the-value-of-free-customers/</link>
		<comments>http://blog.joeandrieu.com/2013/03/01/google-sees-the-value-of-free-customers/#comments</comments>
		<pubDate>Fri, 01 Mar 2013 13:51:29 +0000</pubDate>
		<dc:creator>Joe Andrieu</dc:creator>
				<category><![CDATA[ProjectVRM]]></category>
		<category><![CDATA[User Driven]]></category>
		<category><![CDATA[Vendor Relationship Management]]></category>

		<guid isPermaLink="false">http://blog.joeandrieu.com/?p=1097</guid>
		<description><![CDATA[This is fascinating: http://www.adweek.com/news/technology/google-bringing-trueview-ads-apps-games-147558 Google has an ad program on YouTube that let&#8217;s users skip ads and they are now extending it to other ad formats. Even though it is the same old advertising game&#8211;something that could use some fixing&#8211;what&#8217;s impressive is that with the ad-skipping feature Google saw &#8220;a 40 percent reduction in the number [...]]]></description>
				<content:encoded><![CDATA[<p>This is fascinating:<br />
<a href="http://www.adweek.com/news/technology/google-bringing-trueview-ads-apps-games-147558" target="_blank"> http://www.adweek.com/news/technology/google-bringing-trueview-ads-apps-games-147558</a></p>
<p>Google has an ad program on YouTube that let&#8217;s users skip ads and they are now extending it to other ad formats.</p>
<p>Even though it is the same old advertising game&#8211;something that could use some fixing&#8211;what&#8217;s impressive is that with the ad-skipping feature Google saw &#8220;a 40 percent reduction in the number of people who click away from a video when shown a pre-roll&#8221; ad.</p>
<p>It&#8217;s real-world proof that a free customer is more valuable than a captive one. Give people the freedom to leave and more will stay than if you had forced the issue.</p>
<p>I&#8217;ve done this myself. Initially, I was ready to leave the page because the content didn&#8217;t seem worth the extra delay of the ad. But then I see that if I wait just a few seconds, I can click past it. Not only does the ability to click past keep me from just abandoning the video altogether, but in a few instances the opening bit was funny or intriguing or just interesting enough for me to want to see the rest of the ad.</p>
<p>It&#8217;s a brilliant example of how giving people the freedom to leave can actually keep them around more.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.joeandrieu.com/2013/03/01/google-sees-the-value-of-free-customers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Badges for the Standard Label Kickstarter</title>
		<link>http://blog.joeandrieu.com/2012/05/23/badges-for-the-standard-label-kickstarter/</link>
		<comments>http://blog.joeandrieu.com/2012/05/23/badges-for-the-standard-label-kickstarter/#comments</comments>
		<pubDate>Wed, 23 May 2012 19:31:03 +0000</pubDate>
		<dc:creator>Joe Andrieu</dc:creator>
				<category><![CDATA[Information Sharing]]></category>
		<category><![CDATA[Shared Information]]></category>
		<category><![CDATA[badges]]></category>
		<category><![CDATA[Kantara]]></category>
		<category><![CDATA[kickstarter]]></category>
		<category><![CDATA[standard information sharing label]]></category>
		<category><![CDATA[standard label]]></category>

		<guid isPermaLink="false">http://blog.joeandrieu.com/?p=1098</guid>
		<description><![CDATA[We&#8217;ve been asked if we have any badges to help promote our Kickstarter for the Standard Information Sharing Label. The answer is now yes! If you&#8217;re a backer or just want to help promote the idea, put these babies on your website or blog or Twitter or Facebook and help get out the word! We [...]]]></description>
				<content:encoded><![CDATA[<p>We&#8217;ve been asked if we have any badges to help promote our Kickstarter for the <a href="http://standardlabel.org" target="_blank">Standard Information Sharing Label</a>.</p>
<p>The answer is now yes!</p>
<p>If you&#8217;re a backer or just want to help promote the idea, put these babies on your website or blog or Twitter or Facebook and help get out the word!<br />
<code></code><br />
We have less than two weeks left to rally support for a radical new way for companies to communicate about what they do with the information we share online.</p>
<p>Once we finish the Kickstarter, the link will go directly to our new website and will help promote the use of the Standard Label for websites everywhere.</p>
<p>Feel free to download the image or just use the URLs as SRC tags. We&#8217;ve also provided example HTML that links directly to http://standardlabel.org.</p>
<style type="text/css">
table { border: thick black solid; 
background: transparent;
vertical-align: middle;
width: 80%;
margin-left: 10%;
margin-right: 10%;
}
tr {
background-color: white;
color: none;
border: thin black solid;
}
td {
background-color: white;
vertical-align: middle;
padding: 20px;
border: none;
}
td.myleft {
  padding-right: 10px;
  text-align: center;
}
td.myright {
  padding-left: 10px;
}
code {
   display: block;
   color: black;
   pading: 5px;
}
</style>
<table>
<tr>
<td class="myleft">
<a href="http://standardlabel.org"><img src="http://blog.joeandrieu.com/wp-content/uploads/2012/05/standard-label-badge.1.png" alt="I Support The Standard Label!" title="I Support The Standard Label!"/></a></td>
<td class="myright"><code>&lt;a href="http://standardlabel.org">&lt;img src="http://blog.joeandrieu.com/wp-content/uploads/2012/05/standard-label-badge.1.png" alt="I Support The Standard Label!" title="I Support The Standard Label!"/>&lt;/a></code></td>
</tr>
<tr>
<td class="myleft">
<a href="http://standardlabel.org"><img src="http://blog.joeandrieu.com/wp-content/uploads/2012/05/standard-label-badge.2.png" alt="I Support The Standard Label!" title="I Support The Standard Label!"/></a></td>
<td class="myright"><code>&lt;a href="http://standardlabel.org">&lt;img src="http://blog.joeandrieu.com/wp-content/uploads/2012/05/standard-label-badge.2.png" alt="I Support The Standard Label!" title="I Support The Standard Label!"/>&lt;/a></code></td>
</tr>
<tr>
<td class="myleft">
<a href="http://standardlabel.org"><img src="http://blog.joeandrieu.com/wp-content/uploads/2012/05/standard-label-badge.3.png" alt="I Support The Standard Label!" title="I Support The Standard Label!"/></a></td>
<td class="myright"><code>&lt;a href="http://standardlabel.org">&lt;img src="http://blog.joeandrieu.com/wp-content/uploads/2012/05/standard-label-badge.3.png" alt="I Support The Standard Label!" title="I Support The Standard Label!"/>&lt;/a></code></td>
</tr>
<tr>
<td class="myleft">
<a href="http://standardlabel.org"><img src="http://blog.joeandrieu.com/wp-content/uploads/2012/05/standard-label-badge.4.png" alt="I Support The Standard Label!" title="I Support The Standard Label!"/></a></td>
<td class="myright"><code>&lt;a href="http://standardlabel.org">&lt;img src="http://blog.joeandrieu.com/wp-content/uploads/2012/05/standard-label-badge.4.png" alt="I Support The Standard Label!" title="I Support The Standard Label!"/>&lt;/a></code></td>
</tr>
</table>
]]></content:encoded>
			<wfw:commentRss>http://blog.joeandrieu.com/2012/05/23/badges-for-the-standard-label-kickstarter/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Rethinking Context</title>
		<link>http://blog.joeandrieu.com/2012/05/15/rethinking-context/</link>
		<comments>http://blog.joeandrieu.com/2012/05/15/rethinking-context/#comments</comments>
		<pubDate>Tue, 15 May 2012 18:02:01 +0000</pubDate>
		<dc:creator>Joe Andrieu</dc:creator>
				<category><![CDATA[Information Sharing]]></category>
		<category><![CDATA[Shared Information]]></category>
		<category><![CDATA[context]]></category>
		<category><![CDATA[FTC privacy report]]></category>
		<category><![CDATA[personal levels of assurance]]></category>
		<category><![CDATA[privacy]]></category>
		<category><![CDATA[smart disclosure]]></category>
		<category><![CDATA[standard label]]></category>

		<guid isPermaLink="false">http://blog.joeandrieu.com/?p=1087</guid>
		<description><![CDATA[Insights from PII2012 The FTC Privacy Report makes it clear that context is the key to privacy. For example, notice and consent need not be presented and secured if the use is obvious from context: If you buy a book from Amazon, it&#8217;s clear they need an address to ship you the book. But sometimes [...]]]></description>
				<content:encoded><![CDATA[<p><em>Insights from <a href="http://privacyidentityinnovation.com">PII2012</a></em></p>
<p>The <a href="http://www.ftc.gov/os/2012/03/120326privacyreport.pdf">FTC Privacy Report</a> makes it clear that context is the key to privacy. For example, notice and consent need not be presented and secured if the use is obvious from context: If you buy a book from Amazon, it&#8217;s clear they need an address to ship you the book.</p>
<p>But sometimes the context isn&#8217;t clear to the average user, even when it is obvious to developers. My Mom believes she doesn&#8217;t share anything on Facebook because she mostly just comments on other people&#8217;s posts. <a href="http://www.linkedin.com/in/ilanawesterman">Ilana Westerman&#8217;s</a> work shows the same disconnect: many people just don&#8217;t see their privacy exposure because they have simplified models of their actions. They think what they are doing isn&#8217;t the risky stuff, but they rarely have the awareness of what they are really doing.</p>
<p>Making that harder are monolithic Terms of Service and Privacy Policies that bury the details arbitrarily far away from the point of exposure, and in confusing legalese. </p>
<p>The answer is some form of bite-size context management. For example, Smart Disclosure, which is the US administration&#8217;s <a href="http://radar.oreilly.com/2012/04/what-is-smart-disclosure.html">language</a> for greater clarity about risks of information sharing: </p>
<blockquote><p>One of the most powerful versions of smart disclosure is when data on products or services (including pricing algorithms, quality, and features) is combined with personal data (like customer usage history, credit score, health, energy and education data) into &#8220;choice engines&#8221; (like search engines, interactive maps or mobile applications) that enable consumers to make better decisions in context, at the point of a buying or contractual decision</p></blockquote>
<p>Or perhaps something along the lines of <a href="http://www.att.com/gen/press-room?pid=22677">Personal Levels of Assurance</a>, a term from AT&#038;T describing piece-wise on-demand disclosure and consent.</p>
<p>This is also the approach behind the <a href="http://standardlabel.org">Standard Information Sharing Label</a>, which let&#8217;s you see in simple, consistent terms, exactly what happens with the data you are about to share, before you share it. That instance of sharing defines the context for which the information may be used, and the label makes it easy for individuals to understand that context.</p>
<p>We aren&#8217;t compressing the entire Terms of Service and Privacy Policy for a given site, we&#8217;re presenting just the essential details about a particular instance of information sharing. Bite-size disclosure, right at the point of sharing, because nobody wants to read 47 pages of legalese.</p>
<p>We think that&#8217;s the right model for untangling the world wide web.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.joeandrieu.com/2012/05/15/rethinking-context/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>It all starts with sharing&#8230;</title>
		<link>http://blog.joeandrieu.com/2012/05/02/it-all-starts-with-sharing/</link>
		<comments>http://blog.joeandrieu.com/2012/05/02/it-all-starts-with-sharing/#comments</comments>
		<pubDate>Wed, 02 May 2012 15:37:26 +0000</pubDate>
		<dc:creator>Joe Andrieu</dc:creator>
				<category><![CDATA[Information Sharing]]></category>
		<category><![CDATA[ProjectVRM]]></category>
		<category><![CDATA[Shared Information]]></category>
		<category><![CDATA[User Driven]]></category>
		<category><![CDATA[Vendor Relationship Management]]></category>
		<category><![CDATA[IIW]]></category>
		<category><![CDATA[iiw14]]></category>
		<category><![CDATA[information sharing work group]]></category>
		<category><![CDATA[ISWG]]></category>
		<category><![CDATA[Kantara]]></category>
		<category><![CDATA[Kantara Initiative]]></category>
		<category><![CDATA[label]]></category>
		<category><![CDATA[legal]]></category>
		<category><![CDATA[notice]]></category>
		<category><![CDATA[open standard]]></category>
		<category><![CDATA[open standards]]></category>
		<category><![CDATA[privacy]]></category>
		<category><![CDATA[privacy policy]]></category>
		<category><![CDATA[standard information sharing label]]></category>
		<category><![CDATA[standard label]]></category>
		<category><![CDATA[terms of service]]></category>
		<category><![CDATA[terms of use]]></category>
		<category><![CDATA[TOS]]></category>
		<category><![CDATA[TOU]]></category>
		<category><![CDATA[VRM]]></category>

		<guid isPermaLink="false">http://blog.joeandrieu.com/?p=1074</guid>
		<description><![CDATA[From kindergarten through our professional life, sharing binds us together as friends, colleagues, and collaborators, so perhaps it should be no surprise that online sharing through services like Facebook, Twitter, and email shapes our online social life. Yet sharing online is anything but simple. The details of what happens with the information we share is [...]]]></description>
				<content:encoded><![CDATA[<p>From kindergarten through our professional life, sharing binds us together as friends, colleagues, and collaborators, so perhaps it should be no surprise that online sharing through services like Facebook, Twitter, and email shapes our online social life. Yet sharing online is anything but simple.</p>
<p>The details of what happens with the information we share is often hidden behind long, complicated legal agreements that almost no one reads. If we&#8217;re lucky, they are explained in Terms of Service and Privacy Policy documents, sometimes buried out of view, other times forced on us like ransom notes forcing us to state our compliance or leave the site.</p>
<p>It doesn&#8217;t have to be that way.</p>
<p>Today, at the <a href="http://www.internetidentityworkshop.com/" target="_blank">Internet Identity Workshop</a>, we officially launch the <a href="http://standardlabel.org" target="_blank">Standard Information Sharing Label</a>, which makes it easy for websites to say in simple, consistent language what they do with our information, making it easier for individuals to make better decisions about the information we share online.</p>
<p>The <a href="http://informationsharingworkgroup.org" target="_blank">Information Sharing Work Group</a> has published a <a href="http://kantarainitiative.org/confluence/display/infosharing/Standard+Information+Sharing+Label" target="_blank">draft specification</a> defining the Standard Label as well as a <a href="http://www.kickstarter.com/projects/joeandrieu/a-standard-information-sharing-label" target="_blank">Kickstarter project</a> to finance its graphic design.</p>
<p>The <a href="http://www.kickstarter.com/projects/joeandrieu/a-standard-information-sharing-label" target="_blank">Kickstarter</a> has a brief video explaining the effort. The official press release is <a href="http://kantarainitiative.org/wordpress/2012/05/reinventing-the-web-one-site-at-a-time-new-label-helps-people-make-smarter-decisions-about-information-we-share-online/" target="_blank">here</a>.</p>
<p>The work is free to use and open to collaborators.</p>
<p>In all my years contributing to the VRM conversation, few projects have made me as proud as I am of the work behind the <a href="http://standardlabel.org" target="_blank">Standard Label</a>.</p>
<p>Check it out. If you like it, please spread the word and consider chipping into help take this work to the next level.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.joeandrieu.com/2012/05/02/it-all-starts-with-sharing/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>The World&#8217;s Simplest AutoTweeter (in node.js)</title>
		<link>http://blog.joeandrieu.com/2012/01/30/the-worlds-simplest-autotweeter-in-node-js/</link>
		<comments>http://blog.joeandrieu.com/2012/01/30/the-worlds-simplest-autotweeter-in-node-js/#comments</comments>
		<pubDate>Mon, 30 Jan 2012 21:04:01 +0000</pubDate>
		<dc:creator>Joe Andrieu</dc:creator>
				<category><![CDATA[AutoTweeter]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[hacking]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[node-OAuth]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[OAuth]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[repeal day]]></category>
		<category><![CDATA[repeal day santa barbara]]></category>
		<category><![CDATA[sbhackerspace]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://blog.joeandrieu.com/?p=1037</guid>
		<description><![CDATA[Last month, I set up a quick little autotweeter using Node.js to help me with Repeal Day Santa Barbara. I wrote a short blurb about it before hand, here&#8217;s what actually shipped. (Many thanks to the guys at the Santa Barbara Hacker Space for inspiring and contributing to this project.) The plan was simple. Set [...]]]></description>
				<content:encoded><![CDATA[<p>Last month, I set up a quick little autotweeter using <a href="http://nodejs.org/" target="_blank">Node.js</a> to help me with <a href="http://repealdaysb.com" target="_blank">Repeal Day Santa Barbara</a>. I wrote a short <a href="http://blog.joeandrieu.com/2011/11/09/towards-a-node-js-auto-tweeter/" target="_blank">blurb</a> about it before hand, here&#8217;s what actually shipped.</p>
<p>(Many thanks to the guys at the <a href="http://sbhackerspace.posterous.com/" target="_blank">Santa Barbara Hacker Space</a> for inspiring and contributing to this project.)</p>
<p>The plan was simple.</p>
<ol>
<li>Set up a free server at <a href="http://aws.amazon.com" target="_blank">Amazon Web Services</a>.</li>
<li>Write a simple daemon that processes a queue of tweets, sending them to the <a href="http://twitter.com/#!/RepealDaySB" target="_blank">RepealDaySB twitter account</a> at just the right time.</li>
<li>Write a bunch of tweets and schedule them.</li>
<li>Run that daemon on the evening in question (December 5)</li>
</ol>
<h3>AWS</h3>
<p>Setting up with Amazon was pretty easy. I created an instance at the &#8220;free tier&#8221; level with port 22 as the only inbound port, using an ubuntu AMI (ami-6006f309). Installing node.js and <a href="http://www.gnu.org/software/emacs/" target="_blank">emacs</a> was pretty easy, once I connected using <a href="http://www.vandyke.com/products/securecrt/" target="_blank">Van Dyke&#8217;s SecureCRT</a>, which handled the public key authentication like a charm. With that setup, it was pretty straightforward to start coding.  (I did need some other ports to explore some of the examples that turned out to be dead ends, but for the live service, all I needed was SSH access on port 22.)</p>
<h3>The First Tweet</h3>
<p>The next step was to work through the details to get node.js to send just one tweet to <a href="http://twitter.com" target="_blank">Twitter</a>. A lot of the <a href="https://gist.github.com/555607" target="_blank">examples</a> out there <a href="http://moonlitscript.com/post.cfm/how-to-use-oauth-and-twitter-in-your-node-js-expressjs-app/" target="_blank">offer more functionality</a> than I needed, using frameworks like <a href="http://expressjs.com/" target="_blank">ExpressJS</a> to support authenticating into Twitter as any user.  But I didn&#8217;t need that. In fact, I didn&#8217;t want an interactive service. I didn&#8217;t really need a database and I didn&#8217;t need a real-time interface. I just wanted to tweet as me (well, as my RepealDaySB persona).</p>
<p>Twitter has pretty good support for this single-user use case:  <a href="https://dev.twitter.com/docs/auth/oauth/single-user-with-examples">https://dev.twitter.com/docs/auth/oauth/single-user-with-examples</a>  If only they&#8217;d had example code for node.js&#8230;</p>
<p>The good news is that <a href="https://github.com/ciaranj/node-oauth" target="_blank">node-OAuth</a> is the go-to library for OAuth on node.js and after a bit of wrangling it did the trick:</p>
<p>So, the first thing I did was put my secret keys into twitterkeys.js</p>
<blockquote>
<pre>exports.token = '3XXXXXXXXX89-3CbAPSxXXXXXXXXXXy42A9ddvQkFs96XXXXXXX';
exports.secret = 'HHXXXXXesTKZ4bLllXXXXXXXXXX8zAaU';
exports.consumerKey = "XXXXXXXbgfJRXXXXXXXX";
exports.consumerSecret = "9XXXXXXXXXQJ9U8VuoNMXXXXXXXXX";</pre>
</blockquote>
<p>Then, I could import that file like this:</p>
<blockquote>
<pre>var keys = require('./twitterkeys');</pre>
</blockquote>
<p>And access it like this:</p>
<blockquote>
<pre>var tweeter = new OAuth(
  "https://api.twitter.com/oauth/request_token",
  "https://api.twitter.com/oauth/access_token",
  keys.consumerKey,
  keys.consumerSecret,
  "1.0",
  null,
  "HMAC-SHA1”
);</pre>
</blockquote>
<p>I did the same thing with my tweets in tweets.js, since I thought that might be useful:</p>
<blockquote>
<pre>module.exports =
[ {
  status:"test1",
  timestamp: "2011-11-5"
},{
  status:"test2",
  timestamp: "2011-11-7"
}];</pre>
</blockquote>
<p>And to access that,</p>
<blockquote>
<pre>var tweets = require('./tweets.js');</pre>
</blockquote>
<p>The astute observer will note my brilliant plan to use a timestamp for scheduling. We&#8217;ll return to that later.</p>
<p>To figure out what to do with my shiny new OAuth object I looked up <a href="https://dev.twitter.com/docs/api" target="_blank">Twitter&#8217;s API</a>:</p>
<blockquote><p>POST statuses/update  Updates the authenticating user&#8217;s status, also known as tweeting. To upload an image to accompany the tweet, use POST statuses/update_with_media. For each update attempt, the update text is compared with the authenticating user&#8217;s recent tweets.Any attempt that would result in duplication will be&#8230;</p></blockquote>
<p>Easy. So the URL to use with OAuth is</p>
<blockquote>
<pre>https://dev.twitter.com/docs/api/1/post/statuses/update</pre>
</blockquote>
<p>And here&#8217;s the code that actually combines all that into my very first tweet from node.js.</p>
<blockquote>
<pre>var https = require('https');

var OAuth= require('oauth').OAuth;
var keys = require('./twitterkeys');
var twitterer = new OAuth(
		   "https://api.twitter.com/oauth/request_token",
		   "https://api.twitter.com/oauth/access_token",
		   keys.consumerKey,
		   keys.ConsumerSecret,
		   "1.0",
		   null,
		   "HMAC-SHA1"
		  );

var tweets = require('./tweets.js');

var status = tweets[0].status;

var body = ({'status': status});

  // url, oauth_token, oauth_token_secret, post_body, post_content_type, callback

twitterer.post("http://api.twitter.com/1/statuses/update.json",
	       keys.token, keys.secret, body, "application/json",
	       function (error, data, response2) {
		   if(error){
		       console.log('Error: Something is wrong.\n'+JSON.stringify(error)+'\n');
		       for (i in response2) {
			       out = i + ' : ';
			       try {
				   out+=response2[i];
			       } catch(err) {}
			       out += '/n';
			       console.log(out);
			   }
		   }else{
		       console.log('Twitter status updated.\n');
		       console.log(response2+'\n');
		   }
	       });</pre>
</blockquote>
<h3>Data Store</h3>
<p>At first I thought I&#8217;d use a database. There are plenty that are easily accessible from node.js and I even signed up for a free service that hosted <a href="http://couchdb.apache.org/" target="_blank">CouchDB</a>. CouchDB is attractive for node.js work because you can basically store JSON objects directly in the database. But that also got me thinking&#8230;</p>
<p>Maybe a database is overkill: too much capability for what I really needed. I don&#8217;t need to update the tweets during the evening. I don&#8217;t need to support simultaneous access. I don&#8217;t need speed or scalability. That&#8217;s when I realized I was thinking like a client-side developer&#8211;the world I do most of my javascript coding in.  With node.js on the server, I could just read and write to a local file!  Turns out it&#8217;s easy.  I should have thought about that earlier, given that I already had been reading my tweets with the @require command, but I hadn&#8217;t thought about being able to WRITE to the file to keep track of what had been tweeted.</p>
<p>Here&#8217;s how you do it. First, set up the path, using the __dirname variable to access the local directory:</p>
<blockquote>
<pre>var path = __dirname+"/tweets.js";</pre>
</blockquote>
<p>Then, to read the file:</p>
<blockquote>
<pre>var fs = require('fs');</pre>
<pre>fs.readFile(path,"utf8", function(err,data) {</pre>
<pre>  if (err) throw err;</pre>
<pre>    tweets = JSON.parse(data);</pre>
<pre>});</pre>
</blockquote>
<p>And to write the file:</p>
<blockquote>
<pre>fs.writeFile(path,JSON.stringify(tweets,null,4),function(err) {</pre>
<pre>  if(err) throw err;</pre>
<pre>    console.log("It's saved");</pre>
<pre>});</pre>
</blockquote>
<h3>Date &amp; Time</h3>
<p>Now, about that timestamp.  I had to represent <em><strong>when</strong></em> I wanted to tweet and having been here before, I knew it could be tricky to make sure the server agrees on the timezone. Javascript has a great Date() object which can parse ISO-8601 formatted dates (e.g., 2011-12-05T10:00-08:00) , so I tried using that. Since the timezone is explicit in ISO-8601, it doesn&#8217;t matter what timezone the server is in, as long as the comparison uses a fully qualified timestamp. It took a bit of trial and error because the parser is pretty strict, but eventually, I got it.  However, that raw timestamp isn&#8217;t that easy to work with, so I used an old trick that I ported from Excel into Google Docs. Put the data in a spreadsheet for editing, and use columns to format it into the right JSON. Then you can cut &amp; paste the rows into a text editor, delete all the tabs, and get the format you need. Here&#8217;s <a href="https://docs.google.com/spreadsheet/ccc?key=0AtuIwzf1Z1eWdHhtVmNXbVhUUzVYY1ZzNTRrUFFfRGc " target="_blank">the doc</a> I actually used.</p>
<p>It worked like magic. I got to use spreadsheet math to track the number of characters remaining in the tweet plus to schedule the dates. Things like</p>
<blockquote>
<pre>=B9+25/24/60</pre>
</blockquote>
<p>set a time that&#8217;s 25 minutes after cell B9, which made scheduling our tweets a breeze. With a bit of wrangling, I was able to get the easy-to-edit date and tweet on the left translated into the proper JSON &amp; ISO-8601 format on the right.</p>
<p>After deleting the tabs, here&#8217;s what a resulting line looks like:</p>
<blockquote>
<pre>{"status":"Good Morning, Santa Barbara!  Happy Repeal Day, everybody! 78 Years ago, we lifted the chains of Prohibition, ratifying the 21st Amendment!","timestamp":"2011-12-05 T 10:00 -08:00"},</pre>
</blockquote>
<p>Add a bracket or two and clip the extra comma, and you&#8217;ve got a nice JSON array suitable for our javascript code.</p>
<p>Google Docs was especially nice because it made collaborating on the tweets super easy. My business partner and I had a great way to review and revise the set of tweets as we got ready for the main event.</p>
<h3>Timing</h3>
<p>The next trick was figuring out how to run the code so that it hummed politely along and sent the tweets when necessary. Since this was the only important process on my machine, I could&#8217;ve ran a never-ending loop constantly checking the time, but that seemed inelegant, and after all, the point was to learn how to use node.js properly. What I wanted was to start the daemon and forget about it, and let it sleep &amp; wake up just when it needs to send a tweet.</p>
<p>So, every once in a while, the daemon wakes up, builds a list of tweets that need to be tweeted (because the current time is after their timestamp), tweets them, and marks them as tweeted. Also, we keep track of the earliest timestamp in the rest of the tweets, so we can sleep the right amount of time.</p>
<p>Here&#8217;s how:</p>
<blockquote>
<pre>var now = new Date();
var next_time;
var tweet_now = new Array();
for(t in tweets) {
   if(tweets[t].tweeted)
     continue;
   time = new Date(tweets[t].timestamp);
   if(time &lt; now ) {
     tweet_now.push(tweets[t].status);
     tweets[t].tweeted = true;
   } else if (!next_time || // either this is the first pass
       time &lt; next_time) { // or this is a sooner timestamp than recorded
     next_time = time;
     console.log("setting next time = "+next_time);
}</pre>
</blockquote>
<p>And then, just a bit of house keeping. We tweet, save to file, and reset the timer.  The nice thing about saving to file is that in case we have to kill the daemon, when we loading the file at the start, we&#8217;ll know which tweets are already sent.</p>
<blockquote>
<pre>if(tweet_now.length) {
   tweet(tweet_now);
}</pre>
<pre>save_tweets();</pre>
<pre>if(next_time) {
  delay = next_time.getTime()-now.getTime();
  setTimeout(run_tweets,delay);
   console.log("Delay: "+delay);
} else {
   console.log("Done.");
}</pre>
</blockquote>
<p>And that&#8217;s pretty much it.  It&#8217;s quick and dirty, so I just dump the errors to console, which is great for debugging, but it may not be the best strategy. More on that later.</p>
<p>Here&#8217;s the complete file that we actually used the night of December 5, Repeal Day.</p>
<blockquote>
<pre>var fs = require('fs');
var OAuth= require('oauth').OAuth;
var keys = require('./twitterkeys');
var path = __dirname+"/tweets.js";
var tweets;
var auto_tweet = function() {
  console.log("auto_tweet");
  fs.readFile(path,"utf8", function(err,data) {
    if (err) throw err;
    tweets = JSON.parse(data);
    // tweets are only loaded once. If you change the file, restart
         run_tweets();
  });
};
var run_tweets = function() {
  console.log("run_tweets");
  //find all the tweets that happen before "now"
  // saving the soonest timestamp that is before "now"
  //mark them as "tweeted"
  //tweet them
  //save to file
  //reschedule
  var now = new Date();
  var next_time;
  // console.log("first next_time = " + next_time.toUTCString());
  var tweet_now = new Array();
  for(t in tweets) {
    if(tweets[t].tweeted)
      continue;
    time = new Date(tweets[t].timestamp);
    if(time &lt; now ) {
      tweet_now.push(tweets[t].status);
      tweets[t].tweeted = true;
    } else if (!next_time || // either this is the first pass
      time &lt; next_time) { // or this is a sooner timestamp than recorded
      next_time = time;
      console.log("setting next time = "+next_time);
    }
  }
  if(tweet_now.length) {
    tweet(tweet_now);
  }
  save_tweets();
  if(next_time) {
    delay = next_time.getTime()-now.getTime();
    setTimeout(run_tweets,delay);
    console.log("Delay: "+delay);
  } else {
    console.log("Done.");
  }
};
var save_tweets = function() {
  fs.writeFile(path,JSON.stringify(tweets,null,4),function(err) {
    if(err) throw err;
    console.log("It's saved");
  });
};
var tweet = function(tweets) {
   var tweeter = new OAuth(
    "https://api.twitter.com/oauth/request_token",
    "https://api.twitter.com/oauth/access_token",
    keys.consumerKey,
    keys.consumerSecret,
    "1.0",
    null,
    "HMAC-SHA1"
  );
  var body;
  for(t in tweets) {
    console.log("tweeting : "+tweets[t]);
    body = ({'status': tweets[t]});
    tweeter.post("http://api.twitter.com/1/statuses/update.json",
      keys.token, keys.secret, body, "application/json",
      function (error, data, response2) {
        if(error){
          console.log('Error: Something is wrong.\n'+JSON.stringify(error)+'\n');
        } else {
          console.log('Twitter status updated.\n');
        }
      });
    }
  }
// Now start it up
auto_tweet();</pre>
</blockquote>
<h3> Success</h3>
<p>It worked, mostly. And it shipped on time. That was awesome. I made it as simple as possible. If I could have, I would&#8217;ve made it simpler. But that isn&#8217;t to say there weren&#8217;t problems.</p>
<h3>Challenges</h3>
<p>1. Too many libraries, too much functionality.</p>
<p>It took a long time to wade through the blog posts and tutorials on how to use node.js, OAuth, and Twitter. It&#8217;s great that there are so many approaches, many well documented. But I didn&#8217;t need all that. Short, and simple.  Maybe you&#8217;re looking for that too. If so, I hope it was easy to find this post.</p>
<p>2. Operations support</p>
<p>As I was out on the Repeal Day pub crawl, all I had was my Android phone to keep on top of things. Surprisingly, I was able to get an SSH client working, even using the public key authentication.  Unfortunately, the text was TINY.  And I couldn&#8217;t type the &#8220;|&#8221; character, making it impossible to use some of my favorite commands.  Apparently, that&#8217;s a well-known problem with my particular phone.  Also, the batteries got sucked dry REAL fast.  I had to resort to keeping the phone off most of the time. Even then, it died well before the tweets ran their course.</p>
<p>3. Twitter won&#8217;t send your own tweets to your phone</p>
<p>This was particularly annoying. Since my app was sending my tweets, but Twitter wouldn&#8217;t echo them to my phone, I had to keep checking, either manually or by asking my partner if the tweet went out.</p>
<h3>Unresolved Issues</h3>
<p>1. Process management was non-existent</p>
<p>So, not having dealt with server processes for a few years, I hadn&#8217;t fully thought through the fact that closing the session would kill my daemon. Next time I&#8217;ll try I&#8217;ll try using <a href="http://blog.nodejitsu.com/keep-a-nodejs-server-up-with-forever" target="_blank">Forever</a>.</p>
<p>2. Server may have been unstable</p>
<p>In hindsight, I think the server crashed on me and I have no idea why. I should&#8217;ve piped the error codes into a log file, which, presumably could be done with a proper process handling approach.  Killing and rerunning it restored the server, but there was something fishy going on that I never got to the bottom of.</p>
<p>3. Wacky characters didn&#8217;t paste well from Docs to JSON</p>
<p>Undoubtedly this was a UNICODE encoding issue, and it showed up in words that had tildes or accents. Which were quite a few given the exotic ingredients in some of the cocktails for Repeal Day. The best way around this would be to find a way to read from Google Docs directly. The second would be perhaps to build some sort of interface instead of using Google Docs. Alternatively, I could debug the copy &amp; paste process and see if I could isolate where the problem happened. Maybe it was in my SSH terminal, pasting into emacs, which might suggest that copy &amp; pasting into a real editor locally and sending the file to the server might avoid the problem.</p>
<h3> And Done</h3>
<p>That&#8217;s it.  Perhaps it was a bit of overkill. There are plenty of free auto-tweeting services out there. But in addition to my doubts about how well they might work, I also thought it was a small enough use case to use to learn node.js. In that, it was a huge success.</p>
<p>Let me know if this was useful for you. I&#8217;d love to hear from fellow coders if this helped you along in any way.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.joeandrieu.com/2012/01/30/the-worlds-simplest-autotweeter-in-node-js/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Kindle files to my iPad (Gutenberg eBooks)</title>
		<link>http://blog.joeandrieu.com/2012/01/15/kindle-files-to-my-ipad-gutenberg-ebooks/</link>
		<comments>http://blog.joeandrieu.com/2012/01/15/kindle-files-to-my-ipad-gutenberg-ebooks/#comments</comments>
		<pubDate>Sun, 15 Jan 2012 22:19:02 +0000</pubDate>
		<dc:creator>Joe Andrieu</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[ebook]]></category>
		<category><![CDATA[gutenberg]]></category>
		<category><![CDATA[ipad]]></category>
		<category><![CDATA[kindle]]></category>
		<category><![CDATA[mobi]]></category>

		<guid isPermaLink="false">http://blog.joeandrieu.com/?p=1033</guid>
		<description><![CDATA[How do you get a book at Project Gutenberg into your iPad Kindle app? It&#8217;s easy. Go to Gutenberg on your iPad and download the &#8220;Kindle&#8221; .mobi file.  It&#8217;ll automatically open in the Kindle app. Yay. Don&#8217;t worry about instructions for how to get a .mobi file to your iPad Kindle.  It&#8217;s a bit of [...]]]></description>
				<content:encoded><![CDATA[<p>How do you get a book at <a href="http://www.gutenberg.org/wiki/Main_Page" target="_blank">Project Gutenberg</a> into your iPad Kindle app?</p>
<p>It&#8217;s easy.</p>
<p>Go to Gutenberg on your iPad and download the &#8220;Kindle&#8221; .mobi file.  It&#8217;ll automatically open in the Kindle app. Yay.</p>
<p>Don&#8217;t worry about instructions for how to get a .mobi file to your iPad Kindle.  It&#8217;s a bit of a chore. But as long as you have a URL for the .mobi file, just use the Safari browser to download it directly.  One you open it, it will be in your Kindle bookshelf until you delete it.</p>
<p>Works like a charm.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.joeandrieu.com/2012/01/15/kindle-files-to-my-ipad-gutenberg-ebooks/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Playing in the Treehouse</title>
		<link>http://blog.joeandrieu.com/2011/11/10/playing-in-the-treehouse/</link>
		<comments>http://blog.joeandrieu.com/2011/11/10/playing-in-the-treehouse/#comments</comments>
		<pubDate>Thu, 10 Nov 2011 22:35:45 +0000</pubDate>
		<dc:creator>Joe Andrieu</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[education]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[treehouse]]></category>

		<guid isPermaLink="false">http://blog.joeandrieu.com/?p=1022</guid>
		<description><![CDATA[For the last few months, I’ve been helping a friend find a good way to learn HTML. She’s an experienced professional designer… in fact her website designs were winning awards as far back as 1994. But she finally realized that because she never learned the brick and mortar work underlying the web, she was hampered [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://teamtreehouse.com/"><img class="alignright size-full wp-image-1023" style="border-style: initial; border-color: initial;" title="treehouse logo" src="http://blog.joeandrieu.com/wp-content/uploads/2011/11/treehouse-logo.png" alt="treehouse" width="284" height="287" /></a></p>
<p>For the last few months, I’ve been helping a friend find a good way to learn HTML. She’s an experienced professional designer… in fact her website designs were winning awards as far back as 1994. But she finally realized that because she never learned the brick and mortar work underlying the web, she was hampered in building breakthrough designs.  As the web moves more and more to interactive, real-time mash ups that is becoming even more true.</p>
<p>Unfortunately, the vast majority of options we considered were either way too expensive (like returning to Art Center to take a traditional college-level course), too focused on tools (learning yet another WYSIWYG editor is not what she’s looking for), or too scattershot (covering everything in so much detail it’s not clear where to start).</p>
<p>Enter <a href="http://teamtreehouse.com/" target="_blank">Treehouse</a>.  They just got a bunch of <a href="http://techcrunch.com/2011/10/17/web-design-community-treehouse-raises-600k-from-reid-hoffman-kevin-rose-and-others/" target="_blank">funding</a>, which is why they crossed my <a href="http://www.bothsidesofthetable.com/2011/10/19/investing-in-treehouse/" target="_blank">RSS stream</a>, and I immediately liked the idea: a flat, monthly fee for unlimited access to very focused, very straightforward set of online classes about web design and development. You start with the basics and work your way up to web guru. Plus, they have an iOS track that might be interesting later. If they were to add Android, that’d be cool and can we imagine a future of server-side code like Perl and PHP or perhaps apps like <a href="http://wordpress.org" target="_blank">WordPress</a> or <a href="http://nodejs.org" target="_blank">Node.js</a>? I sure can.</p>
<p>To brush up on my fundamentals, I decided to try it out before recommending it to my friend…</p>
<p>It definitely lives up to the hype.</p>
<p>It is simple and straightforward, with just the right amount of quizzes and coding challenges. There are badges to earn and a registry for folks looking to hire students of the class. The incentives and engagement are nicely packaged in a smooth, easy framework. I’m an old hand at most of this stuff—I have already sent in a few bits of feedback correcting a few technical errors on the quizzes—but I am going to work through the series just to reconnect to the fundamentals.  I expect it to be fast, easy, and nicely relevant to some of my current projects.</p>
<p>So, if you’re completely new to HTML or want a nice foundation layer for your professional work, I couldn’t recommend Treehouse more.  I don’t often give such sterling endorsements, but I like what they’ve done.</p>
<p>Kudos to <a href="http://teamtreehouse.com/about" target="_blank">Ryan Carson and Team</a>. Well done.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.joeandrieu.com/2011/11/10/playing-in-the-treehouse/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Towards a node.js Auto-Tweeter</title>
		<link>http://blog.joeandrieu.com/2011/11/09/towards-a-node-js-auto-tweeter/</link>
		<comments>http://blog.joeandrieu.com/2011/11/09/towards-a-node-js-auto-tweeter/#comments</comments>
		<pubDate>Wed, 09 Nov 2011 20:18:50 +0000</pubDate>
		<dc:creator>Joe Andrieu</dc:creator>
				<category><![CDATA[AutoTweeter]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[repeal day]]></category>
		<category><![CDATA[sbhackerspace]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://blog.joeandrieu.com/?p=1010</guid>
		<description><![CDATA[I’ve been intrigued by node.js as a platform for highly-scalable server applications written in javascript and finally found a super simple application I wanted to try with it: an auto-tweeter that would let me schedule future tweets to my own account.  I’m organizing a pub crawl for Repeal Day and I want a flight of [...]]]></description>
				<content:encoded><![CDATA[<p>I’ve been intrigued by <a href="http://nodejs.org" target="_blank">node.js</a> as a platform for highly-scalable server applications written in javascript and finally found a super simple application I wanted to try with it: an auto-tweeter that would let me schedule future tweets to my own account.  I’m organizing a pub crawl for <a href="http://repealdaysb.com" target="_blank">Repeal Day</a> and I want a flight of <a href="https://twitter.com/#!/RepealDaySB" target="_blank">tweets</a> to go out during the crawl… without me or my partners having to do it manually.</p>
<p>I mentioned this to my buddies at <a href="http://sbhackerspace.posterous.com/" target="_blank">Santa Barbara Hacker Space</a> and we made it a collaborative project.  I’ll miss this week&#8217;s <a href="http://sbhackerspace.posterous.com/new-class-webtech-wednesday-presents-learn-py" target="_blank">WebTech Wednesday</a> session, but perhaps a write up will help keep the conversation going.</p>
<p>The idea is pretty simple.  There are three components.</p>
<ol>
<li>The tweet engine</li>
<li>The datastore</li>
<li>CRUD Interfaces to the data store</li>
</ol>
<p>The tweet engine will query the datastore every so often and see if there are any tweets that need to be tweeted (because their tweet_by timestamp is in the past).</p>
<p>The datastore will hold the tweets and their tweet_by time, stored as UTC timestamps.</p>
<p>The CRUD interface will let us create, read, update and delete those tweets.</p>
<p>Future ideas:</p>
<ol>
<li>Use Twitter authentication for accessing the app</li>
<li>Bulk uploader for multiple tweets.</li>
<li>Support multiple users</li>
<li>Support queues of tweets, which get tweeted at a regular schedule</li>
<li>Support additional entity data with the tweets, such as geolocation</li>
</ol>
<p>Issues:</p>
<ol>
<li>Managing the timestamp will take some thought. The CRUD interface should use localtime—with an option to override the timezone—but store UTC in the database. That will avoid some common problems with tweets going out on the server’s time zone when the user thought it was set for theirs.</li>
<li>This first version will, unfortunately, be totally exposed to anyone who knows the URL. We’ll add twitter authentication as soon as possible.</li>
<li>Timing the engine will take some finesse. We could just poll the database, but that wastes a lot of cycles.  Instead, I&#8217;d like the engine to schedule itself to run at the next tweet_by time and have the CRUD either wake the process up early or kill &amp; restart it.</li>
</ol>
<p>That’s it for the start. More as it happens.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.joeandrieu.com/2011/11/09/towards-a-node-js-auto-tweeter/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Trust Me&#8230; Things Change.</title>
		<link>http://blog.joeandrieu.com/2011/04/22/trust-me-things-change/</link>
		<comments>http://blog.joeandrieu.com/2011/04/22/trust-me-things-change/#comments</comments>
		<pubDate>Fri, 22 Apr 2011 08:24:32 +0000</pubDate>
		<dc:creator>Joe Andrieu</dc:creator>
				<category><![CDATA[Information Sharing]]></category>
		<category><![CDATA[Personal Data Store]]></category>
		<category><![CDATA[Shared Information]]></category>
		<category><![CDATA[User Driven Services]]></category>
		<category><![CDATA[Vendor Relationship Management]]></category>
		<category><![CDATA[consent]]></category>
		<category><![CDATA[revocation]]></category>
		<category><![CDATA[trust]]></category>

		<guid isPermaLink="false">http://blog.joeandrieu.com/?p=979</guid>
		<description><![CDATA[Trust is complicated. But for some reason, online trust mechanisms assume it is outrageously simple. For example, firewalls imply that once you&#8217;re in the network, you&#8217;re trusted. It&#8217;s baked into the framing of the problem. Similarly, Trust Frameworks assume that once you are in the Framework, you&#8217;re trusted (although you could build a framework that [...]]]></description>
				<content:encoded><![CDATA[<p>Trust is complicated. But for some reason, online trust mechanisms assume it is outrageously simple.</p>
<p><img class="alignleft size-medium wp-image-980" title="black and white handshake" src="http://blog.joeandrieu.com/wp-content/uploads/2011/04/black-and-white-handshake.dreamstime_18851240-300x225.jpg" alt="black and white handshake" width="210" height="158" /></p>
<p>For example, firewalls imply that once you&#8217;re in the network, you&#8217;re trusted. It&#8217;s baked into the framing of the problem. Similarly, Trust Frameworks assume that once you are in the Framework, you&#8217;re trusted (although you <em>could</em> build a framework that is dynamic). Even a user directed approach like Facebook Connect assumes that once you click &#8220;allow&#8221;, you trust that website to use your information appropriately, essentially forever&#8230; even if you revoke that permission later.</p>
<p>Trust isn&#8217;t broad-based and it isn&#8217;t static. It is directed and dynamic.</p>
<p>Think about it. We don&#8217;t trust our accountant to babysit and we don&#8217;t trust our babysitter with our finances. Trust is given for specific purposes and in specific contexts and it changes as quickly as we can fire that babysitter.</p>
<p><img class="alignright size-medium wp-image-983" title="multiple multi color handshakes" src="http://blog.joeandrieu.com/wp-content/uploads/2011/04/multi-multi-color-handshakes.dreamstime_4062545-300x300.jpg" alt="multiple multi color handshakes" width="180" height="180" />We trust the receptionist at the doctor&#8217;s office with our written medical histories because he is behind the counter, apparently employed by the doctor who needs that information to do her job.  We trust the bartender with our credit card because she&#8217;s behind the bar serving drinks and we accept that it will be kept safe and not used until we close out the bill.  But we wouldn&#8217;t give that receptionist our medical history if we met him in a bar later that evening, and we wouldn&#8217;t give that bartender our credit card if we met her as a fellow patient in the doctor&#8217;s office the next day.</p>
<p>We trust people to do specific things—or not to do certain other things—and that trust is based on the context in which we give it and the state of our relationship with the trusted party.</p>
<p>That means that just like our relationships, trust changes over time. Trust systems need ways to discover that trust should change and allow for that change to be managed. Reagan put it perfectly, &#8220;Trust but verify.&#8221;</p>
<p><iframe title="YouTube video player" width="425" height="349" src="http://www.youtube.com/embed/As6y5eI01XE" frameborder="0" allowfullscreen></iframe></p>
<p>When verification fails, trust changes.</p>
<p>Whether it&#8217;s a romantic partner, a subcontractor, a company, or top-secret agent, trust is granted incrementally. When it is lost, it is often destroyed.</p>
<p>Incremental trust happens all the time. We don&#8217;t like logging in just to view a web page, but we don&#8217;t mind it to see confidential information like order history. We aren&#8217;t comfortable giving our credit card just to enter a store&#8211;the relationship isn&#8217;t ready for that yet&#8211;but we don&#8217;t mind once we start the check out process.</p>
<p>When we lose trust, we sometimes throw the jerks out on the street. Betrayal is an unfortunate fact of life; it also has great significance to how we handle online trust. How do we &#8220;break up&#8221; with service providers? Revoking consent and demanding our data purged is an obvious need, but one that is often obscured or impossible.  As our relationships change, our trust changes. Yet our digital trust models mostly don&#8217;t.</p>
<p>Online trust models assume that trust is binary, broad, and stable—that you either have it or you don’t—for one simple reason: because it&#8217;s easy to implement.</p>
<p>When we log into a website with Facebook Connect, Facebook verifies that we want to share information with the website. However, there is no way for us to modify the permissions. We can&#8217;t say what use is allowed and what isn&#8217;t. We can&#8217;t pick and choose which data they get. We can&#8217;t ask for additional consideration. And we can&#8217;t put a time limit on access. Facebook&#8217;s interface presumes all-or-nothing and forever, for anything. But what we&#8217;d really like is something like this:</p>
<blockquote><p>&#8220;You can write to my wall, but only for messages I explicitly approve. You can have my email address but only for account maintenance, not for &#8220;special offers&#8221; from you or your associates. You <strong>can&#8217;t</strong> have access to my home address. You can use the photos tagged &#8220;public&#8221; for one month after I post them, but I want a revenue share from any money you make from them. Ask me another time about reading my inbox.&#8221;</p></blockquote>
<p>In order for our trust model to support transactions like this, it needs to be specific <em>and</em> flexible. It should not only let us direct our trust to specific purposes, it should make it easy to moderate that trust as our relationships evolve.</p>
<p>Lawrence Lessig famously said &#8220;<a target="_blank" href="http://www.lessig.org/content/standard/0,1902,4165,00.html">Code is Law</a>&#8220;. Trust models like Facebook&#8217;s, and the code behind it, make it nearly impossible for sites to allow the kind of user-driven permissions we need. While our relationships evolve, the current platforms are actually too brittle for developers to implement flexible, user-respecting approaches to privacy and permission unless they are willing to jump through hoops and hack around arbitrary technical limitations.  We need a new code base that actually makes it easy for developers to do the right thing, rather than code that enshrines restrictive and disempowering practices as strongly as if the law made it mandatory.</p>
<p>Because the one thing I know is that tomorrow <em>will be</em> different, and the harder it is for developers to support changing relationships, the harder it is for the entire ecosystem to respond to changing needs.</p>
<p><strong>In short:</strong></p>
<p>Stop the monolithic permissioning ceremonies!</p>
<p>Trust evolves.</p>
<p>Deal with it.</p>
<p>Until we do, online trust will remain brittle and untenable for our most important, powerful, and profitable relationships.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.joeandrieu.com/2011/04/22/trust-me-things-change/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
