diff --git a/Changelog.md b/Changelog.md
index 7e3a39738561186d4e619e5ca6e679450d9bc26d..055c1ebd34e5bec0ad59c4ba2805e0a9be024d18 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -2,6 +2,9 @@
 
 All notable changes to this project will be documented in this file.
 
+## [0.62] - 2021-03-24
+- POL1-392: added latch timestamp to version response
+
 ## [0.61] - 2021-03-05
 - POL1-380: added /poller/speeds route
 
diff --git a/circuit_tree.py b/circuit_tree.py
new file mode 100644
index 0000000000000000000000000000000000000000..96b7928e6629f7715fcb94d37979c684e399bbfb
--- /dev/null
+++ b/circuit_tree.py
@@ -0,0 +1,63 @@
+import os
+from operator import itemgetter
+
+import click
+from tree_format import format_tree
+
+from inventory_provider.db.ims import IMS, CIRCUIT_PROPERTIES
+
+username = 'TEST05'
+password = ''
+bt = os.getenv('IMS_BT')
+
+ds = IMS('http://83.97.94.128:2080/api', username, password, bt)
+
+NAV_PROPS = [
+    CIRCUIT_PROPERTIES['Speed'],
+    CIRCUIT_PROPERTIES['Product']
+]
+
+
+@click.command()
+@click.option('-c', 'carriers', is_flag=True)
+@click.argument('root_circuit_id', type=click.INT, required=True)
+def cli(carriers, root_circuit_id):
+    if carriers:
+        children_prop = 'carriercircuits'
+        childid = 'carriercircuitid'
+        NAV_PROPS.append(CIRCUIT_PROPERTIES['CarrierCircuits'])
+    else:
+        children_prop = 'subcircuits'
+        childid = 'subcircuitid'
+        NAV_PROPS.append(CIRCUIT_PROPERTIES['SubCircuits'])
+
+    def _get_childcircuit_tree(circuit_id):
+
+        circuit = ds.get_entity_by_id(
+            'circuit', circuit_id, navigation_properties=NAV_PROPS)
+        _tree = [
+            f'{circuit["id"]} -- {circuit["name"]} -- '
+            f'prod. {circuit["product"]["name"]} -- '
+            f'spd. {circuit["speed"]["name"]}'
+        ]
+
+        if circuit[children_prop]:
+
+            children = []
+            for child_circuit in circuit[children_prop]:
+                children.append(_get_childcircuit_tree(
+                    child_circuit[childid]
+                ))
+            _tree.append(children)
+        else:
+            _tree.append([])
+        return _tree
+    tree = _get_childcircuit_tree(root_circuit_id)
+    print(format_tree(
+        tree, format_node=itemgetter(0), get_children=itemgetter(1))
+    )
+
+
+if __name__ == '__main__':
+    # 659386
+    cli()
diff --git a/inventory_provider/routes/default.py b/inventory_provider/routes/default.py
index f65d6124835c09f70459f9d2defe01a36e23dbd6..047cc10e3534d092879545c3f3a3ab8cf0e882e8 100644
--- a/inventory_provider/routes/default.py
+++ b/inventory_provider/routes/default.py
@@ -4,42 +4,43 @@ from flask import Blueprint, jsonify, current_app
 from inventory_provider.routes import common
 from inventory_provider.tasks.common import get_current_redis, get_latch
 
-routes = Blueprint("inventory-data-default-routes", __name__)
+routes = Blueprint('inventory-data-default-routes', __name__)
 
 API_VERSION = '0.1'
 
 VERSION_SCHEMA = {
-    "$schema": "http://json-schema.org/draft-07/schema#",
+    '$schema': 'http://json-schema.org/draft-07/schema#',
 
-    "definitions": {
-        "latch": {
-            "type": "object",
-            "properties": {
-                "current": {"type": "integer"},
-                "next": {"type": "integer"},
-                "this": {"type": "integer"},
-                "failure": {"type": "boolean"},
-                "pending": {"type": "boolean"},
+    'definitions': {
+        'latch': {
+            'type': 'object',
+            'properties': {
+                'current': {'type': 'integer'},
+                'next': {'type': 'integer'},
+                'this': {'type': 'integer'},
+                'failure': {'type': 'boolean'},
+                'pending': {'type': 'boolean'},
+                'timestamp': {'type': 'number'}
             },
-            "required": ["current", "next", "this", "pending", "failure"],
-            "additionalProperties": False
+            'required': ['current', 'next', 'this', 'pending', 'failure'],
+            'additionalProperties': False
         }
     },
 
-    "type": "object",
-    "properties": {
-        "api": {
-            "type": "string",
-            "pattern": r'\d+\.\d+'
+    'type': 'object',
+    'properties': {
+        'api': {
+            'type': 'string',
+            'pattern': r'\d+\.\d+'
         },
-        "module": {
-            "type": "string",
-            "pattern": r'\d+\.\d+'
+        'module': {
+            'type': 'string',
+            'pattern': r'\d+\.\d+'
         },
-        "latch": {"$ref": "#/definitions/latch"}
+        'latch': {'$ref': '#/definitions/latch'}
     },
-    "required": ["api", "module"],
-    "additionalProperties": False
+    'required': ['api', 'module'],
+    'additionalProperties': False
 }
 
 
@@ -48,7 +49,7 @@ def after_request(resp):
     return common.after_request(resp)
 
 
-@routes.route("/version", methods=['GET', 'POST'])
+@routes.route('/version', methods=['GET', 'POST'])
 @common.require_accepts_json
 def version():
     """
diff --git a/inventory_provider/tasks/common.py b/inventory_provider/tasks/common.py
index ac85afb7de7094517c95cf2ed5f2929b211f6afc..427d51d8a18e4128f3dd3b174274e65fa17f5f8f 100644
--- a/inventory_provider/tasks/common.py
+++ b/inventory_provider/tasks/common.py
@@ -1,5 +1,6 @@
 import json
 import logging
+import time
 
 import jsonschema
 import redis
@@ -11,17 +12,18 @@ DEFAULT_REDIS_SENTINEL_TIMEOUT = 0.1
 DEFAULT_SENTINEL_SOCKET_TIMEOUT = 0.1
 
 DB_LATCH_SCHEMA = {
-    "$schema": "http://json-schema.org/draft-07/schema#",
-    "type": "object",
-    "properties": {
-        "current": {"type": "integer"},
-        "next": {"type": "integer"},
-        "this": {"type": "integer"},
-        "pending": {"type": "boolean"},
-        "failure": {"type": "boolean"}
+    '$schema': 'http://json-schema.org/draft-07/schema#',
+    'type': 'object',
+    'properties': {
+        'current': {'type': 'integer'},
+        'next': {'type': 'integer'},
+        'this': {'type': 'integer'},
+        'pending': {'type': 'boolean'},
+        'failure': {'type': 'boolean'},
+        'timestamp': {'type': 'number'}
     },
-    "required": ["current", "next", "this"],
-    "additionalProperties": False
+    'required': ['current', 'next', 'this'],
+    'additionalProperties': False
 }
 
 TASK_LOG_SCHEMA = {
@@ -86,17 +88,24 @@ def update_latch_status(config, pending=False, failure=False):
     logger.debug('updating latch status: pending={}, failure={}'.format(
         pending, failure))
 
+    now = time.time()
     for db in config['redis-databases']:
         r = _get_redis(config, dbid=db)
         latch = get_latch(r)
         if not latch:
             continue
+        if not pending and not failure:
+            if not latch['pending'] and not latch['failure']:
+                logger.error(
+                    'updating latch for db {db} with pending=failure=True, '
+                    f'but latch is already {latch}')
+            latch['timestamp'] = now
         latch['pending'] = pending
         latch['failure'] = failure
         r.set('db:latch', json.dumps(latch))
 
 
-def set_latch(config, new_current, new_next):
+def set_latch(config, new_current, new_next, timestamp):
 
     logger.debug('setting latch: new current={}, new next={}'.format(
         new_current, new_next))
@@ -107,7 +116,8 @@ def set_latch(config, new_current, new_next):
             'next': new_next,
             'this': db,
             'pending': False,
-            'failure': False
+            'failure': False,
+            'timestamp': timestamp
         }
 
         r = _get_redis(config, dbid=db)
@@ -129,7 +139,11 @@ def latch_db(config):
     next_idx = db_ids.index(latch['next'])
     next_idx = (next_idx + 1) % len(db_ids)
 
-    set_latch(config, new_current=latch['next'], new_next=db_ids[next_idx])
+    set_latch(
+        config,
+        new_current=latch['next'],
+        new_next=db_ids[next_idx],
+        timestamp=time.time())
 
 
 def _get_redis(config, dbid=None):
diff --git a/inventory_provider/tasks/worker.py b/inventory_provider/tasks/worker.py
index 8a85d7e6ad1cac9db894b2730755addb6057b00f..9102731490f31548ccb06818d5e109196635dce2 100644
--- a/inventory_provider/tasks/worker.py
+++ b/inventory_provider/tasks/worker.py
@@ -199,7 +199,7 @@ def update_interfaces_to_services(self):
     rp.execute()
 
 
-def _unmanaged_interfaces(self):
+def _unmanaged_interfaces():
 
     def _convert(d):
         # the config file keys are more readable than
@@ -215,18 +215,6 @@ def _unmanaged_interfaces(self):
         _convert,
         InventoryTask.config.get('unmanaged-interfaces', []))
 
-    # if interfaces:
-    #     r = get_next_redis(InventoryTask.config)
-    #     rp = r.pipeline()
-    #     for ifc in interfaces:
-    #         rp.set(
-    #             f'reverse_interface_addresses:{ifc["name"]}',
-    #             json.dumps(ifc))
-    #         rp.set(
-    #             f'subnets:{ifc["interface address"]}',
-    #             json.dumps([ifc]))
-    #     rp.execute()
-
 
 @app.task(base=InventoryTask, bind=True, name='update_access_services')
 @log_task_entry_and_exit
@@ -553,7 +541,8 @@ def _erase_next_db(config):
         set_latch(
             config,
             new_current=saved_latch['current'],
-            new_next=saved_latch['next'])
+            new_next=saved_latch['next'],
+            timestamp=saved_latch.get('timestamp', 0))
 
 
 @app.task(base=InventoryTask, bind=True, name='internal_refresh_phase_2')
@@ -710,6 +699,10 @@ def _build_subnet_db(update_callback=lambda s: None):
             entry = subnets.setdefault(ifc['interface address'], [])
             entry.append(ifc)
 
+    for ifc in _unmanaged_interfaces():
+        entry = subnets.setdefault(ifc['interface address'], [])
+        entry.append(ifc)
+
     update_callback('saving {} subnets'.format(len(subnets)))
 
     rp = r.pipeline()
diff --git a/setup.py b/setup.py
index 74ed25b87921f2629418f0fdfd3966ffc3a83bdf..4832a99f1912f06f8d5044f585c61a108fac9c9a 100644
--- a/setup.py
+++ b/setup.py
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
 
 setup(
     name='inventory-provider',
-    version="0.61",
+    version="0.62",
     author='GEANT',
     author_email='swd@geant.org',
     description='Dashboard inventory provider',
diff --git a/test/conftest.py b/test/conftest.py
index 4bafdb12d30e117bc0de5cd261e1d1bdec8f240a..2984ae3785845bc100471a30a207177601be2da3 100644
--- a/test/conftest.py
+++ b/test/conftest.py
@@ -54,6 +54,20 @@ def data_config_filename():
                 "password": "ims_password"
               },
             "managed-routers": "bogus url",
+            "unmanaged-interfaces": [
+                {
+                    "address": "99.99.99.99",
+                    "network": "99.99.99.0/24",
+                    "interface": "ABC/0/0/0",
+                    "router": "bogus.host.name"
+                },
+                {
+                    "address": "999.999.999.99",
+                    "network": "999.999.999.0/24",
+                    "interface": "ZZZ/9/a/x:0.123",
+                    "router": "another.bogus.host.name"
+                }
+            ]
         }
 
         f.write(json.dumps(config).encode('utf-8'))
diff --git a/test/test_celery_worker_global.py b/test/test_celery_worker_global.py
index 330f8d815e4040eb06abef7d2d0594075e72e41c..ecd1d25e192ecaa06ee4528684292366a8472e2a 100644
--- a/test/test_celery_worker_global.py
+++ b/test/test_celery_worker_global.py
@@ -77,7 +77,7 @@ def test_next_redis(data_config, mocked_redis):
     :param mocked_redis:
     :return:
     """
-    common.set_latch(data_config, 10, 20)
+    common.set_latch(data_config, 10, 20, 100)
     r = common.get_next_redis(data_config)
     assert r
 
@@ -85,6 +85,7 @@ def test_next_redis(data_config, mocked_redis):
     latch = common.get_latch(r)
     assert latch['current'] == 10
     assert latch['next'] == 20
+    assert latch['timestamp'] == 100
 
 
 def test_next_redis_with_none(data_config, mocked_redis):
diff --git a/test/test_general_routes.py b/test/test_general_routes.py
index 254d9db122b4d944bdd66df67f8a41e5ca67712c..8bc82db71c96426f68d502f8fe4dac4e2414cd40 100644
--- a/test/test_general_routes.py
+++ b/test/test_general_routes.py
@@ -5,59 +5,59 @@ from inventory_provider.routes import common
 from inventory_provider.routes.default import VERSION_SCHEMA
 
 DEFAULT_REQUEST_HEADERS = {
-    "Content-type": "application/json",
-    "Accept": ["application/json"]
+    'Content-type': 'application/json',
+    'Accept': ['application/json']
 }
 
 
 def test_version_request(client, mocked_redis):
 
     rv = client.post(
-        "version",
+        'version',
         headers=DEFAULT_REQUEST_HEADERS)
     assert rv.status_code == 200
     jsonschema.validate(
-        json.loads(rv.data.decode("utf-8")),
+        json.loads(rv.data.decode('utf-8')),
         VERSION_SCHEMA)
 
 
 def test_load_json_docs(data_config, mocked_redis):
 
     INTERFACE_SCHEMA = {
-        "$schema": "http://json-schema.org/draft-07/schema#",
+        '$schema': 'http://json-schema.org/draft-07/schema#',
 
-        "definitions": {
-            "interface": {
-                "type": "object",
-                "properties": {
-                    "logical-system": {"type": "string"},
-                    "name": {"type": "string"},
-                    "description": {"type": "string"},
-                    "bundle": {
-                        "type": "array",
-                        "items": {"type": "string"}
+        'definitions': {
+            'interface': {
+                'type': 'object',
+                'properties': {
+                    'logical-system': {'type': 'string'},
+                    'name': {'type': 'string'},
+                    'description': {'type': 'string'},
+                    'bundle': {
+                        'type': 'array',
+                        'items': {'type': 'string'}
                     },
-                    "ipv4": {
-                        "type": "array",
-                        "items": {"type": "string"}
+                    'ipv4': {
+                        'type': 'array',
+                        'items': {'type': 'string'}
                     },
-                    "ipv6": {
-                        "type": "array",
-                        "items": {"type": "string"}
+                    'ipv6': {
+                        'type': 'array',
+                        'items': {'type': 'string'}
                     }
                 },
-                "required": ["name", "description", "ipv4", "ipv6"],
-                "additionalProperties": False
+                'required': ['name', 'description', 'ipv4', 'ipv6'],
+                'additionalProperties': False
             }
         },
 
-        "type": "object",
-        "properties": {
-            "key": {"type": "string"},
-            "value": {"$ref": "#/definitions/interface"}
+        'type': 'object',
+        'properties': {
+            'key': {'type': 'string'},
+            'value': {'$ref': '#/definitions/interface'}
         },
-        "required": ["key", "value"],
-        "additionalProperties": False
+        'required': ['key', 'value'],
+        'additionalProperties': False
     }
 
     for ifc in common.load_json_docs(
diff --git a/test/test_worker_utils.py b/test/test_worker_utils.py
index 198bc43b2591fe5f40eb381c9763adcaf73a939f..f18c826456595a9e084787c8cb982eb47561dcb6 100644
--- a/test/test_worker_utils.py
+++ b/test/test_worker_utils.py
@@ -11,6 +11,7 @@ import jsonschema
 from inventory_provider.tasks import worker
 from inventory_provider.tasks import common
 from inventory_provider.routes import msr
+from inventory_provider import config
 
 
 def backend_db():
@@ -23,7 +24,7 @@ def backend_db():
     }).db
 
 
-def test_build_subnet_db(mocked_worker_module):
+def test_build_subnet_db(mocked_worker_module, data_config_filename):
     """
     Verify that valid reverse subnet objects are created.
 
@@ -52,6 +53,16 @@ def test_build_subnet_db(mocked_worker_module):
         'items': {"$ref": "#/definitions/interface"},
     }
 
+    all_subnet_interfaces = set()
+    unmanaged_interfaces = set()
+    with open(data_config_filename) as f:
+        params = config.load(f)
+        for ifc in params.get('unmanaged-interfaces', []):
+            ifc_key = (f'{ifc["router"].lower()}'
+                       f':{ifc["interface"].lower()}'
+                       f':{ifc["network"]}')
+            unmanaged_interfaces.add(ifc_key)
+
     db = backend_db()  # also forces initialization
 
     def _x(k):
@@ -80,8 +91,16 @@ def test_build_subnet_db(mocked_worker_module):
         for ifc in value:
             assert ifc['interface address'] == address
 
+        ifc_key = (f'{ifc["router"]}'
+                   f':{ifc["interface name"]}'
+                   f':{ifc["interface address"]}')
+
+        all_subnet_interfaces.add(ifc_key)
+
     assert found_record
 
+    assert unmanaged_interfaces <= all_subnet_interfaces
+
 
 def test_build_juniper_peering_db(mocked_worker_module):
     """