{#snippet protectionsPanel(opts: { title: string rules: ReturnType onOpen?: (name?: string) => void editLabel: string manageLabel: string })} {@const onOpen = opts.onOpen} {@const rules = opts.rules}
{opts.title} {#if rules.enforcementUnknown} {rules.readFailed ? 'Could not read the protection rules' : 'Checking protection rules…'} {:else} {#if rules.enforcesDeployBlock}{:else}{/if} Direct edits {rules.enforcesDeployBlock ? 'are blocked' : 'are allowed'} {#if rules.enforcesForkingBlock}{:else}{/if} Forking {rules.enforcesForkingBlock ? 'is blocked' : 'is allowed'} {#if rules.enforcesDeployBlock || rules.enforcesForkingBlock} Workspace admins always bypass these rules. {/if} {#if rules.enforcingRulesets.length > 0}
Enforced by {#each rules.enforcingRulesets as ruleset (ruleset.name)}
{ruleset.name} {#if ruleset.name === DEV_WORKSPACE_LOCK_RULE_NAME} Applied by this pairing {/if}
{#if onOpen} {/if}
{/each}
{/if} {/if} {#if onOpen && rules.enforcingRulesets.length === 0}
{/if}
{/snippet} {#snippet ownDevSection()} {#if pairedDev}

This workspace's {devLabelNoun(pairedDev.label)} is {pairedDev.name} ({pairedDev.id}). Edits to this workspace are redirected there.

{@render protectionsPanel({ title: 'Protections in force on this workspace', rules: ownRules, onOpen: openRulesets, editLabel: 'Edit', manageLabel: 'Manage in Rulesets' })}
{#if pairedDev.isMember || $superadmin} {/if}
{:else if availableAttachLabels.length === 0}

Every environment label is already taken by a dev workspace in this chain, and two carrying the same label would deploy to the same branch. Promote through the existing chain instead.

{:else}

Pair this workspace with a dev workspace: the same code with a different environment (resource and variable values). Edits are made in the dev workspace and promoted here.

Attach an existing workspace as dev