> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. # Task Pack Specification (Sprint 43 Draft) The Task Pack specification defines a deterministic, auditable format that enables operators to encode multi-step maintenance, validation, and deployment workflows. Packs are executed by the Task Runner service, distributed through the Packs Registry, and invoked via the StellaOps CLI (`stella pack ...`) or Orchestrator integrations. --- ## 1 · Goals & Scope - **Deterministic execution.** Identical inputs yield identical run graphs, output manifests, and evidence bundles across environments (online, sealed, or offline). - **Secure-by-default.** Pack metadata must capture provenance, signatures, RBAC requirements, and secret usage; execution enforces tenant scopes and approvals. - **Portable.** Packs are distributed as signed OCI artifacts or tarballs that work in connected and air-gapped deployments, including Offline Kit mirrors. - **Composable.** Packs can reference reusable steps, expressions, and shared libraries without sacrificing determinism or auditability. Non-goals: full-blown workflow orchestration, unbounded scripting, or remote code injection. All logic is declarative and constrained to Task Runner capabilities. --- ## 2 · Terminology | Term | Definition | |------|------------| | **Pack manifest** | Primary YAML document (`pack.yaml`) describing metadata, inputs, steps, policies, and evidence expectations. | | **Step** | Atomic unit of work executed by Task Runner (e.g., command, API call, policy gate, approval). Steps can be sequential or parallel. | | **Expression** | Deterministic evaluation (JMESPath-like) used for branching, templating, and conditionals. | | **Policy gate** | Declarative rule that blocks execution until conditions are met (e.g., approval recorded, external signal received). | | **Artifact** | File, JSON blob, or OCI object produced by a step, referenced in manifests and evidence bundles. | | **Pack bundle** | Distribution archive (`.stella-pack.tgz` or OCI ref) containing manifest, assets, schemas, and provenance metadata. | --- ## 3 · Pack Layout ``` my-pack/ ├─ pack.yaml # Required manifest ├─ assets/ # Optional static assets (scripts, templates) ├─ schemas/ # JSON schemas for inputs/outputs ├─ docs/ # Markdown docs rendered in Console/CLI help ├─ provenance/ # DSSE statements, SBOM, attestations └─ README.md # Author-facing summary (optional) ``` Publishing via Packs Registry or OCI ensures the directory is canonical and hashed. --- ## 4 · Manifest Schema (v1.0) ```yaml apiVersion: stellaops.io/pack.v1 kind: TaskPack metadata: name: sbom-remediation version: 1.3.0 description: > Audit SBOM drift, quiet high-risk findings, and export mitigation evidence. tags: [sbom, remediation, policy] tenantVisibility: ["west-prod", "east-stage"] # optional allowlist maintainers: - name: Jane Doe email: jane@example.com license: AGPL-3.0-or-later annotations: imposedRuleReminder: true spec: inputs: - name: sbomBundle type: object schema: schemas/sbom-bundle.schema.json required: true - name: dryRun type: boolean default: false secrets: - name: jiraToken scope: packs.run # Authority scope required description: Optional token for ticket automation approvals: - id: security-review grants: ["packs.approve"] expiresAfter: PT4H reasonTemplate: "Approve remediation for SBOM {{ inputs.sbomBundle.metadata.image }}" steps: - id: validate-input run: uses: builtin:validate-schema with: target: "{{ inputs.sbomBundle }}" schema: schemas/sbom-bundle.schema.json - id: plan-remediation when: "{{ not inputs.dryRun }}" run: uses: builtin:policy-simulate with: sbom: "{{ inputs.sbomBundle }}" policy: "policies/remediation.yaml" - id: approval-gate gate: approval: security-review message: "Security must approve remediation before changes apply." - id: apply-remediation run: uses: builtin:cli-command with: command: ["stella", "policy", "promote", "--from-pack"] - id: export-evidence run: uses: builtin:evidence-export with: includeArtifacts: ["{{ steps.plan-remediation.outputs.planPath }}"] outputs: - name: evidenceBundle type: file path: "{{ steps.export-evidence.outputs.bundlePath }}" success: message: "Remediation applied; evidence bundle ready." failure: retries: maxAttempts: 1 backoffSeconds: 0 message: "Remediation failed; see evidence bundle for context." ``` ### 4.1 Field Summary | Field | Description | Requirements | |-------|-------------|--------------| | `metadata` | Human-facing metadata; used for registry listings and RBAC hints. | `name` (DNS-1123), `version` (SemVer), `description` ≤ 2048 chars. | | `spec.inputs` | Declarative inputs validated at plan time. | Must include type; custom schema optional but recommended. | | `spec.secrets` | Secrets requested at runtime; never stored in pack bundle. | Each secret references Authority scope; CLI prompts or injects from profiles. | | `spec.approvals` | Named approval gates with required grants and TTL. | ID unique per pack; `grants` map to Authority roles. Approval metadata (`runId`, `gateId`, `planHash`) feeds Authority’s `pack_run_id`/`pack_gate_id`/`pack_plan_hash` parameters (see `docs/task-packs/runbook.md#4-approvals-workflow`). | | `spec.steps` | Execution graph; each step is `run`, `gate`, `parallel`, or `map`. | Steps must declare deterministic `uses` module and `id`. | | `spec.outputs` | Declared artifacts for downstream automation. | `type` can be `file`, `object`, or `url`; path/expression required. | | `success` / `failure` | Messages + retry policy. | `failure.retries.maxAttempts` + `backoffSeconds` default to 0. | --- ## 5 · Step Types | Type | Schema | Notes | |------|--------|-------| | `run` | Executes a built-in module (`builtin:*`) or registry-provided module. | Modules must be deterministic, side-effect constrained, and versioned. | | `parallel` | Executes sub-steps concurrently; `maxParallel` optional. | Results aggregated; failures trigger abort unless `continueOnError`. | | `map` | Iterates over deterministic list; each iteration spawns sub-step. | Sequence derived from expression result; ordering stable. | | `gate.approval` | Blocks until approval recorded with required grants. | Supports `autoExpire` to cancel run on timeout. | | `gate.policy` | Calls Policy Engine to ensure criteria met (e.g., no critical findings). | Fails run if gate not satisfied. | `when` expressions must be pure (no side effects) and rely only on declared inputs or prior outputs. --- ## 6 · Determinism & Validation 1. **Plan phase** (`stella pack plan`, `TaskRunner.Plan` API) parses manifest, resolves expressions, validates schemas, and emits canonical graph with hash. 2. **Simulation** compares plan vs dry-run results, capturing differences in `planDiff`. Required for approvals in sealed environments. 3. **Execution** uses plan hash to ensure runtime graph matches simulation. Divergence aborts run. 4. **Evidence**: Task Runner emits DSSE attestation referencing plan hash, input digests, and output artifacts. Validation pipeline: ```text pack.yaml ──▶ schema validation ──▶ expression audit ──▶ determinism guard ──▶ signing ``` Packs must pass CLI validation before publishing. ### 6.1 · TP Gap Remediation (2025-12) - **Canonical plan hash (TP1):** Compute `plan.hash` as `sha256:<64-hex>` over canonical JSON (`plan.canonicalPlanPath`) with sorted keys and normalized numbers/booleans. The canonical plan file ships in offline bundles. - **Inputs lock (TP2):** CLI emits `inputs.lock` capturing resolved inputs and redacted secret placeholders; hashed via `hashes[]` and included in evidence bundles. - **Approval ledger DSSE (TP3):** Approval responses are DSSE-signed ledgers embedding `runId`, `gateId`, `planHash`, and tenant context; Task Runner rejects approvals without matching plan hash. - **Secret redaction (TP4):** `security.secretsRedactionPolicy` defines hashing/redaction for secrets and PII; transcripts/evidence must reference this policy. - **Deterministic RNG/time (TP5):** RNG seed is derived from `plan.hash`; timestamps use UTC ISO-8601; log ordering is monotonic. - **Sandbox + egress quotas (TP6):** Packs declare `sandbox.mode`, explicit `egressAllowlist`, CPU/memory limits, and optional `quotaSeconds`; missing fields cause fail-closed refusal. - **Registry signing + revocation (TP7):** Bundles carry SBOM + DSSE envelopes and reference a revocation list enforced during registry import. - **Offline bundle schema + verifier (TP8):** Offline exports must satisfy `docs/task-packs/packs-offline-bundle.schema.json` and pass `scripts/packs/verify_offline_bundle.py --require-dsse`. - **SLO + alerting (TP9):** Manifests declare `slo.runP95Seconds`, `slo.approvalP95Seconds`, `slo.maxQueueDepth`, and optional `slo.alertRules`; telemetry enforces and alerts on breaches. - **Fail-closed gates (TP10):** Approval/policy/timeline gates fail closed when DSSE, hash entries, or quotas are missing/expired; CLI surfaces remediation hints. - **Approval ledger schema:** Approval decisions must conform to `docs/task-packs/approvals-ledger.schema.json`; planHash is `sha256:<64-hex>` and DSSE envelopes must reference ledger digest. --- ## 7 · Signatures & Provenance - Pack bundles are signed with **cosign** (keyless Fulcio/KMS supported) and optionally DSSE envelopes. - `provenance/` directory stores signed statements (SLSA Build L1+) linking source repo, CI run, and manifest hash. - Registry verifies signatures on push/pull; Task Runner refuses unsigned packs unless in development mode. - Attestations include: - Pack manifest digest (`sha256`) - Pack bundle digest - Build metadata (`git.ref`, `ci.workflow`, `cli.version`) --- ## 8 · RBAC & Scopes Authority scopes introduced by `AUTH-PACKS-41-001`: | Scope | Purpose | |-------|---------| | `packs.read` | Discover packs, download manifests. | | `packs.write` | Publish/update packs in registry (requires signature). | | `packs.run` | Execute packs via CLI/Task Runner. | | `packs.approve` | Fulfil approval gates defined in packs. | Task Runner enforces scopes per tenant; pack metadata may further restrict tenant visibility (`metadata.tenantVisibility`). --- ## 9 · Observability & Evidence - Metrics: `pack_run_duration_seconds`, `pack_step_retry_total`, `pack_gate_wait_seconds`. - Logs: Structured JSON per step with scrubbed inputs (`secretMask` applied). - Timeline events: `pack.started`, `pack.approval.requested`, `pack.approval.granted`, `pack.completed`. - Evidence bundle includes: - Plan manifest (canonical JSON) - Step transcripts (redacted) - Artifacts manifest (sha256, size) - Attestations references --- ## 10 · Compatibility Matrix | CLI Version | Pack API | Task Runner | Notes | |-------------|----------|-------------|-------| | 2025.10.x | `pack.v1` | Runner build `>=2025.10.0` | Approvals optional, loops disabled. | | 2025.12.x | `pack.v1` | Runner build `>=2025.12.0` | Approvals resume, secrets injection, localization strings. | | Future | `pack.v2` | TBD | Will introduce typed outputs & partial replay (track in Epic 13). | CLI enforces compatibility: running pack with unsupported features yields `ERR_PACK_UNSUPPORTED`. --- ## 11 · Publishing Workflow 1. Author pack (`pack.yaml`, assets, docs). 2. Run `stella pack validate` (schema + determinism). 3. Generate bundle: `stella pack build --output my-pack.stella-pack.tgz`. 4. Sign: `cosign sign-blob my-pack.stella-pack.tgz`. 5. Publish: `stella pack push registry.example.com/org/my-pack:1.3.0`. 6. Registry verifies signature, records provenance, and exposes pack via API. --- ## 12 · Compliance Checklist - [ ] Manifest schema documented for all fields, including approvals, secrets, and outputs. - [ ] Determinism requirements outlined with plan/simulate semantics and CLI validation steps. - [ ] Signing + provenance expectations spelled out with cosign/DSSE references. - [ ] RBAC scopes (`packs.*`) and tenant visibility rules captured. - [ ] Observability (metrics, logs, evidence) described for Task Runner integrations. - [ ] Compatibility matrix enumerates CLI/Runner requirements. - [ ] Publishing workflow documented with CLI commands. - [ ] Imposed rule reminder included at top of document. --- *Last updated: 2025-12-05 (Sprint 0157-0001-0001 TaskRunner I).*