Skip to content

Add workshop connect --all for bulk review-and-connect of compatible plugs and slots #1114

Open

Description

@tlm

Summary

Users with many interfaces to wire up must run workshop connect once per pair. A user with 18 secrets currently needs 18 separate workshop connect invocations.

Propose a bulk mode:

workshop connect --all [--interface <INTERFACE>] [<WORKSHOP>] [--yes]

It discovers unconnected plugs and compatible slots, proposes safe
pairings grouped by interface, prints the proposal for review, and connects
them only after explicit confirmation. --yes/-y skips the prompt for
scripts.

The approved proposal is a fixed snapshot. The command applies exactly
that set of connections or fails without applying any of them.

Motivation

This issue was originally reported by @PietroPasotti,
whose use case requires around 18 secrets to be supplied to a workshop.

The secret interface is the motivating case. Secrets are deliberately
never auto-connected, and the workshop definition's connections: list is
also subject to the auto-connection policy, so it cannot wire secrets
either. workshop connect is therefore the only route, and a user with 18
secrets has to repeat it 18 times.

The problem is general: any interface with many disconnected plugs and
slots has the same ergonomics issue.

Current behaviour

  • workshop connect connects exactly one plug to one optional slot.
  • workshop connections can list disconnected plugs and slots, but does
    not propose pairings.

Proposed user experience

Command shape

workshop connect --all [--interface <INTERFACE>] [<WORKSHOP>] [--yes]
  • --all selects bulk mode.
  • --interface <INTERFACE> limits the proposal to that interface. Without
    it, all eligible interfaces are considered.
  • As elsewhere in workshop, omitting <WORKSHOP> uses the default
    workshop; supplying a name targets that workshop.
  • --all cannot be combined with explicit plug/slot arguments.
  • --yes/-y is only valid with --all.

Review output

Group the proposal by interface, because interface is the compatibility
and policy boundary. This makes a bulk operation easy to reason about, and
in the motivating case collapses all 18 secret connections into one visible
block. Order interfaces alphabetically, then order rows within each group
by plug endpoint and slot.

$ workshop connect --all myworkshop
secret
  PLUG                            SLOT                            NOTES
  myworkshop/api:aws-access-key   myworkshop/system:aws-access-key  attributes: service=aws
  myworkshop/api:github-token     myworkshop/system:github-token    attributes: service=github
  ...
  myworkshop/web:stripe-secret    myworkshop/system:stripe-secret   attributes: service=stripe

mount
  PLUG                            SLOT                            NOTES
  myworkshop/go:mod-cache         myworkshop/system:mod-cache       -

18 connections proposed (17 secret, 1 mount).

Not proposed:
  secret
    myworkshop/db:credentials
      no exact-name slot; 2 secret slots match. Connect explicitly with:
      workshop connect myworkshop/db:credentials myworkshop/system:<SLOT>

Connect these 18 connections? [y/N]: y

Connected 18 connections in workshop "myworkshop" (17 secret, 1 mount).

Notes on the presentation:

  • Showing slot lookup attributes for secrets lets users verify the
    intended keyring item. Never show secret values.
  • Only selected pairs are shown, never the full plug/slot cross-product.
  • Ambiguous or unmatched endpoints are listed separately so users know
    what was deliberately skipped.
  • After the command finishes, print a short summary of what was connected.

Pairing rules

A candidate relationship exists when:

  • Plug and slot are in the same project and workshop.
  • Plug and slot use the same interface.
  • The plug has no existing connections.
  • The pair is not already connected and is not explicitly undesired/denied.
  • The manual connection policy permits the pair, not the auto-connection
    policy.
  • Interface-specific validation is satisfied.

Selection rules:

  1. If a slot has the same name as the plug, select it.
  2. Otherwise, if exactly one compatible slot exists, select it.
  3. Otherwise, leave the plug unpaired and report why (zero or multiple
    candidates).
  4. Never guess when there are multiple candidates. This is essential for
    secrets, where many plugs and slots share the same interface.
  5. One plug may be connected to at most one slot. Multiple plugs may share
    a slot.
  6. Bound plug groups are treated as one unit: propose the master only and
    report bound plugs as covered by it.

Safety and confirmation

  • Print the full plan before making any change.
  • Default answer is No; only y or yes proceeds.
  • Declining the prompt makes no changes and exits non-zero.
  • If stdin is not a terminal and --yes was not supplied, fail with a
    clear message rather than hanging or silently proceeding. Scripts must
    opt in explicitly.
  • --yes skips the prompt but should still print the plan so it is
    captured in logs.
  • Re-running --all should be idempotent: only still-unconnected pairs are
    proposed.
  • Consider documenting that --yes is convenient but loses the review
    step, especially when secrets are involved.

Proposal snapshot and all-or-nothing behaviour

Once the proposal has been shown, exactly that proposal is what the
command attempts to connect. It must never silently add, drop, or replace
entries.

Before applying the plan, revalidate the whole proposal against the
current state. Abort the entire operation if any proposed pair is no
longer valid, for example because:

  • A proposed plug is now connected to a different slot.
  • A proposed plug or slot no longer exists.
  • A plug or slot definition changed, including after a workshop refresh.
  • The workshop was refreshed, stopped, or removed such that the pair can
    no longer be connected.
  • The interface or connection policy changed so the pair is no longer
    permitted.
  • The workshop's connections changed in any other way that means the
    original pair cannot be satisfied.

If any part of the proposal is invalid, no connections from the plan are
made, the whole operation fails, and the command exits non-zero.

New candidates that appear after the proposal is displayed are ignored.
The user approved a specific list, so new pairs must not be added to it.

The approved plan must also be applied as a single unit. The command must
not report success unless every proposed connection was applied. If any
connection in the plan cannot be applied, the operation fails as a whole
and the command exits non-zero.

On failure, report what invalidated the plan so the user can review the
new state and run the command again:

$ workshop connect --all myworkshop
  ...
Connect these 18 connections? [y/N]: y

Error: the proposed connections are no longer valid; no connections were made.
  myworkshop/api:github-token: plug is now connected to myworkshop/system:old-token
  myworkshop/db:credentials: slot "credentials" was removed after a refresh

On success, print a short summary of the exact set connected:

Connected 18 connections in workshop "myworkshop" (17 secret, 1 mount).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions