                 .replaceString("\\*",       "[^/:?]*")
                 + "($|\\?)")
         
-        debugLog(.Configuration, ["URL pattern", urlPattern, "compiles to regex", pattern.pattern])
-        
-        configure(
-            { pattern.matches($0.absoluteString) },
-            description: description ?? urlPattern,
-            configurer: configurer)
-        }
-    
-    /**
-      Accepts an arbitrary URL matching predicate if the wildcards in the `urlPattern` flavor of `configure()`
-      aren’t robust enough.
-    */
-    public final func configure(
-            urlMatcher: NSURL -> Bool,
-            description: String? = nil,
-            configurer: Configuration.Builder -> Void)
-        {
-        let entry = ConfigurationEntry(
-            description: "config \(nextConfigID) [" + (description ?? "custom") + "]",
-            urlMatcher: urlMatcher,
-            configurer: configurer)
-        configurationEntries.append(entry)
-        debugLog(.Configuration, ["Added", entry])
-        }
-    
-    /**
-      A convenience to add a one-off content transformer. Useful for transformers that create model objects. Example:
-      
-          $0.config.addContentTransformer { MyModel(json: $0) }
-    */
-    public final func configureTransformer<I,O>(
-            urlPattern: String,
-            description: String? = nil,
-            contentTransform: ResponseContentTransformer<I,O>.Processor)
-        {
-        configure(urlPattern, description: description ?? "\(urlPattern) : \(I.self) → \(O.self)")
-            {
-            $0.config.responseTransformers.add(
-                ResponseContentTransformer(processor: contentTransform))
-            }
-        }
-    
-    private var configID = 0
-    private var nextConfigID: Int { return configID++ }
-    
-    /**
-      Signals that all resources need to recompute their configuration next time they need it.
-      
-      Because the `configure(...)` methods accept an arbitrary closure, it is possible that the results of
-      that closure could change over time. However, resources cache their configuration after it is computed. Therefore,
-      if you do anything that would change the result of a configuration closure, you must call
-      `invalidateConfiguration()` in order for the changes to take effect.
-      
-      _《insert your functional programming purist rant here if you so desire》_
-
-      Note that you do _not_ need to call this method after calling any of the `configure(...)` methods.
-      You only need to call it if one of the previously passed closures will now behave differently.
-    
-      For example, to make a header track the value of a modifiable property:
-
-          var flavor: String {
-            didSet { invalidateConfiguration() }
-          }
-
-          init() {
-            super.init(base: "https://api.github.com")
-            configure​ {
-              $0.config.headers["Flavor-of-the-month"] = self.flavor  // NB: use weak self if service isn’t a singleton
-            }
-          }
-    
-      Note that this method does _not_ immediately recompute all existing configurations. This is an inexpensive call.
-      Configurations are computed lazily, and the (still relatively low) performance impact of recomputation is spread
-      over subsequent resource interactions.
-    */
-    public final func invalidateConfiguration()
-        {
-        if anyConfigSinceLastInvalidation
-            { debugLog(.Configuration, ["Configurations need to be recomputed"]) }
-        anyConfigSinceLastInvalidation = false
-        
-        configVersion++
-        }
-
-    private var anyConfigSinceLastInvalidation = false
-    
-    internal func configurationForResource(resource: Resource) -> Configuration
-        {
-        anyConfigSinceLastInvalidation = true
-        debugLog(.Configuration, ["Computing configuration for", resource])
-        let builder = Configuration.Builder()
-        for entry in configurationEntries
-            where entry.urlMatcher(resource.url)
-            {
-            debugLog(.Configuration, ["Applying", entry, "to", resource])
-            entry.configurer(builder)
-            }
-        return builder.config
-        }
-    
-    private struct ConfigurationEntry: CustomStringConvertible
-        {
-        let description: String
-        let urlMatcher: NSURL -> Bool
-        let configurer: Configuration.Builder -> Void
-        }
-    
-    // MARK: Wiping state
-    
-    /**
-      Wipes the state of this service’s resources. Typically used to handle logout.
-      
-      Applies to resources matching the predicate, or all resources by default.
-    */
-    public final func wipeResources(predicate: Resource -> Bool =  { _ in true })
-        {
-        resourceCache.flushUnused()
-        for resource in resourceCache.values
-            {
-            if predicate(resource)
-                { resource.wipe() }
-            }
-        }
-
-    /**
-      Wipes the state of a subset of this service’s resources, matching based on URLs (instead of `Resource` instances).
-      
-      Useful for making shared predicates that you can pass to both `configure(_:)` and this method.
-    */
-    public final func wipeResourcesMatchingURL(predicate: NSURL -> Bool)
-        {
-        wipeResources { (res: Resource) in predicate(res.url) }
-        }
+        debugLog(.Configuration, ["URL pattern", self, "compiles to regex", pattern.pattern])
+        
+        return { pattern.matches($0.absoluteString) }
+        }
+
+    /// :nodoc:
+    public var configurationPatternDescription: String
+        { return self }
     }
 
+/**
+  Support for passing a specific `Resource` to `Service.configure(...)`.
+*/
+extension Resource: ConfigurationPatternConvertible
+    {
+    /**
+      Matches this specific resource when passed as a pattern to `Service.configure(...)`.
+    */
+    public func configurationPattern(service: Service) -> NSURL -> Bool
+        {
+        let resourceURL = url  // prevent resource capture in closure
+        return { $0 == resourceURL }
+        }
+
+    /// :nodoc:
+    public var configurationPatternDescription: String
+        { return url.absoluteString }
+    }

import Foundation

/**
A set of logically connected RESTful resources, grouped under a base URL.

You will typically create a separate subclass of `Service` for each REST API you use.
*/
@objc(BOSService)
public class Service: NSObject

      - `/foo*/bar` matches `/foo/bar` and `/food/bar`.
    
      The pattern ignores the resource’s query string.
    */
    public func configurationPattern(service: Service) -> NSURL -> Bool
        {
        let prefix = containsRegex("^[a-z]+:")
            ? ""                               // If pattern has a protocol, interpret as absolute URL
            : service.baseURL!.absoluteString  // Pattern is relative to API base
        let resolvedPattern = prefix + stripPrefix("/")
        let pattern = NSRegularExpression.compile(
            NSRegularExpression.escapedPatternForString(resolvedPattern)
                .replaceString("\\*\\*\\/", "([^:?]*/|)")
