"You don't open a repository. You open the thing a repository produces — if it produces one."
Member and Surface Are Different Nouns
It's tempting to think 'the family is a list of repos, and launching means opening a repo.' Firelink refuses that shortcut. A FamilyMember is a repository or product identity; it owns zero or more LaunchSurface objects, where a surface is an actual user-facing thing the member produces — a WebUI, a native app. The launcher opens surfaces, never repository internals. Examples read cleanly: a Pippa WebUI surface, a Firekeeper menu-bar-app surface, an Ember engine-UI surface. The repo is the member; the openable thing is the surface.
Some Members Have No Surface at All
This distinction earns its keep at the edges. A shared kit or a workshop repository might produce nothing you can launch — it's a library other siblings vendor, or a batch tool with no server. Firelink still shows that member in the Web Hub (it exists, it has Git state, it matters), but it does not invent a fake launcher target for it. No phantom 'Open' button that does nothing. If a member has no surface, the launcher simply has nothing to offer for it, and that's the honest answer.
'Open' Is Context-Aware, Never Blind
Because a surface is a real thing and not just a URL string, opening it is context-aware. The same web surface resolves to localhost on the office loopback, to a LAN address on the local network, and to a Tailscale HTTPS address from the tailnet. There is deliberately no context-blind 'primary' URL that the UI falls back to — a link rendered on a card follows the same client-aware resolver as the main Open action. The surface knows how to be reached from wherever you are, instead of pretending one address works everywhere.