Mirror Staffing & DSSE Signing Plan

Status: APPROVED Version: 1.0.0 Last Updated: 2025-12-06 Owner: Mirror Creator Guild Unblocks: AIRGAP-46-001, DEPLOY-AIRGAP-46-001, AIRGAP-54-001

Currency note (2026-07-11): This is an approved historical implementation plan, not a live CLI runbook. The stella mirror create|sign|verify|pack sequence below is not implemented as described. Current source keeps mirror create discoverable but fails closed with exit code 9 and writes no files. Use stella feedser bundle export or stella mirror seed export for implemented export flows, and see ../mirror/architecture.md plus ../cli/architecture.md for the current boundary.

Executive Summary

This document defines the staffing structure and DSSE (Dead Simple Signing Envelope) signing workflow for the StellaOps Mirror system. It provides the implementation plan required to unblock air-gap bundle creation, signing, and distribution.

1. Staffing Structure

1.1 Mirror Creator Guild Ownership

RoleResponsibilityContact
Guild LeadOverall mirror strategy, release coordinationmirror-guild@stella-ops.org
Bundle EngineerCreate, verify, and publish air-gap bundlesDevOps rotation
Signing AuthorityManage signing keys, approve releasesSecurity Guild delegate
QA ValidatorVerify bundle integrity before publicationQA Guild delegate

1.2 Staffing Resolution (PGMI0101)

The Program Management Initiative PGMI0101 is resolved with the following assignments:

InitiativeAssigneeEffective Date
Mirror bundle creationDevOps Guild (rotation)2025-12-06
DSSE signing authoritySecurity Guild2025-12-06
CLI integrationDevEx/CLI Guild2025-12-06
Offline Kit updatesDeployment Guild2025-12-06

2. DSSE Signing Workflow

2.1 Key Management

┌─────────────────────────────────────────────────────────────────────────────┐
│                         Key Hierarchy                                        │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  Root CA (offline, HSM-backed)                                               │
│  └── Signing CA (intermediate)                                               │
│      ├── mirror-signing-key (ECDSA P-256)                                   │
│      │   └── Used for: bundle.dsse, catalog.dsse                            │
│      ├── attestation-signing-key (ECDSA P-256)                              │
│      │   └── Used for: SBOM attestations, VEX attestations                  │
│      └── dev-signing-key (ECDSA P-256)                                      │
│          └── Used for: development/testing only                             │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

2.2 Key Locations

KeyEnvironmentLocationAccess
Dev signing keyDevelopmenttools/cosign/cosign.dev.keyPublic (password: stellaops-dev)
CI signing keyCI/CDCOSIGN_PRIVATE_KEY_B64 secretGitea CI only
Production keyProductionHSM / VaultSecurity Guild only

2.3 DSSE Envelope Structure

{
  "payloadType": "application/vnd.stellaops.mirror-bundle+json",
  "payload": "<base64-encoded manifest>",
  "signatures": [
    {
      "keyid": "sha256:<fingerprint>",
      "sig": "<base64-encoded signature>"
    }
  ]
}

2.4 Signing Process

# 1. Create bundle manifest
stella mirror create --output bundle/

# 2. Sign the manifest (dev)
stella mirror sign bundle/manifest.json \
  --key tools/cosign/cosign.dev.key \
  --output bundle/manifest.dsse

# 3. Sign the manifest (CI/prod)
stella mirror sign bundle/manifest.json \
  --key env://COSIGN_PRIVATE_KEY_B64 \
  --output bundle/manifest.dsse

# 4. Verify signature
stella mirror verify bundle/manifest.dsse \
  --key tools/cosign/cosign.pub

# 5. Package bundle
stella mirror pack bundle/ --output stellaops-airgap-2025.10.0.tar.gz

3. CI/CD Pipeline

3.1 Gitea Workflow: Mirror Bundle Creation

# .gitea/workflows/mirror-bundle.yml
name: Mirror Bundle
on:
  push:
    tags:
      - 'v*-airgap'
  workflow_dispatch:

jobs:
  create-bundle:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Create air-gap bundle
        run: |
          stella mirror create \
            --images deploy/releases/${{ github.ref_name }}.yaml \
            --output bundle/

      - name: Sign bundle
        env:
          COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY_B64 }}
          COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
        run: |
          stella mirror sign bundle/manifest.json \
            --key env://COSIGN_PRIVATE_KEY \
            --output bundle/manifest.dsse

      - name: Package bundle
        run: |
          stella mirror pack bundle/ \
            --output stellaops-airgap-${{ github.ref_name }}.tar.gz

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: airgap-bundle
          path: stellaops-airgap-*.tar.gz

3.2 Gitea Workflow: Bundle Verification

# .gitea/workflows/mirror-verify.yml
name: Mirror Verify
on:
  workflow_run:
    workflows: ["Mirror Bundle"]
    types: [completed]

jobs:
  verify-bundle:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Download bundle
        uses: actions/download-artifact@v4
        with:
          name: airgap-bundle

      - name: Verify signature
        run: |
          tar xzf stellaops-airgap-*.tar.gz
          stella mirror verify bundle/manifest.dsse \
            --key tools/cosign/cosign.pub

      - name: Verify checksums
        run: |
          stella mirror verify-checksums bundle/

4. Air-Gap Load Script

4.1 Load Script (deploy/airgap/load.sh)

#!/usr/bin/env bash
# StellaOps Air-Gap Bundle Loader
# Usage: ./load.sh <bundle.tar.gz> [registry:port]

set -euo pipefail

BUNDLE="${1:?Bundle path required}"
REGISTRY="${2:-localhost:5000}"

echo "==> Extracting bundle..."
tar xzf "$BUNDLE" -C /tmp/airgap-bundle

echo "==> Verifying signature..."
stella mirror verify /tmp/airgap-bundle/manifest.dsse \
  --key /tmp/airgap-bundle/public-key.pem

echo "==> Loading images to registry..."
for image in /tmp/airgap-bundle/images/*.tar; do
  echo "    Loading $(basename "$image")..."
  docker load -i "$image"

  # Retag for local registry
  original=$(docker inspect --format='{{index .RepoTags 0}}' "$(docker load -i "$image" -q)")
  retagged="${REGISTRY}/$(echo "$original" | cut -d'/' -f2-)"
  docker tag "$original" "$retagged"
  docker push "$retagged"
done

echo "==> Importing advisory data..."
stella concelier import /tmp/airgap-bundle/advisories/

echo "==> Done! Registry: $REGISTRY"

5. Offline Kit Integration

5.1 Bundle Contents

stellaops-airgap-2025.10.0/
├── manifest.json              # Bundle manifest
├── manifest.dsse              # DSSE-signed manifest
├── public-key.pem             # Verification key
├── SHA256SUMS                 # Checksums
├── SHA256SUMS.sig             # Signed checksums
├── images/                    # Container images
│   ├── authority-v2025.10.0.tar
│   ├── concelier-v2025.10.0.tar
│   ├── scanner-web-v2025.10.0.tar
│   ├── scanner-worker-v2025.10.0.tar
│   └── ...
├── advisories/                # Advisory data
│   ├── nvd-2025-12-01.json.gz
│   ├── ghsa-2025-12-01.json.gz
│   └── ...
├── scripts/
│   ├── load.sh                # Registry loader
│   ├── verify.sh              # Verification script
│   └── update.sh              # Incremental update
└── docs/
    ├── INSTALL.md             # Installation guide
    ├── VERIFY.md              # Verification guide
    └── TROUBLESHOOT.md        # Troubleshooting

6. Tasks Unblocked

This plan unblocks:

Task IDDescriptionStatus
AIRGAP-46-001Mirror staffing + DSSE plan✅ UNBLOCKED
DEPLOY-AIRGAP-46-001Air-gap load scripts✅ UNBLOCKED
AIRGAP-54-001Exporter/AirGap/CLI coordination✅ UNBLOCKED
DEVPORT-64-002DevPortal Offline (already DONE)✅ N/A

7. Changelog

DateVersionChange
2025-12-061.0.0Initial plan with staffing, DSSE workflow, CI/CD pipelines