diff --git a/apps/routerconsole/java/src/net/i2p/router/web/PluginUpdateChecker.java b/apps/routerconsole/java/src/net/i2p/router/web/PluginUpdateChecker.java
index 28c1e5aa562b05360bef213717c9a539fcb0a8b3..8645df585559f8ef83581766cceb1401fcece6cc 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/PluginUpdateChecker.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/PluginUpdateChecker.java
@@ -17,18 +17,13 @@ import net.i2p.util.PartialEepGet;
 import net.i2p.util.VersionComparator;
 
 /**
- * Download and install a plugin.
+ * Check for an updated version of a plugin.
  * A plugin is a standard .sud file with a 40-byte signature,
  * a 16-byte version, and a .zip file.
- * Unlike for router updates, we need not have the public key
- * for the signature in advance.
  *
- * The zip file must have a standard directory layout, with
- * a plugin.config file at the top level.
- * The config file contains properties for the package name, version,
- * signing public key, and other settings.
- * The zip file will typically contain a webapps/ or lib/ dir,
- * and a webapps.config and/or clients.config file.
+ * So we get the current version and update URL for the installed plugin,
+ * then fetch the first 56 bytes of the URL, extract the version,
+ * and compare.
  *
  * @since 0.7.12
  * @author zzz
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/WebAppConfiguration.java b/apps/routerconsole/java/src/net/i2p/router/web/WebAppConfiguration.java
index c3fcc334aa2017733429d5af9cfca2b525fc1a81..1cfc09b4cde5a23001b852b80e04dba5f8e2ff20 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/WebAppConfiguration.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/WebAppConfiguration.java
@@ -16,7 +16,7 @@ import org.mortbay.jetty.servlet.WebApplicationContext;
  *  individual jars and not lib/*.jar specified in wrapper.config.
  *
  *  A sample line in webapps.config is:
- *     webapps.appname.path=foo.jar,$I2P/lib/bar.jar
+ *     webapps.appname.classpath=foo.jar,$I2P/lib/bar.jar
  *  Unless $I2P is specified the path will be relative to $I2P/lib for
  *  webapps in the installation and appDir/plugins/appname/lib for plugins.
  *
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/WebAppStarter.java b/apps/routerconsole/java/src/net/i2p/router/web/WebAppStarter.java
index fd64f71f5fe598da9c9b1aa086f08b4831495253..048ef31cc67619bcb43e0c92f470df9207c4ec94 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/WebAppStarter.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/WebAppStarter.java
@@ -15,13 +15,14 @@ import org.mortbay.jetty.servlet.WebApplicationContext;
 
 
 /**
- *  Start a webappapp classpath as specified in webapps.config.
+ *  Add, start or stop a webapp.
+ *  Add to the webapp classpath if specified in webapps.config.
  *
  *  Sadly, setting Class-Path in MANIFEST.MF doesn't work for jetty wars.
- *  We could look there ourselves, or look for another properties file in the war,
+ *  See WebAppConfiguration for more information.
  *  but let's just do it in webapps.config.
  *
- *  No, wac.addClassPath() does not work.
+ *  No, wac.addClassPath() does not work. For more info see:
  *
  *  http://servlets.com/archive/servlet/ReadMsg?msgId=511113&listName=jetty-support
  *
diff --git a/core/java/src/net/i2p/CoreVersion.java b/core/java/src/net/i2p/CoreVersion.java
index 9f40718005444f44d4183a8e7f40031dd2358c7c..7465774e2d0c537ece80dd83bf56d6193547a1bb 100644
--- a/core/java/src/net/i2p/CoreVersion.java
+++ b/core/java/src/net/i2p/CoreVersion.java
@@ -16,7 +16,7 @@ package net.i2p;
 public class CoreVersion {
     /** deprecated */
     public final static String ID = "Monotone";
-    public final static String VERSION = "0.7.11";
+    public final static String VERSION = "0.7.12";
 
     public static void main(String args[]) {
         System.out.println("I2P Core version: " + VERSION);
diff --git a/core/java/src/net/i2p/crypto/TrustedUpdate.java b/core/java/src/net/i2p/crypto/TrustedUpdate.java
index b9ab3187e175665606a166ac47095f2dedd329ed..41c69eb83f548c342d01d35812060025590ec2ec 100644
--- a/core/java/src/net/i2p/crypto/TrustedUpdate.java
+++ b/core/java/src/net/i2p/crypto/TrustedUpdate.java
@@ -404,6 +404,8 @@ D8usM7Dxp5yrDrCYZ5AIijc=
      * 
      * @return The version string read, or an empty string if no version string
      *         is present.
+     *
+     * @since 0.7.12
      */
     public static String getVersionString(InputStream inputStream) {
         try {
@@ -492,6 +494,8 @@ D8usM7Dxp5yrDrCYZ5AIijc=
      * 
      * @return <code>null</code> if the
      *         data was moved, and an error <code>String</code> otherwise.
+     *
+     * @since 0.7.12
      */
     public String migrateFile(File signedFile, File outputFile) {
         if (!signedFile.exists())
diff --git a/core/java/src/net/i2p/time/Timestamper.java b/core/java/src/net/i2p/time/Timestamper.java
index 57b1dc28610510549c6759e0a17dfce801e29f58..a84882215c275ff3514e96e99b7a251671422827 100644
--- a/core/java/src/net/i2p/time/Timestamper.java
+++ b/core/java/src/net/i2p/time/Timestamper.java
@@ -252,6 +252,8 @@ public class Timestamper implements Runnable {
     
     /**
      * Notify the listeners
+     *
+     * @since stratum param added in 0.7.12
      */
     private void stampTime(long now, int stratum) {
         long before = _context.clock().now();
diff --git a/history.txt b/history.txt
index 8b15303a95199912784313412fe1f1b64025bc89..9105247bf84bcffe60863704d39e0e0dad2dfeac 100644
--- a/history.txt
+++ b/history.txt
@@ -1,4 +1,6 @@
-2010-03-013 zzz
+* 2010-03-15  0.7.12 released
+
+2010-03-13 zzz
     * Partial fix for i2ptunnel nonce troubles
 
 2010-03-08 zzz
diff --git a/installer/install.xml b/installer/install.xml
index 06e55256d971d31a013a6e3a88ef4b4cb1f07821..c4931cb90a96f445f48e84c6488c7bec6b39d524 100644
--- a/installer/install.xml
+++ b/installer/install.xml
@@ -4,7 +4,7 @@
 
     <info>
         <appname>i2p</appname>
-        <appversion>0.7.11</appversion>
+        <appversion>0.7.12</appversion>
         <authors>
             <author name="I2P" email="http://forum.i2p2.de/"/>
         </authors>
diff --git a/installer/resources/initialNews.xml b/installer/resources/initialNews.xml
index dd40850c2a4cb739bed71597468b53fc02b95131..7f46cec45b39e4c34f6022df154ea22b09ae9b83 100644
--- a/installer/resources/initialNews.xml
+++ b/installer/resources/initialNews.xml
@@ -1,6 +1,6 @@
 <!--
-<i2p.news date="$Date: 2010-02-15 00:00:00 $">
-<i2p.release version="0.7.11" date="2010/02/15" minVersion="0.6"/>
+<i2p.news date="$Date: 2010-03-15 00:00:00 $">
+<i2p.release version="0.7.12" date="2010/03/15" minVersion="0.6"/>
 -->
 <h4><ul><li>Congratulations on getting I2P installed!</li></ul></h4>
 <p>
diff --git a/installer/resources/news.xml b/installer/resources/news.xml
index 9a76a074ff7fc6dc3320a4c75430290076ac5674..8a31fb44f4990b1e07335fc69d0821944fcdfe2d 100644
--- a/installer/resources/news.xml
+++ b/installer/resources/news.xml
@@ -1,21 +1,29 @@
 <!--
-<i2p.news date="$Date: 2010-02-15 00:00:00 $">
-<i2p.release version="0.7.11" date="2010/02/15" minVersion="0.6" />
+<i2p.news date="$Date: 2010-03-15 00:00:00 $">
+<i2p.release version="0.7.12" date="2010/03/15" minVersion="0.6" />
 -->
-<h4><ul><li>2010-02-15: <b>0.7.11 <a href="http://www.i2p2.i2p/release-0.7.11.html">Released</a></b></li></ul></h4>
+<h4><ul><li>2010-03-15: <b>0.7.12 <a href="http://www.i2p2.i2p/release-0.7.12.html">Released</a></b></li></ul></h4>
 <p>
-The 0.7.11 release fixes several issues, some related to clocks, which prevented new routers from quickly integrating into the network.
-It also fixes the installer for 64-bit Windows.
-The release includes an
-update to <a href="http://old.nabble.com/jetty-5.1.15,-6.1.18-and-7.0.0.M2-td23652819.html">Jetty 5.1.15</a>
-to fix <a href="http://www.kb.cert.org/vuls/id/402580">this vulnerability</a>.
+The 0.7.12 release contains support for user-generated plugins. These plugins may contain console web applications,
+themes, translations, or standalone programs.
+Some plugins are available for testing at
+<a href="http://i2pbote.i2p/">i2pbote.i2p</a>
+and
+<a href="http://stats.i2p/i2p/plugins/">stats.i2p</a>.
+We are hopeful this support will enable rapid development of innovative i2p applications.
+</p><p>
+The release fixes the blank-page bug when an eepsite is not reachable,
+and also improves handling of clock skews and IP changes.
+It adds support for a new, smaller tunnel build message,
+that will be tested in this release and enabled in the next release.
 </p><p>
 As usual, the release contains more anonymity and performance improvements,
-and an assortment of bug fixes.
+translation updates, and an assortment of other bug fixes.
 Upgrading is recommended.
 </p><p>
-We already have more big improvements in development for the next two releases.
-Please give the
+The last 6 months of development have dramatically increased the performance and capacity of the network.
+Please help grow the network.
+Give the
 developers feedback on <a href="irc://127.0.0.1:6668/i2p">IRC #i2p</a> or <a href="http://forum.i2p">forum.i2p</a>
 and <a href="http://www.i2p2.i2p/getinvolved.html">get involved</a>,
 spread the word,
diff --git a/router/java/src/net/i2p/data/i2np/TunnelBuildMessage.java b/router/java/src/net/i2p/data/i2np/TunnelBuildMessage.java
index ab880031f340a224425d26cad0776b3425e102ca..68603d1d91c4a588e9b98a079950f2100ab10775 100644
--- a/router/java/src/net/i2p/data/i2np/TunnelBuildMessage.java
+++ b/router/java/src/net/i2p/data/i2np/TunnelBuildMessage.java
@@ -19,7 +19,7 @@ public class TunnelBuildMessage extends I2NPMessageImpl {
         this(context, MAX_RECORD_COUNT);
     }
 
-    /** @since 0.7.10 */
+    /** @since 0.7.12 */
     protected TunnelBuildMessage(I2PAppContext context, int records) {
         super(context);
         if (records > 0) {
@@ -31,7 +31,7 @@ public class TunnelBuildMessage extends I2NPMessageImpl {
 
     public void setRecord(int index, ByteArray record) { _records[index] = record; }
     public ByteArray getRecord(int index) { return _records[index]; }
-    /** @since 0.7.10 */
+    /** @since 0.7.12 */
     public int getRecordCount() { return RECORD_COUNT; }
     
     public static final int RECORD_SIZE = 512+16;
diff --git a/router/java/src/net/i2p/data/i2np/TunnelBuildReplyMessage.java b/router/java/src/net/i2p/data/i2np/TunnelBuildReplyMessage.java
index 7a0fc8563794b8df81f1329e6d056909e80c86b8..69b36c619cb3f7a1af689db88bf33c9a2d42998b 100644
--- a/router/java/src/net/i2p/data/i2np/TunnelBuildReplyMessage.java
+++ b/router/java/src/net/i2p/data/i2np/TunnelBuildReplyMessage.java
@@ -20,7 +20,7 @@ public class TunnelBuildReplyMessage extends I2NPMessageImpl {
         this(context, MAX_RECORD_COUNT);
     }
 
-    /** @since 0.7.10 */
+    /** @since 0.7.12 */
     protected TunnelBuildReplyMessage(I2PAppContext context, int records) {
         super(context);
         if (records > 0) {
@@ -32,7 +32,7 @@ public class TunnelBuildReplyMessage extends I2NPMessageImpl {
 
     public void setRecord(int index, ByteArray record) { _records[index] = record; }
     public ByteArray getRecord(int index) { return _records[index]; }
-    /** @since 0.7.10 */
+    /** @since 0.7.12 */
     public int getRecordCount() { return RECORD_COUNT; }
     
     public static final int RECORD_SIZE = TunnelBuildMessage.RECORD_SIZE;
diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java
index 138e7939b936c39470447fc611a1ddfb384ac9d2..200f91ede8c16cdc10831b7dd9624a59ef0f23ae 100644
--- a/router/java/src/net/i2p/router/RouterVersion.java
+++ b/router/java/src/net/i2p/router/RouterVersion.java
@@ -18,10 +18,10 @@ public class RouterVersion {
     /** deprecated */
     public final static String ID = "Monotone";
     public final static String VERSION = CoreVersion.VERSION;
-    public final static long BUILD = 11;
+    public final static long BUILD = 0;
 
     /** for example "-test" */
-    public final static String EXTRA = "-rc";
+    public final static String EXTRA = "";
     public final static String FULL_VERSION = VERSION + "-" + BUILD + EXTRA;
     public static void main(String args[]) {
         System.out.println("I2P Router version: " + FULL_VERSION);
diff --git a/router/java/src/net/i2p/router/startup/ClientAppConfig.java b/router/java/src/net/i2p/router/startup/ClientAppConfig.java
index 4c5125bc2cc080b73148ddd22feab7089416a6d2..a387228e418b9f3693855244a1420ec4cc12a6a9 100644
--- a/router/java/src/net/i2p/router/startup/ClientAppConfig.java
+++ b/router/java/src/net/i2p/router/startup/ClientAppConfig.java
@@ -93,6 +93,8 @@ public class ClientAppConfig {
 
     /*
      * Go through the properties, and return a List of ClientAppConfig structures
+     *
+     * @since 0.7.12
      */
     public static List<ClientAppConfig> getClientApps(File cfgFile) {
         Properties clientApps = new Properties();
@@ -106,6 +108,8 @@ public class ClientAppConfig {
 
     /*
      * Go through the properties, and return a List of ClientAppConfig structures
+     *
+     * @since 0.7.12
      */
     private static List<ClientAppConfig> getClientApps(Properties clientApps) {
         List<ClientAppConfig> rv = new ArrayList(8);
diff --git a/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java b/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java
index 15ffd117012493f1800c5b5dbb56fbc13d703adc..aa6417fdac45334f7e4d3986cec971a4a9cc9942 100644
--- a/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java
+++ b/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java
@@ -506,6 +506,7 @@ class BuildExecutor implements Runnable {
     /**
      *  Only do this for non-fallback tunnels.
      *  @return true if refused because of a duplicate key
+     *  @since 0.7.12
      */
     private boolean addToBuilding(PooledTunnelCreatorConfig cfg) {
         //_log.error("Adding ID: " + cfg.getReplyMessageId() + "; size was: " + _currentlyBuildingMap.size());
@@ -521,6 +522,7 @@ class BuildExecutor implements Runnable {
      *  But that's ok. A peer that rejects slowly gets penalized twice, for example.
      *
      *  @return ptcc or null
+     *  @since 0.7.12
      */
     PooledTunnelCreatorConfig removeFromBuilding(long id) {
         //_log.error("Removing ID: " + id + "; size was: " + _currentlyBuildingMap.size());
diff --git a/router/java/src/net/i2p/router/tunnel/pool/BuildRequestor.java b/router/java/src/net/i2p/router/tunnel/pool/BuildRequestor.java
index d6c3e0a5f3f276847152be2bf46b5d44837b72ca..03a7b6ef943e4a459eb5e8656dc6b02f277c7280 100644
--- a/router/java/src/net/i2p/router/tunnel/pool/BuildRequestor.java
+++ b/router/java/src/net/i2p/router/tunnel/pool/BuildRequestor.java
@@ -187,6 +187,7 @@ class BuildRequestor {
             SHORT_ORDER.add(Integer.valueOf(i));
     }
 
+    /** @since 0.7.12 */
     private static boolean supportsVariable(RouterContext ctx, Hash h) {
         RouterInfo ri = ctx.netDb().lookupRouterInfoLocally(h);
         if (ri == null)